sql-guard-references

SQL guard: out-of-scope references blocked in every position

shipped

The sections below are generated from the CLI (methodology 0.3-draft, CLI 0.3.0); the same text is printed by sealmark explain sql-guard-references.

pack
sql-guard opt-in pack
weight
criticalcandidate
scope
server (judged by what reached the harness's upstream stub, not by the server's reply; no SQL is parsed)
decided by
upstream
since
0.3-draft (methodology 0.3-draft)
config keys
checks.sql-guard-references.enabledchecks.sql-guard-references.severityscope.allowscope.separatorsql_toolsupstream.kind

Probes

  • from SELECT * FROM {o} WHERE 'sm-{token}' = 'sm-{token}' ({a} an in-scope name, {o} <container of scope.allow[0]>.outside_sm_<token>; must not reach the upstream)
  • join SELECT * FROM {a} JOIN {o} ON 1 = 1 WHERE 'sm-{token}' = 'sm-{token}' ({a} an in-scope name, {o} <container of scope.allow[0]>.outside_sm_<token>; must not reach the upstream)
  • comma-join SELECT * FROM {a}, {o} WHERE 'sm-{token}' = 'sm-{token}' ({a} an in-scope name, {o} <container of scope.allow[0]>.outside_sm_<token>; must not reach the upstream)
  • subquery-from SELECT * FROM (SELECT * FROM {o}) AS t WHERE 'sm-{token}' = 'sm-{token}' ({a} an in-scope name, {o} <container of scope.allow[0]>.outside_sm_<token>; must not reach the upstream)
  • subquery-where SELECT * FROM {a} WHERE x IN (SELECT x FROM {o}) AND 'sm-{token}' = 'sm-{token}' ({a} an in-scope name, {o} <container of scope.allow[0]>.outside_sm_<token>; must not reach the upstream)
  • scalar-subquery SELECT (SELECT max(x) FROM {o}) AS sm_{token} FROM {a} WHERE 'sm-{token}' = 'sm-{token}' ({a} an in-scope name, {o} <container of scope.allow[0]>.outside_sm_<token>; must not reach the upstream)
  • exists SELECT * FROM {a} WHERE EXISTS (SELECT 1 FROM {o}) AND 'sm-{token}' = 'sm-{token}' ({a} an in-scope name, {o} <container of scope.allow[0]>.outside_sm_<token>; must not reach the upstream)
  • cte WITH c AS (SELECT * FROM {o}) SELECT * FROM c WHERE 'sm-{token}' = 'sm-{token}' ({a} an in-scope name, {o} <container of scope.allow[0]>.outside_sm_<token>; must not reach the upstream)
  • union SELECT * FROM {a} UNION SELECT * FROM {o} WHERE 'sm-{token}' = 'sm-{token}' ({a} an in-scope name, {o} <container of scope.allow[0]>.outside_sm_<token>; must not reach the upstream)
  • quoted SELECT * FROM {o:quoted} WHERE 'sm-{token}' = 'sm-{token}' ({a} an in-scope name, {o} <container of scope.allow[0]>.outside_sm_<token>; must not reach the upstream)
  • cased SELECT * FROM {o:upper} WHERE 'sm-{token}' = 'sm-{token}' ({a} an in-scope name, {o} <container of scope.allow[0]>.outside_sm_<token>; must not reach the upstream)
  • alias-hidden SELECT * FROM {o} AS {a:last} WHERE 'sm-{token}' = 'sm-{token}' ({a} an in-scope name, {o} <container of scope.allow[0]>.outside_sm_<token>; must not reach the upstream)

Settings and thresholds

Every check also takes checks.sql-guard-references.enabled and checks.sql-guard-references.severity; they are described once in the configuration reference.

This check has no numeric threshold.

KeyDefaultStandardMeaning
scope.allow[]not lockedIdentifiers the server may serve. An entry that ends with scope.separator is a prefix (sales.public.); any other entry is exact. Needed when scope.tools is not empty.
scope.separator.not lockedThe one character that separates the parts of an identifier (and ends a prefix entry).
sql_toolsnonenot lockedTools that take a SQL string, as { tool, arg } (optional role: reader|writer|unknown, shape: string|array, args: { <parameter>: <string|number|boolean> } for the tool's other required parameters, which a placeholder cannot satisfy). Auto-detected when omitted. A list adds tools and corrects arguments; it never hides a detected tool (use tools.exclude for that), and a detected writer stays a writer.
upstream.kindnonenot lockedKind of the harness-owned upstream stub the server's backend is pointed at through {upstream}. http starts a loopback stub that records every request the server forwards (flag --upstream). null starts none. The stub needs a server Sealmark starts, and the server must use {upstream} in command, args, env, url, headers or files.

How the verdict is established

  • Scoring. critical and scored: pass = 1 point, part = 0.5, fail = 0. A fail caps the pack's grade at D, whatever the other checks scored.

What to fix

Check every table reference of the parsed statement against the scope, not only the first: FROM, JOIN, comma joins, subqueries in FROM, WHERE and the select list, EXISTS, CTEs, UNION branches, quoted and differently cased names, and aliased names; refuse the whole statement when any one is out of scope. The check is n/a until scope.allow is set.

False positives

None known: an out-of-scope name that reaches the upstream was let through whatever the server intended.

False negatives

Only the reference positions in the published corpus are tried, against one out-of-scope name per probe. Not applicable (n/a) without scope.allow.