GraphQL Non-JSON Queries over POST: Potential CSRF Vulnerability
Description
The GraphQL endpoint accepts queries submitted via POST requests with application/x-www-form-urlencoded Content-Type instead of requiring JSON format. This configuration weakness allows attackers to craft simple HTML forms that can submit GraphQL operations, bypassing the browser's same-origin policy protections that normally prevent cross-site requests with custom JSON content types. This creates an exploitable Cross-Site Request Forgery (CSRF) vulnerability.
Remediation
Configure your GraphQL server to reject POST requests that do not use application/json Content-Type. Implement the following protections:
1. Enforce JSON Content-Type validation: Reject requests with Content-Type other than application/json at the server level.
// Express.js example
app.post('/graphql', (req, res, next) => {
const contentType = req.headers['content-type'];
if (!contentType || !contentType.includes('application/json')) {
return res.status(415).json({ error: 'Content-Type must be application/json' });
}
next();
});2. Implement CSRF tokens: For additional defense-in-depth, require anti-CSRF tokens in custom headers (e.g., X-CSRF-Token) for all state-changing operations.
3. Use SameSite cookies: Set the SameSite attribute to 'Strict' or 'Lax' on authentication cookies to prevent them from being sent with cross-site requests.
4. Verify request origin: Validate the Origin and Referer headers to ensure requests originate from trusted domains.