Skip to content

fix(web): escape backslashes in analytics ClickHouse literals#1925

Merged
richiemcilroy merged 1 commit into
mainfrom
security/clickhouse-sql-injection
Jun 19, 2026
Merged

fix(web): escape backslashes in analytics ClickHouse literals#1925
richiemcilroy merged 1 commit into
mainfrom
security/clickhouse-sql-injection

Conversation

@richiemcilroy

@richiemcilroy richiemcilroy commented Jun 19, 2026

Copy link
Copy Markdown
Member

Escapes backslashes (not just single quotes) when interpolating values into the ClickHouse/Tinybird analytics queries, closing a SQL injection through the analytics video/cap id parameters.

Greptile Summary

This PR fixes a SQL injection vulnerability in ClickHouse/Tinybird analytics queries by escaping backslashes before single quotes in the escapeLiteral helper. The previous implementation only doubled single quotes, which allowed a trailing backslash in attacker-controlled input (video/cap IDs, org IDs) to neutralise the doubled quote and break out of the string literal.

  • Both get-analytics.ts and data.ts receive the identical one-line fix (replace(/\\\\/g, \"\\\\\\\\") applied before the quote doubling), and all 14+ interpolation sites in data.ts already route through escapeLiteral, so coverage is complete.
  • The ordering of the two replacements (backslash first, then quote) is correct and the accompanying comment clearly documents why the sequence matters.

Confidence Score: 5/5

Targeted, correct security fix with no logic changes — safe to merge.

The change is a minimal, well-reasoned patch to a single escaping function replicated across two files. All dynamic values in both files already flow through escapeLiteral, the replacement order is correct (backslashes before quotes), and no other code paths are touched.

No files require special attention.

Important Files Changed

Filename Overview
apps/web/actions/videos/get-analytics.ts Fixes SQL injection by escaping backslashes before single quotes in escapeLiteral; all dynamic values (orgId, pathname) are consistently wrapped.
apps/web/app/(org)/dashboard/analytics/data.ts Same escapeLiteral hardening applied; all 14 tenant_id and pathname interpolation sites confirmed to go through the updated function.

Reviews (2): Last reviewed commit: "fix(web): escape backslashes in analytic..." | Re-trigger Greptile

@polarityinc

polarityinc Bot commented Jun 19, 2026

Copy link
Copy Markdown

Paragon Review Skipped

Hi @richiemcilroy! Your Polarity credit balance is insufficient to complete this review.

Please visit https://app.paragon.run to finish your review.

@superagent-security

Copy link
Copy Markdown

Superagent didn't find any vulnerabilities or security issues in this PR.

const DEFAULT_RANGE_DAYS = MAX_RANGE_DAYS;

const escapeLiteral = (value: string) => value.replace(/'/g, "''");
// Escape backslashes BEFORE quotes: ClickHouse honors C-style `\'` inside

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Minor nit: the breakout sequence you’re protecting against is \' (single backslash + quote). Writing it as \\' in the inline example reads like two backslashes.

Suggested change
// Escape backslashes BEFORE quotes: ClickHouse honors C-style `\'` inside
// Escape backslashes BEFORE quotes: ClickHouse honors C-style `\'` inside

// Escape backslashes BEFORE quotes: ClickHouse honors C-style `\'` inside
// single-quoted literals, so doubling quotes alone lets a trailing backslash
// neutralise the doubled quote and break out of the string (SQL injection).
const escapeLiteral = (value: string) =>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This helper is now duplicated in apps/web/app/(org)/dashboard/analytics/data.ts too. Might be worth extracting a shared escapeClickhouseLiteral util so the escaping rules don’t drift over time.

Comment on lines +53 to +54
const escapeLiteral = (value: string) =>
value.replace(/\\/g, "\\\\").replace(/'/g, "''");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Duplicated escapeLiteral function

escapeLiteral now exists in identical form in both data.ts and get-analytics.ts. This PR correctly fixes both copies, but any future change (or regression) will have to be made in two places. Consider extracting this function into a shared analytics utility module (e.g., lib/clickhouse-escape.ts) so there is a single source of truth.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/app/(org)/dashboard/analytics/data.ts
Line: 53-54

Comment:
**Duplicated `escapeLiteral` function**

`escapeLiteral` now exists in identical form in both `data.ts` and `get-analytics.ts`. This PR correctly fixes both copies, but any future change (or regression) will have to be made in two places. Consider extracting this function into a shared analytics utility module (e.g., `lib/clickhouse-escape.ts`) so there is a single source of truth.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@richiemcilroy

Copy link
Copy Markdown
Member Author

@greptileai please review the PR

@richiemcilroy richiemcilroy merged commit 9376d90 into main Jun 19, 2026
20 of 21 checks passed
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