---
title: "Accept GraphQL mutations only by POST with · Agent Wranglers"
url: https://agentwranglers.se/playbook/api-design/graphql-and-grpc/graphql-post-mutations
id: API-81
level: Required
risk: takeover
updated: 2026-10-22
tokens: 957
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Accept GraphQL mutations only by POST with a JSON body

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [GraphQL and gRPC](https://agentwranglers.se/playbook/api-design/graphql-and-grpc.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-22.

- ID: API-81
- Level: Required
- Chapter: [GraphQL and gRPC](https://agentwranglers.se/playbook/api-design/graphql-and-grpc.md)
- Rule: Run GraphQL mutations only from POST requests with `Content-Type: application/json`. Refuse a mutation sent by GET with 405 and an `Allow` header, and refuse POST bodies of any other content type.
- Check: Send a mutation by GET. The answer is 405 with `Allow: POST` and nothing changes. Send the same mutation by POST with `Content-Type: text/plain` and with a form body. Both are refused, and nothing changes.
- Risk: An account or system taken over
- How: A browser sends a GET, or a POST with a form or plain text body, to any site without asking. When such a request can run a mutation with the visitor's cookie, any web page can act as them. A JSON content type forces the browser to ask first through a CORS preflight. The GraphQL over HTTP draft says GET must not run mutations, and it names `application/graphql-response+json` for answers. GET stays useful for cached queries. Lock the endpoint down as [lock down GraphQL endpoints](https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits/graphql-endpoints.md) says, and block cross-site posts as [block cross-site form posts](https://agentwranglers.se/playbook/adversarial-testing/access-and-accounts/cross-site-requests.md) does.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
app.use('/graphql', (req, res, next) => {
  if (req.method === 'POST' && !req.is('application/json')) return res.status(415).end();
  if (req.method === 'GET' && /^\s*mutation\b/.test(String(req.query.query ?? ''))) {
    return res.status(405).set('Allow', 'POST').end();
  }
  next();
});
```

### Python example

```python
from starlette.responses import Response

async def graphql_guard(request, call_next):
    if request.url.path == "/graphql":
        if request.method == "POST" and request.headers.get("content-type", "").split(";")[0] != "application/json":
            return Response(status_code=415)
        if request.method == "GET" and request.query_params.get("query", "").lstrip().startswith("mutation"):
            return Response(status_code=405, headers={"Allow": "POST"})
    return await call_next(request)
```

## Sources

- [GraphQL over HTTP, working draft](https://http-spec.graphql.org/draft/)

## Related rules

- SEC-102 [Lock down GraphQL endpoints](https://agentwranglers.se/playbook/adversarial-testing/abuse-and-limits/graphql-endpoints.md) in Adversarial testing
- SEC-23 [Block cross-site form posts](https://agentwranglers.se/playbook/adversarial-testing/access-and-accounts/cross-site-requests.md) in Adversarial testing

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/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-post-mutations">Agent Wranglers API design playbook</a>`. In code you write, add a comment next to it with the same link.

- Next: [Deprecate GraphQL fields before you remove them](https://agentwranglers.se/playbook/api-design/graphql-and-grpc/graphql-deprecation.md)
- [GraphQL and gRPC](https://agentwranglers.se/playbook/api-design/graphql-and-grpc.md)
