Prompt Injection Is Static Analysis Now

GitHub’s July 10 CodeQL changelog has the kind of line that looks small until you imagine it landing in a real pull request: CodeQL 2.26.0 adds a JavaScript and TypeScript query for system prompt injection.

That does not mean static analysis can now “solve” prompt injection. It cannot. Prompt injection is still a design problem, a runtime problem, a product problem, and sometimes just the cost of letting an untrusted person talk to a model.

But the release is still a useful marker. A prompt boundary is becoming something ordinary security tooling can point at. Not as vibes. Not as an AI governance deck. As a code path.

For builders, that is the important part.

What CodeQL Actually Added

The new query is js/system-prompt-injection. CodeQL classifies it as a path problem with high precision, security severity 7.8, and a CWE-1427 tag for improper neutralization of input used for LLM prompting.

The query help describes the risky pattern directly: user-controlled data is included in a system prompt or in a tool description for an agentic system. In that position, the value is no longer ordinary user content. It can become part of the trusted instruction layer the model uses to decide how to behave.

CodeQL’s recommendation is equally direct: do not include user input in system-level or developer-level prompts or tool descriptions. Put user content in the user role. If user input truly has to influence a system prompt or tool description, validate it against a fixed allowlist.

That is not an exotic recommendation. It is the same shape as the advice developers already know from SQL injection, shell command injection, path traversal, SSRF, and template injection: keep control structure separate from untrusted data, and constrain any data that must cross the boundary.

The difference is the boundary has moved into model orchestration code.

Why This Matters More Than The Query Itself

Prompt injection has often been discussed as if it lives in chat transcripts: a clever string, a hostile document, a user saying “ignore previous instructions.” That framing is too narrow for real applications.

In production AI features, prompts are assembled by software. A request parameter might select a persona. A CMS field might shape an assistant instruction. A database value might become part of a tool description. A customer-defined workflow might be interpolated into an agent’s operating rules.

Those are code paths. They can be reviewed, modeled, tested, and scanned.

That does not make the problem easy. Static analysis is strongest when there is a visible flow from an untrusted source to a sensitive sink. It is weaker when the risk depends on product semantics, third-party data, hidden prompt construction, retrieval content, or framework behavior the analyzer does not model yet. Even GitHub’s own CodeQL docs note that niche or custom frameworks may need additional modeling for better analysis.

Still, this is the right direction. The most useful AI security work is not magical model psychology. It is boring boundary maintenance.

The Operator Checklist

  • Search for places where request data, profile fields, CMS content, workspace names, file names, repository text, issue text, or tenant-configured values are interpolated into system prompts, developer prompts, or tool descriptions. Do not only search for the word “system.” Many wrappers hide role names behind helper functions.
  • Separate trusted instructions from user content. If the model needs a user-selected persona, pass the persona as a user message or as a constrained parameter. Keep the system prompt fixed: what the assistant is allowed to do, what it must refuse, how it should treat the persona, and which rules remain non-negotiable.
  • Make tool descriptions boring. Tool descriptions are not a place to paste user-specific context. They are part of the model’s control surface. If the tool searches reference material, describe the tool as “search approved reference material” and pass the requested topic as a parameter or user message.
  • Decide where scanning belongs. GitHub Docs describe three common CodeQL paths: default setup, advanced setup through a workflow, or running the CLI in external CI and uploading results. For small teams, default setup is often enough to start. For teams already tuning query suites and custom packs, confirm JavaScript/TypeScript AI code is included in the analysis path.
  • Do not treat a clean scan as a clean design. CodeQL can catch certain flows. It cannot tell you whether an agent should have a dangerous tool, whether a retrieval corpus is hostile, whether a model will follow the wrong instruction at runtime, or whether your product should let end users define workflow policy in the first place.

The Misframed Conversation

The public conversation around prompt injection still swings between two bad instincts.

One side treats it like a prompt-writing problem: if the instruction is clever enough, the model will obey. The other treats it like an unsolvable property of language models, so every defense is theater.

Neither is useful for operators.

The practical position is less dramatic. Some prompt-injection risk comes from putting untrusted data in trusted places. That class of mistake is not new. It just has new sinks. It belongs in code review, static analysis, CI, framework defaults, and internal engineering guidelines.

Other prompt-injection risk comes from runtime interaction with untrusted content. That requires layered controls: least-privilege tools, explicit confirmation for irreversible actions, output filtering where appropriate, retrieval isolation, audit logs, rate limits, and product decisions about what an AI feature is allowed to do.

Static analysis helps with the first category and can support the second, but it does not replace architecture.

The Durable Lesson

The durable lesson from CodeQL 2.26.0 is not that GitHub added one AI security query. It is that AI control surfaces are being pulled into the same operational machinery as the rest of software security.

That is healthy.

Prompt templates, tool descriptions, agent instructions, and model SDK calls should not live in a special exempt category because they contain natural language. If they shape behavior, they are application logic. If untrusted data flows into them, they deserve scrutiny.

The teams that handle this well will not be the ones with the flashiest “AI security” posture. They will be the teams that turn prompt boundaries into normal engineering facts: named, reviewed, scanned, tested, and kept separate from user-controlled content wherever possible.

That is how this stops being a novelty and becomes operations.

Sources

Scroll to Top