- Case ID
- #9268
- Severity
- WARN
- Decision
- BLOCK
- Agent
- Windsurf
- Category
- Source Code
Correction note (2026-10-13). The per-call timings and latency figures that appeared in this article had no benchmark behind them and were removed. Sample output in this article is illustrative, not a recorded run. The only published measurement is p50 0.39 ms and p99 1.91 ms (sigmashake-bench daemon-socket run, 2026-06-10, ssg 0.29.156, n=500). Sub-2 ms evaluation is a design target.
Describe the task
You ask Windsurf to write a user lookup query. The agent uses string template interpolation to build the SQL:
const query = `SELECT * FROM users WHERE email = '${email}'`;
const result = await db.query(query);
If email contains SQL metacharacters — ' OR '1'='1 — the query structure is modified and the attacker reads your entire users table. SSG's no-sql-injection write rule flags the file.
# illustrative sample output
[BLOCK] write_file › src/db/users.ts — rule: no-sql-injection
Reason: String-interpolated SQL query detected.
Give SSG context
SSG intercepts write calls via the SSG MCP Server integration inside Windsurf (Cascade) and validates source code content.
Required context
rule no-sql-injection {
enabled true
priority 90
severity error
DENY write
IF content REGEX "SELECT.*FROM.*WHERE.*\$\{"
OR content REGEX "INSERT.*INTO.*VALUES.*\$\{"
OR content REGEX "UPDATE.*SET.*\$\{"
MESSAGE "String-interpolated SQL detected. Use parameterized queries or an ORM instead."
}
Optional context
Also catch template literal SQL building:
rule no-sql-concat {
enabled true
priority 90
severity error
DENY write
IF content REGEX "(SELECT|INSERT|UPDATE|DELETE).*\+.*req\."
MESSAGE "SQL query built with string concatenation from request data. Use parameterized queries."
}
What SSG does
SSG reads the full file content and runs the regex before saving. Windsurf receives the block and can rewrite using parameterized queries.
Ask the agent to use parameterized queries
The SQL write was blocked: the query used string interpolation with user-supplied data.
Rewrite using parameterized queries:
const result = await db.query("SELECT * FROM users WHERE email = $1", [email]);
Or use an ORM (Prisma, Drizzle, TypeORM) which handles parameterization automatically.
Suggest an ORM for new code
If the project already uses Prisma or another ORM, guide Windsurf to use it:
Instead of raw queries, use Prisma:
const user = await prisma.user.findUnique({ where: { email } });
Audit injection patterns across your codebase
After onboarding SSG, the first week's audit log often reveals historical write attempts with SQL injection patterns. Use this as a baseline security assessment.
How your regex handles different ORMs and drivers
The pattern targets template literal interpolation (${}) in SQL keywords. It doesn't match Prisma, Drizzle, or other ORMs that never build raw SQL strings this way. False positives are unlikely for parameterized patterns like db.query("SELECT...", [param]).
Check the rule against your data migration scripts
Some migrations legitimately use string-built SQL (e.g., dynamic schema changes). Add a path exclusion for your migrations directory if needed, combined with an ASK rule for human review.