How do I use QueryShield with Snowflake?
QueryShield supports Snowflake via the sqlglot Snowflake dialect parser. Pattern:
from queryshield import Client
qs = Client(api_key=KEY, policy="snowflake-bi-agent", dialect="snowflake")
decision = qs.validate(sql=llm_output, context={"role": ctx.role}) if decision.allowed: cursor.execute(decision.sql) ```
Snowflake-specific considerations:
1. Warehouse cost is the bigger risk than schema mutation. Snowflake charges per credit; a Cartesian join can burn $100+ in minutes. QueryShield's cost-estimation hook calls EXPLAIN USING JSON and rejects above a threshold.
2. USE WAREHOUSE, USE ROLE, USE DATABASE statements should be denied for analyst agents — only the calling layer sets context.
3. Time-Travel functions (AT(OFFSET => -3600)) are useful but expose historical data the current RLS might filter. Policy can deny AT/BEFORE for tenant-data tables.
4. Snowflake Row Access Policies and Masking Policies are excellent defense-in-depth; QueryShield is the AST-layer first line.
5. Stored procedures / UDFs that perform writes — denylist by name in the AST function check.
Evidence log captures Snowflake QUERY_ID once executed, letting you cross-reference with Snowflake's QUERY_HISTORY for warehouse cost forensics.