payloadcms / payloadcms/payload

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

Open
#16,401 0 comments 0 reactions 1 assignee View on GitHub

@r1tsuu is already working on this.

Since May 4, 2026.

v3
Dominant language
TypeScript
Stars
44.8k
Forks
4.2k
Avg merge
2d 21h
Merged PRs (30d)
53

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.