A table name can be SQL, and qanat check says it is fine
What I did
I put SQL code inside a table name in qanat.yaml, then ran the step.
to: ['features.z" AS SELECT 1 AS q; DROP TABLE features__momentum; CREATE OR REPLACE TABLE "zzz']
What happened
$ qanat check ✓ demo: 5 stages, 12 tables, 12 jobs · contract holds $ qanat run inj run status: failed | ParserException: syntax error at or near "SELECT" features.momentum survived: False
The check passed. The step then deleted a real table. The console only shows a red job and a confusing SQL error. It never says a table was deleted.
Why it matters
The code that checks a table name (_qualified()) only counts the dots. It never looks
at the rest of the name. That name goes straight into SQL in store.py.
The console API accepts this name with 200 OK. So does the MCP tool
save_step. That is the real risk: qanat is built so an agent writes these
files. A model does not need bad intent to write a strange name.
How to fix it
- Check the table name with the same rule
Stage.idalready uses:^[a-z][a-z0-9_]*$. Put it in_qualified(), so it covers sources, steps,when:,retention:andtime_columns:together. - Also double any
"insideStore._q(), as a second wall. - Add a test that gives
validate()a bad name and expects an error.