@@ -18,39 +18,49 @@ environments, these solutions often introduce complexity, fragility, and securit
1818
1919### Memory exhaustion from repeated variables
2020
21- GraphQL operations allow the same variable to be referenced multiple times. If a file upload variable is used more than
22- once, its stream may be consumed multiple times—or worse, not at all. This can lead to unpredictable behavior or denial of service (DoS).
21+ GraphQL operations allow the same variable to be referenced multiple times. If a file upload variable is reused, the underlying
22+ stream may be read multiple times or prematurely drained. This can result in incorrect behavior or memory exhaustion.
23+
24+ A safe practice is to use trusted documents or a validation rule to ensure each upload variable is referenced exactly once.
2325
2426### Stream leaks on failed operations
2527
26- GraphQL executes in phases: validation, then execution. If an error occurs during validation or authorization, your
27- server might never reach the resolver that consumes a file stream. If file streams are left unconsumed, memory usage can
28- spike, potentially exhausting server resources.
28+ GraphQL executes in phases: validation, then execution. If validation fails or an authorization check blocks execution, uploaded
29+ file streams may never be consumed. If your server buffers or retains these streams, it can cause memory leaks.
30+
31+ To avoid this, consider writing incoming files to temporary storage immediately, and passing references (like filenames) into
32+ resolvers. Ensure this storage is cleaned up after request completion, regardless of success or failure.
2933
3034### Cross-Site Request Forgery (CSRF)
3135
32- ` multipart/form-data ` is classified as a “simple” request by CORS and does not trigger preflight checks . Without strict CSRF
33- protections, malicious sites may be able to upload files on behalf of unsuspecting users .
36+ ` multipart/form-data ` is classified as a “simple” request in the CORS spec and does not trigger a preflight check . Without
37+ explicit CSRF protection, your GraphQL server may unknowingly accept uploads from malicious origins .
3438
3539### Oversized or excess payloads
3640
37- Attackers can upload arbitrarily large files or extra files not referenced in the GraphQL operation. If your server accepts and
38- buffers these files in memory, you may face reliability issues or be vulnerable to resource exhaustion.
41+ Attackers may submit very large uploads or include extraneous files under unused variable names. Servers that accept and
42+ buffer these can be overwhelmed.
43+
44+ Enforce request size caps and reject any files not explicitly referenced in the map field of the multipart payload.
3945
4046### Untrusted file metadata
4147
42- Uploaded file names, MIME types, and even contents are arbitrary and should be treated as untrusted input. Failing to sanitize
43- file names can lead to path traversal vulnerabilities. Assuming a file’s MIME type is safe can lead to parsing exploits.
48+ Information such as file names, MIME types, and contents should never be trusted. To mitigate risk:
49+
50+ - Sanitize filenames to prevent path traversal or injection issues.
51+ - Sniff file types independently of declared MIME types, and reject mismatches.
52+ - Validate file contents. Be aware of format-specific exploits like zip bombs or maliciously crafted PDFs.
4453
4554## Recommendation: Use signed URLs
4655
47- The most secure and scalable approach is to ** avoid uploading files through GraphQL entirely** . Instead:
56+ The most secure and scalable approach is to avoid uploading files through GraphQL entirely. Instead:
4857
49581 . Use a GraphQL mutation to request a signed upload URL from your storage provider (e.g., Amazon S3).
50592 . Upload the file directly from the client using that URL.
51603 . Submit a second mutation to associate the uploaded file with your application’s data.
5261
53- This approach isolates the file upload concern to infrastructure purpose-built for it, while keeping GraphQL focused on structured data.
62+ This separates responsibilities cleanly, protects your server from binary data handling, and aligns with best practices for
63+ modern web architecture.
5464
5565## If you still choose to support uploads
5666
0 commit comments