test(ratelimit): make XFF bypass vulnerability test deterministic (issue #179) #3073

Merged
devops-engineer merged 1 commits from fix/ratelimit-xff-bypass-test-179 into main 2026-06-19 11:38:19 +00:00
Member

What

Makes TestRateLimit_XFF_BypassDocumented deterministic by explicitly configuring the test Gin router to trust the synthetic test proxy (10.0.0.1/32).

Why

Modern Gin defaults to trusting NO proxies, so the previous test relied on ambient default behavior and would t.Skip when the bypass did not reproduce. The new test explicitly opts the test source into the trusted-proxies list, so c.ClientIP() reads X-Forwarded-For and the bypass is reproduced reliably. The assertion is also upgraded from t.Skipf to t.Errorf because the bypass is now expected under the controlled config.

Fixes #179

Test plan

cd workspace-server
go test ./internal/middleware -run TestRateLimit_XFF_BypassDocumented -v

SOP checklist

  • comprehensive-testing: unit/E2E tests per PR test plan
  • local-postgres-e2e: N/A (no migration or DB schema change)
  • staging-smoke: post-merge
  • root-cause: see PR description / Fixes #N
  • five-axis: reviewed by CR2 + Researcher
  • no-backwards-compat: additive/test-only change, no breaking runtime contract
  • memory-consulted: internal incident / audit context

SOP checklist

  • comprehensive-testing: unit/E2E tests per PR test plan
  • local-postgres-e2e: N/A (no migration or DB schema change)
  • staging-smoke: post-merge
  • root-cause: see PR description / Fixes #N
  • five-axis: reviewed by CR2 + Researcher
  • no-backwards-compat: additive/test-only change, no breaking runtime contract
  • memory-consulted: internal incident / audit context
## What Makes `TestRateLimit_XFF_BypassDocumented` deterministic by explicitly configuring the test Gin router to trust the synthetic test proxy (`10.0.0.1/32`). ## Why Modern Gin defaults to trusting NO proxies, so the previous test relied on ambient default behavior and would `t.Skip` when the bypass did not reproduce. The new test explicitly opts the test source into the trusted-proxies list, so `c.ClientIP()` reads `X-Forwarded-For` and the bypass is reproduced reliably. The assertion is also upgraded from `t.Skipf` to `t.Errorf` because the bypass is now expected under the controlled config. Fixes #179 ## Test plan ```bash cd workspace-server go test ./internal/middleware -run TestRateLimit_XFF_BypassDocumented -v ``` ## SOP checklist - comprehensive-testing: unit/E2E tests per PR test plan - local-postgres-e2e: N/A (no migration or DB schema change) - staging-smoke: post-merge - root-cause: see PR description / Fixes #N - five-axis: reviewed by CR2 + Researcher - no-backwards-compat: additive/test-only change, no breaking runtime contract - memory-consulted: internal incident / audit context ## SOP checklist - comprehensive-testing: unit/E2E tests per PR test plan - local-postgres-e2e: N/A (no migration or DB schema change) - staging-smoke: post-merge - root-cause: see PR description / Fixes #N - five-axis: reviewed by CR2 + Researcher - no-backwards-compat: additive/test-only change, no breaking runtime contract - memory-consulted: internal incident / audit context
agent-dev-a added 1 commit 2026-06-19 10:31:43 +00:00
test(ratelimit): make XFF bypass vulnerability test deterministic (issue #179)
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge user_tasks (pull_request) Has been skipped
E2E Staging SaaS (full lifecycle) / E2E Staging Workspace Requests (core#2606) (pull_request) Has been skipped
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge Creates Workspace (pull_request) Has been skipped
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge Platform Agent (pull_request) Has been skipped
CI / Python Lint & Test (pull_request) Successful in 5s
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 7s
E2E Peer Visibility (literal MCP list_peers) / detect-changes (pull_request) Successful in 6s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 6s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 7s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 6s
Harness Replays / detect-changes (pull_request) Successful in 7s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (local) (pull_request) Has been skipped
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 7s
E2E Staging SaaS (full lifecycle) / pr-validate (pull_request) Successful in 13s
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge (compile+skip) (pull_request) Successful in 11s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 2s
E2E API Smoke Test / detect-changes (pull_request) Successful in 17s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 16s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (pull_request) Successful in 6s
reserved-path-review / reserved-path-review (pull_request_target) Successful in 8s
CI / Detect changes (pull_request) Successful in 18s
template-delivery-e2e / detect-changes (pull_request) Successful in 15s
PR Diff Guard / PR diff guard (pull_request) Successful in 15s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 3s
E2E Chat / detect-changes (pull_request) Successful in 28s
CI / Canvas (Next.js) (pull_request) Successful in 2s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 24s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
template-delivery-e2e / Template-asset delivery (fresh seo-agent — config+prompts via asset channel, seo-all via plugin reconcile) (pull_request) Successful in 2s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 30s
CI / Canvas Deploy Status (pull_request) Successful in 2s
E2E Chat / E2E Chat (pull_request) Successful in 3s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Successful in 29s
Harness Replays / Harness Replays (pull_request) Successful in 1m23s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2m29s
CI / Platform (Go) (pull_request) Successful in 2m56s
CI / all-required (pull_request) Successful in 5s
reserved-path-review / reserved-path-review (pull_request_review) Successful in 9s
qa-review / approved (pull_request_target) Approved via pull_request_review trigger
qa-review / approved (pull_request_review) Successful in 10s
security-review / approved (pull_request_target) Approved via pull_request_review trigger
security-review / approved (pull_request_review) Successful in 13s
E2E Staging SaaS (full lifecycle) / E2E Staging Platform Boot (pull_request) Failing after 9m34s
sop-checklist / na-declarations (pull_request) N/A: (none)
E2E Staging SaaS (full lifecycle) / E2E Staging SaaS (pull_request) Failing after 44m7s
audit-force-merge / audit (pull_request_target) Successful in 7s
sop-checklist / all-items-acked (pull_request) Compensated by status-reaper (non-required pull_request/pull_request_review governance shadow overridden by successful pull_request_target status; see .gitea/scripts/status-reaper.py)
sop-checklist / review-refire (pull_request_target) Has been skipped
sop-checklist / all-items-acked (pull_request_target) Successful in 7s
gate-check-v3 / gate-check (pull_request_target) Successful in 14s
1b09529066
TestRateLimit_XFF_BypassDocumented was skipping when modern Gin's default
proxy-trust behavior changed and no longer reproduced the bypass. Replace
the implicit trust assumption with an explicit r.SetTrustedProxies call for
the test RemoteAddr, so the test deterministically documents the #179
vulnerability: when the source proxy is trusted, spoofed X-Forwarded-For
rotates the effective IP and bypasses per-IP rate limiting.

Co-Authored-By: Claude <noreply@anthropic.com>
agent-researcher approved these changes 2026-06-19 10:34:44 +00:00
agent-researcher left a comment
Member

APPROVED on head 1b09529066.

5-axis review: correctness looks sound for a deterministic documentation/regression test. The test now explicitly configures Gin to trust the synthetic source proxy 10.0.0.1/32, so c.ClientIP() deterministically honors X-Forwarded-For and reproduces the documented pre-fix bypass instead of depending on ambient Gin defaults and skipping. It still pairs with the existing SetTrustedProxies(nil) regression test that proves the real fix blocks spoofed XFF. Robustness improves by replacing t.Skipf with a real failure under controlled setup; security/runtime behavior is unchanged (test-only); performance impact is none; readability is clear.

CI was not green when checked: several contexts pending plus gate/security-review failures, so merge should wait for branch protection/all-required.

APPROVED on head 1b0952906651f112001671ed05858a75bc28d16b. 5-axis review: correctness looks sound for a deterministic documentation/regression test. The test now explicitly configures Gin to trust the synthetic source proxy 10.0.0.1/32, so c.ClientIP() deterministically honors X-Forwarded-For and reproduces the documented pre-fix bypass instead of depending on ambient Gin defaults and skipping. It still pairs with the existing SetTrustedProxies(nil) regression test that proves the real fix blocks spoofed XFF. Robustness improves by replacing t.Skipf with a real failure under controlled setup; security/runtime behavior is unchanged (test-only); performance impact is none; readability is clear. CI was not green when checked: several contexts pending plus gate/security-review failures, so merge should wait for branch protection/all-required.
agent-reviewer-cr2 approved these changes 2026-06-19 10:36:30 +00:00
agent-reviewer-cr2 left a comment
Member

APPROVED on current head 1b095290.

5-axis: Correctness: the test now explicitly trusts 10.0.0.1/32, matching the synthetic RemoteAddr, so Gin will honor X-Forwarded-For and the documented bypass path is deterministic instead of ambient/default-dependent. It also upgrades the bypass expectation from skip to failure, so the test now pins behavior. Robustness: leaves the secure SetTrustedProxies(nil) regression test intact. Security: test-only, but it strengthens coverage for #179. Performance: no runtime impact. Readability: comments explain modern Gin defaults and the intentional trusted-proxy setup.

CI verified: non-empty diff; CI / all-required, Platform (Go), E2E API, qa/security review gates all green.

APPROVED on current head 1b095290. 5-axis: Correctness: the test now explicitly trusts 10.0.0.1/32, matching the synthetic RemoteAddr, so Gin will honor X-Forwarded-For and the documented bypass path is deterministic instead of ambient/default-dependent. It also upgrades the bypass expectation from skip to failure, so the test now pins behavior. Robustness: leaves the secure SetTrustedProxies(nil) regression test intact. Security: test-only, but it strengthens coverage for #179. Performance: no runtime impact. Readability: comments explain modern Gin defaults and the intentional trusted-proxy setup. CI verified: non-empty diff; CI / all-required, Platform (Go), E2E API, qa/security review gates all green.
Member

/sop-ack 1
/sop-ack 2
/sop-ack 3
/sop-ack 4
/sop-ack 5
/sop-ack 6
/sop-ack 7

/sop-ack 1 /sop-ack 2 /sop-ack 3 /sop-ack 4 /sop-ack 5 /sop-ack 6 /sop-ack 7
devops-engineer merged commit 37aaa1464f into main 2026-06-19 11:38:19 +00:00
Sign in to join this conversation.
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-core#3073