AI agent SQL injection begins at one call site: where an agent's SQL string reaches a database driver. agent_sql_seam.py, a static ast detector, finds that seam before anything runs and classifies every DB sink as RAW_STRING_TO_DB, PARAM_OK, POLICY_MEDIATED, or UNRESOLVED. In this post's fixtures, one f-string marks a sink RAW; one bound parameter marks it PARAM_OK, same rows either way.
AI disclosure: I wrote agent_sql_seam.py with an AI assistant and ran it myself, offline, before publishing. Every output block below is pasted from a real local run on Python 3.13.5, standard library only, no network. I checked the exit codes (0 / 1 / 2), hashed the STDOUT of each scenario twice to confirm it is byte-for-byte deterministic, and edited every line. The external quotes and the 1034 / 23 / 0 benchmark numbers belong to Dipankar Sarkar's OrmAI writeup, not to me; I link the primary sources and keep their numbers in their own paragraphs, away from my fixture counts.
In short:
Whether a query can be injected into is a property of how the SQL string was assembled, not of what the query returns. Two calls can pull the identical rows and only one of them ever holds a string an attacker's value can land inside.







