Skip to content

SAFE_STRING_REGEX in escapeSQLValue rejects all non-ASCII characters, breaking JSON field queries with Unicode values #16401

@smoothdvd

Description

@smoothdvd

Describe the Bug

@payloadcms/drizzle rejects any JSON-field where query whose value contains non-ASCII characters (CJK, accented Latin, emoji,
etc.). The validation regex in src/utilities/escapeSQLValue.ts is:

export const SAFE_STRING_REGEX = /^[\w @.-+:]*$/

\w is ASCII-only ([A-Za-z0-9_]), so any string containing characters like 中, é, ü, あ, ñ, etc. fails the test and throws:
APIError: is not allowed as a JSON query value (status 400)

This is called from two paths:

  • dist/queries/parseParams.js:152,154 — applies to every JSON-field query operator (equals, like, in, contains, etc.) across
    both Postgres and SQLite adapters. - dist/postgres/createJSONQuery/index.js:23 and dist/sqlite/createJSONQuery/index.js.

For any project with internationalized data stored in a JSON / json / jsonb column, this makes JSON queries effectively unusable. We hit this on a Chinese-language deployment and have to ship a patch (patches/@payloadcms__drizzle@3.84.1.patch)
replacing the regex with a Unicode-aware version:

export const SAFE_STRING_REGEX = /^[\p{L}\p{N}\s@.-+:_]*$/u

\p{L} (any Unicode letter) and \p{N} (any Unicode number) with the /u flag still block SQL metacharacters (', ;, --, (, ), =, /,
, etc.) so the injection-prevention intent is preserved while allowing legitimate international text.

Expected behavior: JSON-field queries with non-ASCII values should succeed when the value contains only
letters/digits/whitespace and the existing safe punctuation set.

Actual behavior: Any non-ASCII letter or digit causes the query to throw a 400 APIError.

Link to the code that reproduces this issue

https://github.com/smoothdvd/payload-issues

Reproduction Steps

  1. Create a Payload project with the Postgres adapter (@payloadcms/db-postgres) and a collection containing a json field, e.g.:

// collections/Items.ts
import type { CollectionConfig } from 'payload'
export const Items: CollectionConfig = {
slug: 'items',
fields: [
{ name: 'meta', type: 'json' },
],
}
2. Seed a document:

await payload.create({
collection: 'items',
data: { meta: { title: '你好世界' } },
})
3. Query the JSON field with a non-ASCII value:

await payload.find({
collection: 'items',
where: { 'meta.title': { equals: '你好世界' } },
})
4. Observe the request throws:

APIError: 你好世界 is not allowed as a JSON query value
at escapeSQLValue (node_modules/@payloadcms/drizzle/dist/utilities/escapeSQLValue.js:14)

  1. The same failure occurs with like, contains, in, etc., and with any Unicode letter (café, naïve, Größe, 日本語, 한국어, …).

Environment

  • payload@3.84.1
  • @payloadcms/drizzle@3.84.1
  • @payloadcms/db-postgres@3.84.1
  • Node 20.x, PostgreSQL 16

Suggested fix
Swap the regex for the Unicode-aware variant shown above (or equivalent), and add a test covering CJK / accented input on JSON
queries.

Which area(s) are affected?

Not sure

Environment Info

Binaries:
  Node: 22.22.2
  npm: 10.9.7
  Yarn: N/A
  pnpm: 10.33.2
Relevant Packages:
  payload: 3.84.1
Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.4.0: Thu Mar 19 19:31:09 PDT 2026; root:xnu-12377.101.15~1/RELEASE_ARM64_T8132
  Available memory (MB): 16384
  Available CPU cores: 10

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: needs-triagePossible bug which hasn't been reproduced yetv3

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions