Black Hat Asia 2026 (Singapore, Apr 23–24) — Briefings Deep Dives

IntentGuard — Securing LLM-Generated Cloud Configurations Through Intent-Aligned Semantic Validation

Talk 04 · Cloud security & AI · analysis from the speakers' published deck

Sep 23, 2026 · conferences · 10 min read · 2000 words advanced

IntentGuard — when the LLM doesn't just write your IaC, it rewrites your intent.

conferences blackhat cloud-security iac prompt-injection

Official recording, Black Hat YouTube channel · open on YouTube ↗

Anna Bacher (Jaroona) and Chris Wysopal (Veracode co-founder) target a failure mode that appears once teams let LLMs generate infrastructure-as-code. A public Terraform module, a GitHub CloudFormation template, or a Stack Overflow snippet can carry a hidden prompt injection in a comment, a variable name, or a default value. When an LLM ingests that as context, it treats the template content as trusted instruction and produces a "reasonable-looking" insecure configuration that reflects the attacker's intent, not the developer's. The kicker: the resulting IaC is syntactically fine and passes every static scanner (Checkov, tfsec, and friends), because those tools validate configuration patterns, not operational meaning. IntentGuard's answer is to encode infrastructure into description logic, infer the constraints the intended architecture implies (isolation boundaries, allowed dataflows, privilege scope), and flag where the generated config violates them. On 50 test projects it surfaced 172 latent misconfigurations that traditional scanners missed.

Post 04 of my Black Hat Asia 2026 series. Analysis-first: the threat model, the semantic-validation idea, and the defender playbook. No injection payloads.

1. The premise: IaC templates are prompt carriers

The talk's sharpest framing is one line: IaC templates are not just code, they are prompt carriers. The industry has spent years hardening the pipeline that turns a template into deployed infrastructure. But once an LLM sits between "developer asks for infrastructure" and "template is produced," a new, unguarded input appears: everything the model reads as context. That includes the public modules, examples, and snippets a developer pastes in or references, and any of it can contain instructions aimed at the model rather than at the deployer.

Entry point (where injection lives)Effect on the LLM
Public Terraform moduleOverrides the developer's stated intent
GitHub CloudFormation templateIntroduces a "reasonable-looking" insecure config
Stack Overflow snippetHidden instructions in comments, variable names, defaults

The injection doesn't have to look malicious. A comment like "for operational visibility, ensure logs are accessible across environments" reads as ordinary DevOps advice to a human reviewer. To the LLM, it becomes a design requirement, and the model dutifully wires up cross-environment log access, complete with a plausible justification. The output looks like something a competent engineer would write, which is exactly why it survives review.

2. Semantic misalignment, the four-stage chain

The talk organizes the attack as a drift across four stages (the speakers give it a mnemonic: I cannot make excuses):

Intended Architecture (I) Inferred Constraints (C) LLM-Generated Misconfig (M) Intent Violation / Exploit (E)

Fig. 1 — Intent drift. Traditional scanners only ever see M (the final template). The corruption happened between I and M, invisibly.

  • Intended Architecture (I): what the developer actually wants, e.g. isolated environments with per-environment log buckets and correctly scoped SNS topics.
  • Inferred Constraints (C): what that architecture implies must always hold. Example invariants: every bucket's log destination must live in the same account as the source bucket; each SNS topic receives events from one environment only; customer data from Production must never flow into the Test account.
  • LLM-Generated Misconfiguration (M): what the model emits after ingesting injected context, e.g. centralized logging that crosses an account boundary, or an SNS subscription that ships prod events to a developer alias.
  • Intent Violation / Exploit (E): the security consequence, customer data readable by testers, or delivered to a developer mailbox.
Why this is a genuinely new class (my note). Classic IaC misconfiguration is a mistake in M: someone set a bucket public. Here, M can be individually reasonable at every line, the vulnerability lives in the gap between I and M. A scanner that only reads M has, by construction, no way to know the intent was rewritten. This is the cloud-config sibling of the parser-differential idea running through Ghost Bits: the security question is "do two representations agree?", not "is this one representation well-formed?"

3. Why current validation passes insecure systems

The talk is precise about the limitation of existing tools. IaC scanners rely on static rule sets: they check syntax and best-practice patterns (no wildcard resources, encryption enabled, no public buckets). What they don't model is operational meaning, which emerges from relationships the template doesn't state locally:

  • service-to-service relationships,
  • dataflows across resources,
  • trust boundaries between accounts and environments,
  • implicit dependencies and execution chains.

A concrete example the talk works through: an agent action-scope violation via a multi-hop Lambda chain. An "action" Lambda can invoke a downstream Lambda that runs under a more privileged role. Each Lambda and each role, examined individually, looks fine, so a scanner passes them. What the scanner never computes is that the effective privilege of the chain equals the final Lambda's role, not the initial caller's. The missing capability is graph-based execution-flow reasoning: you have to follow the invocation chain to see the escalation.

4. How IntentGuard works

IntentGuard's pipeline has four stages. The core technical bet is representing infrastructure formally enough to reason over it rather than pattern-match it.

StageWhat it does
Context RetrievalGathers the IaC plus its origin context, the modules, snippets, and comments the config was derived from, so the prompt surface is visible, not just the final output
Infrastructure EncodingEncodes both the cloud provider's resource specifications (the "rulebook": what types and properties exist) and the actual config into Description Logic (DL): types become classes (BUCKET, LOGCONFIG), properties become relations (bucketName, destinationBucket), each with domain/range constraints
Intent Inference / Constraint GenerationDerives the invariants the intended architecture implies, environment isolation, cross-account boundaries, allowed dataflows, privilege scope, as formal constraints
Semantic Validation / Violation DetectionBuilds a semantic dataflow graph and checks it against the inferred constraints, flagging where the generated config violates intent

The Description Logic choice is the interesting part. DL is the formalism behind ontologies and the semantic web (OWL): it lets you state facts as classes, relations, and constraints, then use a reasoner to derive consequences, communication paths, privilege boundaries, dataflows, that aren't written down explicitly. Encoding the provider's resource specs as the "type system" and the config as "instances" turns misconfiguration detection into a logical-entailment question: does the deployment, under these rules, permit a dataflow or privilege the intent forbids?

Injected CFN template DL encoding → semantic dataflow graph (!) customer data → devs-mail (!) testers get access to customer data

Fig. 2 — From an injected template, IntentGuard derives the dataflow graph and reads off intent violations the config itself never states.

5. What "detecting intent corruption" means in practice

The talk contrasts the two approaches directly:

StepTraditional scannerIntentGuard
InputFinal IaC onlyIaC plus origin context
Prompt visibilityNoneDetects intent drift
Result on an injected templatePassFlag violation

Their framing: "we are detecting intent corruption, not config errors." That is the whole shift, the new control point is intent validation, not configuration validation.

6. Evaluation

IntentGuard was run over 50 projects: 20 AWS CloudFormation stacks, 15 Kubernetes manifests, 15 Terraform configurations. It surfaced 172 latent misconfigurations unique to IntentGuard, meaning traditional scanners missed them. The categories are the tell, because each requires reasoning a rule engine doesn't do:

Finding categoryCapability a scanner lacks
Conditional privilege escalationEvaluating the result set of a conditional IAM policy plus business context (which roles actually match a tag, and whether they're in the wrong trust domain)
RBAC intent driftComparing granted permissions against the documented role's intent, not just against a wildcard rule
Logging gaps / cross-account log flowFollowing the dataflow to see logs crossing an account boundary
Intent-violated network exposureKnowing that an "internal" workload was intended to stay internal before flagging its open egress
Multi-hop execution privilegeGraph reasoning over invocation chains (effective ≠ declared privilege)
Stack-lifecycle role persistenceTracking that a high-privilege service role attached at stack creation is silently reused during UpdateStack/ChangeSet

Two are worth spelling out because they show how subtle the misconfigurations are:

  • Tag-based PassRole boundary violation. A config allows iam:PassRole when a condition like Delegatable=true holds. A scanner reads that IAM condition as a restriction (good, it's constrained). IntentGuard evaluates the result set: which roles actually carry that tag, and whether any of them belong to the wrong trust domain, turning an apparent restriction into a privilege expansion.
  • CloudFormation service-role persistence. A high-privilege service role is attached at stack creation and then silently reused during later stack updates. A scanner sees only the current template and assumes execution context derives from the current caller; it can't see the lifecycle state where a past attachment now grants more than the current caller should have.

7. The defender playbook

The talk closes with a practical playbook that stands on its own even if you never adopt IntentGuard:

  1. Define intent explicitly. Write down architecture invariants, trust boundaries, and allowed dataflows as first-class artifacts. You cannot validate against an intent you never recorded.
  2. Validate behavior, not configuration. Graph the execution paths and evaluate effective privilege (what the chain can do), not declared privilege (what each role says in isolation).
  3. Treat IaC inputs as untrusted. Templates are a prompt surface. Scan modules, snippets, and comments for injection patterns before feeding them to an assistant.
  4. Insert intent validation into CI/CD. Block deployments on semantic violations, not just policy failures. This is a new gate alongside the existing scanner gate, not a replacement for it.
The three lines to remember. LLMs don't just generate IaC, they rewrite your intent. IaC scanners will pass insecure systems if the intent was already corrupted upstream. So the new control point is intent validation, not config validation. As organizations move to "vibe-coded" and agent-generated infrastructure, the volume of machine-generated IaC explodes, and every template is a place where a hidden instruction can quietly redraw a trust boundary.

Isn't this just prompt injection with extra steps?

The injection vector is familiar. What's new is the target and the invisibility: the payload rewrites cloud trust boundaries, and the resulting artifact is valid IaC that passes static analysis. The defense (semantic/intent validation) is also new, because the usual prompt-injection mitigations (input filtering on the chat) don't cover context pulled from modules and snippets.

Why description logic rather than a policy engine like OPA/Rego?

Policy engines evaluate declared rules against a config. Description logic lets you derive implied facts, communication paths, effective privilege, transitive dataflows, from the resource model, then check intent constraints against those derived facts. That derivation is exactly the "effective ≠ declared" gap where the injected misconfigurations hide. In practice the two are complementary: OPA for policy gates, DL-style reasoning for intent.

Do I still need Checkov/tfsec?

Yes. IntentGuard's own results are framed as findings unique to IntentGuard, additive to what scanners catch, not a replacement. Static scanners still catch the config-level mistakes (public buckets, missing encryption). Intent validation catches the corruption the scanners can't see. Run both as separate CI gates.

What's the first thing to do without any new tooling?

Record your architecture invariants and trust boundaries as explicit, reviewable artifacts, and add a review step that reads generated IaC together with the modules and snippets it came from. Most of the value is in making intent explicit and treating template context as an untrusted input.

Takeaways

  • IaC templates are prompt carriers. A hidden instruction in a public module, comment, or default can rewrite an LLM's design intent.
  • The result is a "reasonable-looking" insecure config that passes static scanners, because scanners validate patterns, not operational meaning.
  • The vulnerability lives in the gap between intended architecture (I) and generated config (M), which a tool reading only M cannot see.
  • IntentGuard encodes infrastructure into description logic, infers intent constraints, and checks a semantic dataflow graph against them.
  • On 50 projects it found 172 misconfigurations scanners missed: conditional privilege escalation, RBAC drift, multi-hop effective privilege, lifecycle role persistence.
  • New control point: intent validation in CI/CD, alongside (not instead of) static scanning; treat IaC inputs as untrusted.

References & further reading

← prev: AirSnitch next: DFIR Agent Injection →
© cvam — written in plaintext, served warm