Agent Tool Security
Securing agent access to internal data sources — SQL injection prevention, MCP tool definitions, JWT-scoped permissions, row-level security, and audit logging for agentic queries against databases like Snowflake.
Overview
Why agent data access is different
Letting an agent query internal databases is harder to lock down than securing human-initiated API requests. The agent writes its query from a natural-language instruction, and that instruction may have been manipulated through prompt injection. The result is a direct path from untrusted user input to your most sensitive internal data.
- MCP tool definition — Calls to unapproved tables, raw SQL — JSON Schema validation
- Parameterized queries — SQL injection through filter values — Tool implementation
- JWT-scoped credentials — Access beyond the session's scope — Auth service and tool
- Row-level security — Rows outside the tenant or data scope — The database
- Audit logging — Exfiltration that passes every other control — Log stream and anomaly detection
The attack surface
The attack surface has two entry points, and each needs its own control.
- The tool definition: a poorly scoped definition lets the agent reach tables it should never touch.
- The tool input: an implementation that concatenates user-supplied values into SQL turns prompt injection into SQL injection.
MCP tool definitions as the first security layer
MCP (Model Context Protocol) is the emerging standard for defining agent tools in 2026. An MCP tool definition declares the tool's schema as JSON Schema: the parameter names, types and constraints the agent must follow when it calls the tool.
A query_snowflake tool that declares no raw_sql parameter cannot be called with raw SQL. Schema validation rejects the call before any implementation code runs.
Parameterized queries: the last programmatic defense
Even with a strict MCP schema, the tool must build SQL with parameterized queries, never string concatenation. In Python that means cursor.execute with %s placeholders, or Snowflake bind parameters. If the agent passes a filter value that contains SQL syntax, parameterization keeps it from changing the query's structure.
> [!IMPORTANT] Schema validation is client-side and can be bypassed in a compromised environment. Parameterized queries in the tool implementation are the last programmatic defense before the database executes.
JWT-scoped credentials
The agent does not share one database credential across all calls. Instead, it authenticates with a short-lived JWT (15-minute TTL) that your auth service issues at session start.
Row-level security
Row-level security in Snowflake and PostgreSQL filters rows by session context, not by query content. A Snowflake row access policy reads the session context variable set from the JWT claims at connection time. It then appends a WHERE clause that limits rows to the allowed tenant or data scope, and the database enforces it regardless of the query logic.
Audit logging
Log every agent query with the fields below. Anomaly detection on this log stream surfaces exfiltration attempts that pass every other control.
- Who: agent ID, user ID and the JWT claims used.
- What: the parameterized SQL that ran.
- Result: rows returned and execution time.
Allowlist versus blocklist
- Allowlist — Blocked by default — Every table must be included explicitly
- Blocklist — Accessible by default — Must enumerate every sensitive table, forever
> [!WARNING] Use an allowlist, not a blocklist, for table access: with a blocklist, any new table is exposed to the agent until someone remembers to add it.
Interview questions
- Walk me through how you would securely give an agent access to query our internal Snowflake database without exposing us to SQL injection or data leaks.
- How does MCP (Model Context Protocol) enforce tool-level security boundaries for an agent?
Sign up free to read the full topic
More MLOps & LLMOps topics
Start free on Cariara · Coding problems · System design studio