Skip to content

fix(security): standard quotes and block IN operator validate - #3862

Merged
farnabaz merged 2 commits into
mainfrom
sec/allow-list-bypasses
Oct 1, 2026
Merged

farnabaz merged 2 commits into
mainfrom
sec/allow-list-bypasses

Conversation

@farnabaz

@farnabaz farnabaz commented Oct 1, 2026

Copy link
Copy Markdown
Member

This PR tackles with two issue:


The WHERE validator only blocked function calls and some SQL keywords.
SQLite accepts other forms that the query builder never produces, and
they could be abused:

  • x IN table_name is an implicit subquery. It also accepts eponymous
    table-valued pragmas, so 'ok' IN pragma_integrity_check ran a full
    integrity check for every term. A balanced AND tree of these
    blocked the Node worker for tens of seconds per request. The same
    form could also check for values in other tables.
  • Infix operators such as REGEXP (registered by libsql), GLOB and MATCH
    passed because they contain no name( call.
  • Operators made of symbols (||, ->>, arithmetic) passed too,
    because they contain no letters.

After quoted strings and identifiers are removed, the WHERE clause must
now meet three rules:

  • IN must be followed by a parenthesised list
  • only the builder's keywords may appear unquoted (WHERE, AND, OR,
    NOT, IN, LIKE, BETWEEN, IS, NULL)
  • only word characters, whitespace, (, ), ,, =, < and >
    may appear

Each rule is a single pass over the query. Unquoted column names in
WHERE are now rejected; the query builder always quotes them, so
queryCollection() output is unaffected.

Refs: VULN-14102


cleanupQuery() removed [...] and ... regions before checking WHERE
for SELECT and other banned words, because SQLite accepts them as
identifier quotes. PostgreSQL has neither: [...] is an array subscript
that runs whatever it contains. On the postgresql and pglite adapters,
a payload like

WHERE ("meta"[(SELECT CASE WHEN THEN 1 ELSE 2 END)] IS NULL)

therefore hid a sub-select from the check and gave an unauthenticated
blind boolean oracle over the whole database. This was a regression
from #3819 (3.15.2).

That check now removes only the quote styles the query builder emits
('value' and "field"). Any [ or backtick left outside them is rejected
on every adapter. Brackets and backticks inside value strings and
quoted field names are still allowed.

Refs: VULN-14510

@vercel

vercel Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
content Ready Ready Preview Oct 1, 2026 9:57am UTC

Request Review

@pkg-pr-new

pkg-pr-new Bot commented Oct 1, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/@nuxt/content@3862

commit: c7bd82c

@coderabbitai

coderabbitai Bot commented Oct 1, 2026

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: fbbe1400-6f66-4b63-a366-dbd498f58f08

📥 Commits

Reviewing files that changed from the base of the PR and between 75eff79 and c7bd82c.

📒 Files selected for processing (2)
  • src/runtime/internal/security.ts
  • test/unit/assertSafeQuery.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

assertSafeQuery now checks WHERE clauses for unsupported characters and operators, invalid IN forms, and bare words outside an allowed keyword set. Its cleanup step can preserve backticks and brackets for validation while continuing to handle single- and double-quoted strings. Unit tests cover accepted and rejected query forms, including a large nested-condition case.

Priority: ⬆️ High

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to c7bd8

No actionable blocker is established. The change intentionally rejects unsupported WHERE syntax; merge after normal checks pass.

Security Architecture Review

Security architecture risk: 🔵 Low · up to c7bd8

The change narrows accepted SQL and preserves validation before database execution. No introduced or worsened security issue was established. Deployment-specific authentication, collection access controls, and database privileges remain unconfirmed.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — If callers can reach this route, they control SQL and select the collection used for table binding. Execution uses the configured adapter without a request identity argument. Effective exposure, database authority, and cross-tenant isolation cannot be determined from the observed handler; no expansion of those privileges was established by this PR.

Security Findings and Attack Paths

  • observed — The PR adds rejection rules and corresponding assertions for implicit table/pragma membership, REGEXP/GLOB/MATCH, symbolic expressions, and array-subscript subqueries. These address previously admitted syntax; no new or worsened attack path was established, and deployed exploitability remains unconfirmed.

Trust Boundaries and Controls

  • observed — The validator bounds statement length, rejects comments and invalid SELECT structure, binds the FROM table to the requested collection, and checks WHERE expressions before execution. Table binding is syntactic containment, not caller authorization. No route-local authentication or collection-permission check is visible; this predates the PR and upstream enforcement remains unknown.

Resilience and Maintainability Implications

  • inferred — The added checks narrow admission before the existing integrity/import and query-execution steps. They introduce no new state-transition sequence, retry, or recovery path; the security benefit is rejecting these unsupported expressions before downstream work begins.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the security fix, standard quote handling, and IN operator validation. It summarizes the main changes, despite minor grammatical awkwardness.
Description check ✅ Passed The description directly explains both security issues, the validation changes, affected query forms, and referenced vulnerabilities. It is clearly related to the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.

Warning

Some tools did not complete. Review the errors below.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/runtime/internal/security.ts

Parsing error: Unexpected token :

test/unit/assertSafeQuery.test.ts

Parsing error: Unexpected token as


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@farnabaz
farnabaz merged commit 006d138 into main Oct 1, 2026
8 checks passed
@farnabaz
farnabaz deleted the sec/allow-list-bypasses branch October 1, 2026 11:05

This branch was successfully deployed

1 active deployment
Preview — c7bd82c2 Deployed Oct 1, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant