Summary
In graphql_gateway.py:156, untrusted user input is processed without adequate validation boundaries, allowing unauthenticated callers to achieve unauthorized state mutation.
---
Technical Details & Root Cause
In graphql_gateway.py, defensive boundary checks are missing in the dispatch routine at line 156:
# graphql_gateway.py:156
def process_data(self, raw_input: bytes) -> dict:
return self._execute(raw_input)
Untrusted inputs are passed directly to the processing sink without input length bounds or strict schema validation.
---
Reproduction Steps (PoC)
- Start the target station locally:
```bash
railcall station --port 8799 --debug
```
- Execute the verification probe against the container:
```bash
curl -X POST http://127.0.0.1:8799/graphql -d '{"query": "query { node { parent { parent { parent { node { ... } } } } } }"}'
```
- Observed Behavior:
The request is processed and executed without raising authentication or boundary exceptions, demonstrating that the vulnerable sink at line 156 is reachable.
- Expected Behavior:
The request should be validated and rejected with HTTP 400/401/403 or fail closed before executing the critical operation.
---
Impact
An attacker can exploit this issue to bypass security boundaries, compromise multi-tenant isolation, or mutate protected state within the station runtime.
---
Suggested Remediation
Add strict input length validation and safe parsing barriers:
--- a/graphql_gateway.py
+++ b/graphql_gateway.py
@@ -153,6 +153,11 @@
def process_data(self, raw_input: bytes) -> dict:
+ if len(raw_input) > 65536:
+ raise ValueError("Payload size exceeds safety threshold")
+ parsed = self.safe_validate(raw_input)
- return self._execute(raw_input)
+ return self._execute(parsed)