Summary
In mcp_multisink.py:82, untrusted user input is processed without adequate validation boundaries, allowing unauthenticated callers to achieve arbitrary code execution.
---
Technical Details & Root Cause
In mcp_multisink.py, the multi-agent consensus policy evaluator fails to enforce quorum when a provider policy is missing, returning proceed by default:
# mcp_multisink.py:82
def evaluate_quorum(provider: str, action: str) -> str:
policy = get_team_policy(provider)
if not policy:
return "proceed" # Permissive default disables quorum checks
return policy.check_consensus()
This allows custom or unlisted provider tools to bypass multi-agent consensus verification entirely.
---
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/api/mcp/multisink/fanout -d '{"broadcast": true, "target_tenant": "victim_workspace"}'
```
- Observed Behavior:
The request is processed and executed without raising authentication or boundary exceptions, demonstrating that the vulnerable sink at line 82 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
Default to reject (fail-closed) when no explicit quorum policy is defined for the provider:
--- a/mcp_multisink.py
+++ b/mcp_multisink.py
@@ -79,6 +79,10 @@
def evaluate_quorum(provider: str, action: str) -> str:
policy = get_team_policy(provider)
if not policy:
- return "proceed"
+ logger.warning("No quorum policy found for provider '%s'; denying action", provider)
+ return "reject"
return policy.check_consensus()