@@ -18,39 +18,49 @@ environments, these solutions often introduce complexity, fragility, and securit
18
18
19
19
### Memory exhaustion from repeated variables
20
20
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.
23
25
24
26
### Stream leaks on failed operations
25
27
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.
29
33
30
34
### Cross-Site Request Forgery (CSRF)
31
35
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 .
34
38
35
39
### Oversized or excess payloads
36
40
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.
39
45
40
46
### Untrusted file metadata
41
47
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.
44
53
45
54
## Recommendation: Use signed URLs
46
55
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:
48
57
49
58
1 . Use a GraphQL mutation to request a signed upload URL from your storage provider (e.g., Amazon S3).
50
59
2 . Upload the file directly from the client using that URL.
51
60
3 . Submit a second mutation to associate the uploaded file with your application’s data.
52
61
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.
54
64
55
65
## If you still choose to support uploads
56
66
0 commit comments