API-86Optional
Allow only known queries from your own apps
When only your own apps call a GraphQL API, register each query at build time. The server runs only registered queries, sent by their hash.
How to do it
Registered queries, also called trusted documents, turn an open query language into a fixed list. A stranger then cannot send a costly or probing query at all. The client sends a hash, which also shortens requests and lets GET answers be cached. Keep the open endpoint for public or partner APIs, with the limits from lock down GraphQL endpoints. Old app versions still send old hashes, so keep each registered query as long as keep old app versions working against the API asks.
Examples
JavaScript example
const trusted = new Map(Object.entries(JSON.parse(readFileSync('persisted-queries.json', 'utf8'))));
app.post('/graphql', express.json(), (req, res, next) => {
const query = trusted.get(req.body?.extensions?.persistedQuery?.sha256Hash);
if (!query) return res.status(400).json({ errors: [{ message: 'Unknown query', extensions: { code: 'PERSISTED_QUERY_NOT_FOUND' } }] });
req.body.query = query;
next();
});
Python example
TRUSTED = json.loads(Path("persisted-queries.json").read_text())
def resolve_query(body: dict) -> str:
query_hash = body.get("extensions", {}).get("persistedQuery", {}).get("sha256Hash")
if query_hash not in TRUSTED:
raise UnknownQuery(query_hash)
return TRUSTED[query_hash]
How to check
Send a valid query that is not on the list to production. It is refused. Every query in the client's build output has a hash in the server's list.
Sources
Related rules
- SEC-102 Lock down GraphQL endpoints in Adversarial testing
- MOB-13 Keep old app versions working against the API in Mobile apps
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/api-design/graphql-and-grpc/graphql-trusted-documents">Agent Wranglers API design playbook</a>. In code you write, add a comment next to it with the same link.