GitHub announced on July 10, 2026 that CodeQL 2.26.0 adds AI prompt-injection detection. Enabling a query is useful; owning a regression test is better.
Primary source: GitHub Changelog, July 10, 2026.
The examples below are implementation templates, not results from a repository I tested.
A useful fixture contains an untrusted source, prompt construction, and a model sink:
security-fixtures/prompt-injection/
├── positive/direct-flow.ts
├── positive/helper-flow.ts
├── negative/trusted-instruction.ts
└── expected-alerts.json
Do not test for the literal phrase ignore previous instructions
. Static analysis needs a data-flow path. Preserve a supported SDK call from your production stack so CodeQL can recognize the sink.
// Intentionally vulnerable fixture. Never ship this path.
import { model } from "./supported-client";
declare function loadIssueBody(id: number): Promise<string>;
export async function summarize(id: number) {
const untrusted = await loadIssueBody(id);
return model.generate({
system: "Summarize the issue",
user: untrusted,
});
}
Add a second positive case that passes the value through a helper. Then add a negative control where attacker input cannot select or alter the instruction. A function named sanitize()
is not evidence of sanitization.
Up SARIF alone does not create a regression gate. Commit the expected rule and fixture location:
{
"required": [
{
"ruleId": "REPLACE_WITH_DOCUMENTED_RULE_ID",
"pathSuffix": "positive/direct-flow.ts"
}
],
"forbiddenPathSuffixes": ["negative/trusted-instruction.ts"]
}
Keep the rule ID as a placeholder until it is copied from the CodeQL 2.26.0 documentation or an observed SARIF result. Machine-facing identifiers should never be guessed.
A small assertion can compare runs[].results[].ruleId
and each physical location against this file. Fail when a required alert disappears or a negative fixture starts alerting. Do not assert the total number of repository alerts; unrelated code changes make that brittle.
| Result after upgrade | Action |
|---|---|
| Required alert remains | Continue normal review |
| Required alert disappears | Block until query, model, build, or fixture changes are explained |
| New positive location appears | Inspect and deliberately update expectations |
| Negative control alerts | Revisit the mitigation assumption before suppressing |
Pin the CodeQL CLI or action version, record it in CI, and run the fixture on a disposable database. Keep runtime adversarial tests too: static analysis cannot prove how a model will react, and custom wrappers or unsupported SDKs may not be modeled.
The goal is intentionally narrow: make one important untrusted-to-model path an executable repository contract instead of a changelog checkbox.