#23420: Gateway: tighten WS connect schema bounds and validation
app: web-ui
gateway
size: S
trusted-contributor
## Summary
Describe the problem and fix in 2–5 bullets:
- Problem: WS `connect` payload strings/collections had minimal bounds, allowing very large metadata in handshake frames.
- Why it matters: large connect metadata increases parser ambiguity and memory pressure before auth/session logic.
- What changed: tightened TypeBox schemas for request frame IDs/methods and `connect` metadata (max lengths, max items/properties) while preserving existing required fields and behavior.
- What did NOT change (scope boundary): auth logic, role/scope authorization flow, and non-connect method handling.
## Change Type (select all)
- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Docs
- [x] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [x] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [ ] Integrations
- [x] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Closes #
- Related #
## User-visible / Behavior Changes
Oversized handshake metadata and overlong request IDs/method names are now rejected during schema validation with the existing invalid-connect/invalid-request error path.
## Security Impact (required)
- New permissions/capabilities? (`No`)
- Secrets/tokens handling changed? (`No`)
- New/changed network calls? (`No`)
- Command/tool execution surface changed? (`No`)
- Data access scope changed? (`No`)
- If any `Yes`, explain risk + mitigation:
## Repro + Verification
### Environment
- OS: macOS
- Runtime/container: Node 22 + pnpm
- Model/provider: N/A
- Integration/channel (if any): Gateway WS protocol
- Relevant config (redacted): default gateway config
### Steps
1. Send WS `connect` with oversized client metadata or overlong request frame id.
2. Observe schema validation failure.
3. Send valid connect frame and verify success path unchanged.
### Expected
- Invalid oversized metadata rejected early.
- Valid connect frames still accepted.
### Actual
- Matches expected behavior.
## Evidence
Attach at least one:
- [x] Failing test/log before + passing after
- [ ] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)
## Human Verification (required)
What you personally verified (not just CI), and how:
- Verified scenarios: protocol validator tests for unknown fields/max lengths and targeted gateway auth e2e invalid-connect case.
- Edge cases checked: unknown connect params field and unknown request-frame property still rejected; valid baseline connect still accepted.
- What you did **not** verify: full gateway e2e matrix beyond the targeted invalid-connect auth case.
## Compatibility / Migration
- Backward compatible? (`Mostly`)
- Config/env changes? (`No`)
- Migration needed? (`No`)
- If yes, exact upgrade steps:
## Failure Recovery (if this breaks)
- How to disable/revert this change quickly: revert this PR.
- Files/config to restore: `src/gateway/protocol/schema/frames.ts`.
- Known bad symptoms reviewers should watch for: legacy clients with unusually large connect metadata rejected at handshake.
## Risks and Mitigations
- Risk: strict bounds may reject outlier client metadata values.
- Mitigation: limits are set well above expected real values and validated by protocol tests + targeted e2e handshake test.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Tightens WebSocket `connect` frame validation by adding maximum length constraints to prevent oversized metadata in handshake frames. This reduces parser ambiguity and memory pressure before authentication logic executes.
- Adds sensible bounds for all connect metadata (256 char limit for most text fields, 8KB for paths/secrets, 16KB for signatures)
- Adds `maxItems` constraints to arrays (256 items max) and `maxProperties` to permissions (256 max)
- New test file validates bounds and ensures unknown fields are rejected via `additionalProperties: false`
- Existing valid connect flows remain unchanged (baseline compatibility maintained)
<h3>Confidence Score: 5/5</h3>
- Safe to merge - pure security hardening with comprehensive validation tests and no behavioral changes to valid clients
- All changes are additive security constraints that reject edge-case oversized payloads while preserving valid client behavior. New comprehensive tests validate both the rejection paths (oversized metadata, unknown fields) and acceptance paths (valid baseline connect). Limits are well above typical real-world values (256 chars for display names, 8KB for tokens, etc.)
- No files require special attention - both changed files are schema definitions with matching test coverage
<sub>Last reviewed commit: b4b1bef</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#20381: feat(gateway): make chat history byte limit configurable via `gatew...
by mgratch · 2026-02-18
77.9%
#23361: Gateway: reject scope assertions without identity binding
by bmendonca3 · 2026-02-22
76.9%
#12802: fix(gateway): default unscoped operator connections to read-only
by yubrew · 2026-02-09
76.0%
#23714: Gateway: add websocket ingress limits for DoS hardening
by bmendonca3 · 2026-02-22
75.5%
#13679: feat(gateway): make WebSocket maxPayload configurable
by andydoucet · 2026-02-10
75.1%
#22381: Security/Gateway: block cross-origin silent auto-pairing in auth mo...
by bmendonca3 · 2026-02-21
74.2%
#23410: Gateway: require prefixes for hook request session-key overrides
by bmendonca3 · 2026-02-22
74.2%
#19255: feat(gateway): add WebSocket connection metrics monitoring
by Wike-CHI · 2026-02-17
74.1%
#23355: Gateway: fail closed on untrusted proxy headers
by bmendonca3 · 2026-02-22
73.9%
#9178: Fix: GatewayClient queueConnect() setTimeout never fires
by vishaltandale00 · 2026-02-04
73.8%