# Security Considerations for Using interpolateParams with Multi-Byte Character Encodings

> Discover security risks of interpolateParams with multi-byte encodings like UTF8MB4. Learn how go-sql-driver/mysql prevents SQL injection with a deny-list.

- Repository: [Go SQL Drivers/mysql](https://github.com/go-sql-driver/mysql)
- Tags: tutorial
- Published: 2026-03-02

---

**Enabling `interpolateParams` with certain multi-byte MySQL collations like GBK or BIG5 creates SQL injection risks due to trailing backslash bytes (0x5c), but the driver blocks unsafe combinations at DSN parse time via a hard-coded deny-list.**

The `go-sql-driver/mysql` driver optimizes query execution by offering `interpolateParams`, a mode that substitutes `?` placeholders with literal values before transmission to eliminate prepared-statement round-trips. When working with multi-byte character encodings such as **UTF8MB4**, developers must understand the specific security boundaries enforced in [`collations.go`](https://github.com/go-sql-driver/mysql/blob/main/collations.go) and [`dsn.go`](https://github.com/go-sql-driver/mysql/blob/main/dsn.go) to prevent SQL injection vulnerabilities arising from ambiguous byte sequences.

## The SQL Injection Risk of Multi-Byte Trailing Bytes

When `interpolateParams` is enabled, the driver assumes responsibility for quoting and escaping parameter values that would normally be handled by the MySQL server. The driver builds the final query string by writing literals for simple Go types and enclosing `[]byte` or `json.RawMessage` values in quotes before applying byte-level escaping.

The critical vulnerability arises with multi-byte character sets like **GBK**, **BIG5**, and **SJIS**, where a valid character’s trailing byte can equal `0x5c`—the ASCII backslash character. In [`connection.go`](https://github.com/go-sql-driver/mysql/blob/main/connection.go), the driver’s `escapeBytesBackslash` function (used by default) escapes special characters by prepending backslashes. If a multi-byte character’s trailing byte is a backslash, the escaping logic could misinterpret it as an escape sequence rather than part of a character, breaking the quoting boundary and allowing attacker-controlled payloads to bypass sanitization.

## Built-In Protection: The unsafeCollations Deny-List

To mitigate this vector, the driver maintains a static deny-list of unsafe collations in [`collations.go`](https://github.com/go-sql-driver/mysql/blob/main/collations.go) (lines 251–260). This map explicitly flags encodings known to produce `0x5c` trailing bytes:

```go
// collations.go – unsafeCollations map
var unsafeCollations = map[string]bool{
    "big5_chinese_ci": true,
    "sjis_japanese_ci": true,
    "gbk_chinese_ci": true,
    // … (other unsafe collations) …
}

```

During DSN parsing, the `Config.normalize` method in [`dsn.go`](https://github.com/go-sql-driver/mysql/blob/main/dsn.go) validates the requested collation against this list when `interpolateParams` is enabled:

```go
// dsn.go – part of Config.normalize
if cfg.InterpolateParams && cfg.Collation != "" && unsafeCollations[cfg.Collation] {
    return errInvalidDSNUnsafeCollation
}

```

If an unsafe collation is detected, the driver aborts initialization with `errInvalidDSNUnsafeCollation`, preemptively blocking the connection before any query interpolation occurs.

## How Client-Side Escaping Works for Safe Collations

For permitted collations such as `utf8mb4_general_ci`, the `interpolateParams` implementation in [`connection.go`](https://github.com/go-sql-driver/mysql/blob/main/connection.go) (lines 48–88) handles parameter substitution. The driver selects an escaping strategy based on the server’s `statusNoBackslashEscapes` flag:

- **Standard mode**: Uses `escapeBytesBackslash` to prefix special characters with backslashes.
- **No-backslash mode**: When the server reports `statusNoBackslashEscapes`, the driver switches to `escapeBytesQuotes`, escaping single quotes by doubling them rather than using backslashes.

This adaptive logic prevents double-escaping errors, but the underlying safety guarantee remains the collation validation performed during DSN setup.

## Configuration Examples: Safe vs. Unsafe Usage

The following examples demonstrate correct and incorrect configurations according to the driver’s source code validation.

**Safe usage with UTF8MB4 (permitted)**

```go
import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

func main() {
    // DSN enables interpolation and uses a safe collation
    dsn := "user:pass@tcp(localhost:3306)/testdb?interpolateParams=true&collation=utf8mb4_general_ci"
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        panic(err)
    }
    // The driver will replace the placeholder safely
    rows, err := db.Query("SELECT * FROM users WHERE id = ?", 42)
    _ = rows
}

```

Because `utf8mb4_general_ci` is absent from `unsafeCollations`, `Config.normalize` permits the connection and `interpolateParams` executes using the escaping logic defined in [`connection.go`](https://github.com/go-sql-driver/mysql/blob/main/connection.go).

**Unsafe collation triggers fatal error**

```go
dsn := "user:pass@tcp(localhost:3306)/testdb?interpolateParams=true&collation=gbk_chinese_ci"
db, err := sql.Open("mysql", dsn)
if err != nil {
    // err == errInvalidDSNUnsafeCollation
    fmt.Println("Interpolation disabled due to unsafe collation")
}

```

Here, `gbk_chinese_ci` matches an entry in the `unsafeCollations` map, causing [`dsn.go`](https://github.com/go-sql-driver/mysql/blob/main/dsn.go) to return `errInvalidDSNUnsafeCollation` and prevent the connection from opening.

## Summary

- The driver maintains an `unsafeCollations` deny-list in [`collations.go`](https://github.com/go-sql-driver/mysql/blob/main/collations.go) (lines 251–260) that blocks GBK, BIG5, SJIS, and other encodings producing ambiguous `0x5c` trailing bytes.
- When `interpolateParams=true` is set with an unsafe collation, `Config.normalize` in [`dsn.go`](https://github.com/go-sql-driver/mysql/blob/main/dsn.go) returns `errInvalidDSNUnsafeCollation` and refuses the connection.
- For safe collations like `utf8mb4_general_ci`, the driver escapes parameters using either `escapeBytesBackslash` or `escapeBytesQuotes` (based on the server's `statusNoBackslashEscapes` flag) as implemented in [`connection.go`](https://github.com/go-sql-driver/mysql/blob/main/connection.go).
- Never bypass the collation validation by modifying driver source; instead, use UTF8MB4 variants or disable `interpolateParams` when working with legacy multi-byte encodings.

## Frequently Asked Questions

### Can I use interpolateParams with UTF8MB4 safely?

Yes. UTF8MB4 collations such as `utf8mb4_general_ci` and `utf8mb4_unicode_ci` are not present in the `unsafeCollations` map. According to the `go-sql-driver/mysql` source code, the driver permits interpolation with these encodings because they do not produce ambiguous trailing backslash bytes that could break the `escapeBytesBackslash` logic.

### What happens if I try to use GBK with interpolateParams enabled?

The DSN parser in [`dsn.go`](https://github.com/go-sql-driver/mysql/blob/main/dsn.go) detects the conflict during `Config.normalize` and returns `errInvalidDSNUnsafeCollation`. The connection fails to open, preventing potential injection vectors that could arise from misinterpreted escape sequences when the driver processes byte slices containing multi-byte characters.

### Does the server-side NO_BACKSLASH_ESCAPES flag affect security?

The driver adapts its escaping strategy in [`connection.go`](https://github.com/go-sql-driver/mysql/blob/main/connection.go) by switching from `escapeBytesBackslash` to `escapeBytesQuotes` when the server reports `statusNoBackslashEscapes`. While this prevents double-escaping, it does not override the collation safety check; unsafe collations remain blocked regardless of server flags because the vulnerability stems from byte interpretation, not escape method.

### Is client-side interpolation faster than server-side prepared statements?

Yes, `interpolateParams` eliminates a network round-trip for the prepare and execute phases. However, this performance gain is only safe when the driver validates the collation against the `unsafeCollations` deny-list in [`collations.go`](https://github.com/go-sql-driver/mysql/blob/main/collations.go). Attempting to force interpolation with blocked encodings removes the server’s safeguards without providing the driver’s compensating controls, exposing the application to SQL injection.