Skip to content

fix(node-core): sql injection in dynamic datasource appending via unescaped json serialization#3031

Merged
ianhe8x merged 1 commit intosubquery:mainfrom
chinhkrb113:contribai/fix/security/sql-injection-in-dynamic-datasource-appe
Apr 1, 2026
Merged

fix(node-core): sql injection in dynamic datasource appending via unescaped json serialization#3031
ianhe8x merged 1 commit intosubquery:mainfrom
chinhkrb113:contribai/fix/security/sql-injection-in-dynamic-datasource-appe

Conversation

@chinhkrb113
Copy link
Copy Markdown
Contributor

@chinhkrb113 chinhkrb113 commented Mar 27, 2026

🔒 Security Fix

Problem

The APPEND_DS_QUERY function constructs a raw SQL query by directly interpolating JSON.stringify(item) into a single-quoted SQL string literal ('${JSON.stringify(item)}'::jsonb). Because JSON.stringify does not escape single quotes, any single quote within the item payload (which represents dynamic datasource parameters, often derived from untrusted on-chain events) will break out of the SQL string literal. This allows an attacker to inject arbitrary SQL commands into the indexer's database by emitting crafted events on-chain.

Severity: high
File: packages/node-core/src/indexer/storeModelProvider/metadata/utils.ts

Solution

Escape single quotes in the serialized JSON string by replacing them with double single quotes ('') before interpolation:

Changes

  • packages/node-core/src/indexer/storeModelProvider/metadata/utils.ts (modified)

Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

Fixes # (issue)

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Checklist

  • I have tested locally
  • I have performed a self review of my changes
  • Updated any relevant documentation
  • Linked to any relevant issues
  • I have added tests relevant to my changes
  • Any dependent changes have been merged and published in downstream modules
  • My code is up to date with the base branch
  • I have updated relevant changelogs. We suggest using chan
    Contributed by Lê Thành Chỉnh
    Code is a tool. Mindset is the real value.

Closes #3030

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced data serialization to properly escape single quotes when storing data, preventing query-related issues.

…ng via unescaped json serialization

The `APPEND_DS_QUERY` function constructs a raw SQL query by directly interpolating `JSON.stringify(item)` into a single-quoted SQL string literal (`'${JSON.stringify(item)}'::jsonb`). Because `JSON.stringify` does not escape single quotes, any single quote within the `item` payload (which represents dynamic datasource parameters, often derived from untrusted on-chain events) will break out of the SQL string literal. This allows an attacker to inject arbitrary SQL commands into the indexer's database by emitting crafted events on-chain.

Affected files: utils.ts

Signed-off-by: ChinhLee <[email protected]>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 27, 2026

📝 Walkthrough

Walkthrough

Fixed a SQL injection vulnerability in the APPEND_DS_QUERY helper by escaping single quotes within JSON strings before embedding them into SQL jsonb literals. The fix replaces single quote characters with their escaped equivalents in the serialized JSON data.

Changes

Cohort / File(s) Summary
SQL Injection Prevention
packages/node-core/src/indexer/storeModelProvider/metadata/utils.ts
Updated makeSet helper to escape single quotes in JSON.stringify(item) output by replacing ' with '' before inserting into the '... '::jsonb SQL literal, preventing quote-based SQL injection via dynamic datasource parameters.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A quote escaped, a quote secured,
Single marks now doubly assured,
No SQL breaks through our line,
The datasources now divine! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the security fix for SQL injection in dynamic datasource appending via unescaped JSON serialization, matching the core change.
Linked Issues check ✅ Passed The pull request addresses the security requirement in issue #3030 by escaping single quotes in JSON-serialized data before embedding it into the SQL string literal.
Out of Scope Changes check ✅ Passed The changes are limited to the specific function requiring the SQL injection fix, with no unrelated modifications to other parts of the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/node-core/src/indexer/storeModelProvider/metadata/utils.ts (1)

28-28: Add a regression test for malicious quote-containing datasource payloads.

Please add a focused test that passes DatasourceParams values like O'Reilly and SQL-looking fragments, then asserts the generated SQL contains doubled quotes (e.g. '') and remains a valid ::jsonb literal.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/node-core/src/indexer/storeModelProvider/metadata/utils.ts` at line
28, Add a regression test that constructs DatasourceParams containing
quote-bearing and SQL-looking values (e.g. "O'Reilly" and "'); DROP TABLE
users;--") and passes them into the same SQL-generation helper in
packages/node-core/src/indexer/storeModelProvider/metadata/utils.ts that
produces the jsonb_set(...) expression (reference the template using VALUE and
value/item interpolation shown in the diff). The test should assert the
generated SQL literal doubles single quotes (e.g. O''Reilly), that the quoted
fragment is still followed by ::jsonb, and that the overall string is a valid
JSONB literal (you can assert presence of the doubled quotes and the trailing
::jsonb token and optionally try parsing/validating the JSON literal if a helper
exists). Ensure the test covers both simple quote and SQL-like payloads.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/node-core/src/indexer/storeModelProvider/metadata/utils.ts`:
- Line 28: Add a regression test that constructs DatasourceParams containing
quote-bearing and SQL-looking values (e.g. "O'Reilly" and "'); DROP TABLE
users;--") and passes them into the same SQL-generation helper in
packages/node-core/src/indexer/storeModelProvider/metadata/utils.ts that
produces the jsonb_set(...) expression (reference the template using VALUE and
value/item interpolation shown in the diff). The test should assert the
generated SQL literal doubles single quotes (e.g. O''Reilly), that the quoted
fragment is still followed by ::jsonb, and that the overall string is a valid
JSONB literal (you can assert presence of the doubled quotes and the trailing
::jsonb token and optionally try parsing/validating the JSON literal if a helper
exists). Ensure the test covers both simple quote and SQL-like payloads.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b9ca93d4-ffd7-4d3b-abbe-360431b7fa43

📥 Commits

Reviewing files that changed from the base of the PR and between cbee806 and ec237a3.

📒 Files selected for processing (1)
  • packages/node-core/src/indexer/storeModelProvider/metadata/utils.ts

@ianhe8x ianhe8x merged commit 009dee0 into subquery:main Apr 1, 2026
1 check passed
@ianhe8x
Copy link
Copy Markdown
Collaborator

ianhe8x commented Apr 1, 2026

Thanks for contributing.

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.

fix(node-core): sql injection in dynamic datasource appending via unescaped json serialization

2 participants