Add AGENTS.md so the threat model is discoverable by agents - #5126
Conversation
CALCITE-7605 landed the threat model at site/_docs/security_threat_model.md and a SECURITY.md that links to it. The remaining gap is the entry point: automated agents locate a project's security model by following AGENTS.md -> SECURITY.md -> the model, and this repository has no AGENTS.md, so the first hop is missing and the chain cannot be walked mechanically. This adds one, pointing at SECURITY.md and summarising the two rules that carry most of the triage weight — the surprising-vs-unsurprising class-loading gate over the SPI positions, and the pushed-down-SQL split (generated SQL reaching a configured backend is not a vulnerability; a pushdown bug reading beyond the configured schemas is P4 and is one) — plus the "Not a vulnerability" and "Downstream responsibilities" lists. No new claims: everything here restates the merged model. AGENTS.md is added to .ratignore alongside SECURITY.md, matching what CALCITE-7605 did for that file, since it carries no license header. Docs only; no production code touched. Generated-by: Claude Opus 5 (1M context)
|
|
Thanks @potiuk for the patch! |
| # Agent guidance | ||
|
|
||
| This file is read by automated agents (security scanners, code analyzers, | ||
| AI assistants) operating on this repository. It points them at the | ||
| human-authored references they should consult before producing output. | ||
|
|
||
| ## Security | ||
|
|
||
| Security model: [SECURITY.md](./SECURITY.md), which links to the project's | ||
| threat model at | ||
| [site/_docs/security_threat_model.md](./site/_docs/security_threat_model.md). | ||
|
|
||
| Calcite is an embedded SQL framework, not a server. It opens no socket and | ||
| has no authentication or authorization of its own; the host application | ||
| owns transport, identity, and schema scoping. Read the threat model before | ||
| reporting anything — it is explicit about what it does and does not treat | ||
| as a vulnerability. | ||
|
|
||
| Two rules carry most of the triage weight: | ||
|
|
||
| - **Surprising vs unsurprising class loading.** A class named through a | ||
| Calcite SPI position — `schemaFactory`, `parserFactory`, `typeSystem`, | ||
| `metaTableFactory`, `metaColumnFactory`, `tableFactory`, function | ||
| classes, `dataSource`, `jdbcDriver`, `model` — is loaded only through | ||
| that SPI, gated by `Class.forName(name, false, loader)` plus an | ||
| `isAssignableFrom` check. A class that does not implement the SPI for | ||
| its position is never instantiated by name. SQL may name SPI classes, | ||
| but only SPI implementations run, and only through their SPI. | ||
| - **Pushed-down SQL.** The SQL Calcite generates and sends to a backend | ||
| the operator configured is *not* a vulnerability — the query author can | ||
| already reach that endpoint through the visible schemas. A pushdown bug | ||
| that reads *beyond* the configured schemas is P4 and *is* one. | ||
|
|
||
| Explicitly not vulnerabilities (see the model's "Not a vulnerability" | ||
| section): the os-adapter running OS commands, the file/CSV/JSON adapters | ||
| reading paths they were configured with, anything requiring a changed | ||
| system property or classpath, a third-party driver's behaviour past the | ||
| connection boundary, and cross-tenant reads that follow from the embedder | ||
| exposing several principals' schemas on one connection. | ||
|
|
||
| The model also lists what belongs to the host rather than the library — | ||
| transport and identity, schema scoping, adapter selection, the classpath, | ||
| and whatever a `model` points at — under "Downstream responsibilities". |
There was a problem hiding this comment.
This gets injected to every context of every agent. It bloats context with zero gain. There's no sense in providing excessive security-related stuff. It should be referenced instead.
There was a problem hiding this comment.
Correct. I am not even sure why it ended up here eventually (long time ago and I had about 100 of similar PRs :( and most of them were bare minimum and linking to SECURITY.md for more details.
This is a bit of the problem with Agentically generated PRs that things like that can slip - especially when you do a lot of those in a short time (learning for me as well to pay more attention).
Thanks @vlsi for updating it.



What
Adds an
AGENTS.mdat the repository root pointing atSECURITY.md, and adds it to.ratignorealongsideSECURITY.md.Why
CALCITE-7605 landed the threat model at
site/_docs/security_threat_model.mdtogether with aSECURITY.mdthat links to it. That part is complete and reads well.What is missing is the entry point. Automated agents — security scanners, code analyzers, coding assistants — locate a project's security model by following a fixed chain:
apache/calcitehas the second and third hops but not the first, so the chain cannot be walked mechanically and an agent starting from a clone has no way to find the model on its own.This matters concretely for the ASF Security team's scanning programme: we refuse to run a scan against a project whose model is not mechanically discoverable, because without the model in context the false-positive rate is more than a PMC can reasonably triage. This PR closes that gap for Calcite.
What is in the file
No new claims — everything restates the merged model:
SECURITY.mdand onward tosite/_docs/security_threat_model.md.Class.forName(name, false, loader)plusisAssignableFrom, across the enumerated SPI positions), and the pushed-down SQL split (generated SQL reaching a configured backend is not a vulnerability; a pushdown bug reading beyond the configured schemas is P4 and is one).Notes for reviewers
.ratignore:AGENTS.mdcarries no license header, so it is excluded exactly as CALCITE-7605 excludedSECURITY.md. Happy to add a header and drop the.ratignoreline instead if the PMC prefers that direction.[CALCITE-NNNN]convention.Opened by the ASF Security team as part of the Frontier Model Preparation scan pre-flight for Calcite, following the request on the PMC's
[GLASSWING]thread. Review, change, or close as the PMC sees fit — the document is the project's.🤖 Generated with Claude Code