Every SAST scanner finds the obvious pattern: a tainted variable fed directly into an LLM call in the same function.
Real code does not look like that.
Real code wraps LLM calls in helper functions. It chains through handle_request -> process_data -> call_llm -> model.generate. The taint vanishes at each function boundary because no scanner tracks what happens across them.
AgentGuard v0.5.5 closes this gap with interprocedural taint analysis.
The Pattern No Scanner Catches
def call_llm(prompt):
return client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}]
)
def handle_request(user_input):
response = call_llm(user_input)
return response
A regex scanner sees: user_input in handle_request -- not an LLM call. It sees chat.completions in call_llm -- but prompt is a parameter. Result: zero findings. False negative.
Three Detection Modes
AgentGuard now builds a catalog of every Python function, records which ones contain LLM sinks, and traces tainted arguments across boundaries:
-
Direct cross-function:
user_input->call_llm(user_input)->chat.completions.create -
Multi-hop chains:
user_input->process_data(user_input)->call_llm(data)-> sink -
Param-signature detection:
def generate_answer(user_query)whereuser_queryreaches LLM inside
Adversarial Self-Review
Before shipping, I ask: what does this miss?
-
Cross-file calls -- Only same-file analysis for now. Phase 2 adds import resolution for
from utils import call_llmpatterns. - Name-based detection -- Works on variable naming conventions. FP rate is 0% on 32 benchmark samples.
-
No sanitizer tracking -- Phase 3 will register
bleach.clean/html.escapeto break taint chains.
Numbers
- 56 tests pass (6 new)
- 32/32 benchmark samples detected
- 0 false positives
- 15 releases on PyPI
pip install dfx-agentguard==0.5.5
GitHub: https://github.com/dockfixlabs/agentguard
Action: https://github.com/marketplace/actions/agentguard-ai-agent-security
Top comments (0)