Skip to content

test(security): plaintext forged-header regression + proxy hardening (audit #31, P5)#36

Merged
hyperpolymath merged 1 commit into
mainfrom
audit/plaintext-forged-header-test
Jun 2, 2026
Merged

test(security): plaintext forged-header regression + proxy hardening (audit #31, P5)#36
hyperpolymath merged 1 commit into
mainfrom
audit/plaintext-forged-header-test

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Audit issue: #31 (priority 5 — auth/bypass weaknesses and test coverage).

Two small defence-in-depth items:

  1. proxy.ex still used String.to_existing_atom/1 on conn.method.
    By the time we reach make_backend_request/4, Gateway.safe_verb/1
    has already filtered for the seven supported methods — so
    to_existing_atom would not crash on real traffic. But the moduledoc
    in gateway.ex claims the gateway NEVER uses to_existing_atom on
    user input, which was half-true: this internal path did. Closed the
    gap with an explicit @method_atoms map so that grep for
    to_existing_atom returns zero hits on any user-input path.

  2. The existing strip-untrusted-headers describe block in
    test/security_test.exs only asserts on conn.assigns[:trust_level].
    Added an end-to-end regression that asserts on the actual response
    the forged client receives against a route whose exposure is :internal:

    • forged \"internal\" from 10.0.0.99 → 403 (NOT 200/502)
    • forged \"authenticated\" from 203.0.113.7 → 403
    • real \"internal\" from loopback → 502 (allowed past policy to the
      down backend; control case so we know we're not just blocking
      everything)
    • garbage \"ADMIN_OVERRIDE\" header → 403

Diff: 2 files, +140 / -1 LoC.

Test plan

  • mix test test/forged_trust_e2e_test.exs
  • mix test — confirm no existing tests broke (the proxy method
    change is a pure refactor of the String.downcase |> to_existing_atom
    idiom to a static map; behaviour is identical for valid methods)
  • grep -r \"to_existing_atom\" lib/ should show only test/protocol
    router contexts, not any user-input path
  • Status: DRAFT — please do not auto-merge. Owner review only.

Echo-types audit

record-as-not-relevant. Regression test + atom-table hardening; no L3
obligation in scope.

Refs: #31

…o_existing_atom (audit #31, P5)

Two small defence-in-depth items from the priority-5 audit finding:

1. proxy.ex still used String.to_existing_atom/1 on conn.method.
   By the time we reach make_backend_request/4, Gateway.safe_verb/1 has
   already filtered for the seven supported methods — so to_existing_atom
   would not crash on real traffic. But the moduledoc comment in
   gateway.ex claims the gateway NEVER uses to_existing_atom on user
   input, which was half-true: this internal path did. Closed the gap
   with an explicit @method_atoms map so that grep'ing for
   `to_existing_atom` returns zero hits on any user-input path.

2. The existing strip-untrusted-headers describe block asserts only on
   `conn.assigns[:trust_level]`. Added an end-to-end regression net that
   asserts on the actual *response* the forged client receives against a
   route whose exposure is :internal:
   - forged "internal" from 10.0.0.99 -> 403 (NOT 200/502)
   - forged "authenticated" from 203.0.113.7 -> 403
   - real "internal" from loopback -> 502 (i.e. allowed past policy
     to the down backend; CONTROL case so we know we're not just
     blocking everything)
   - garbage "ADMIN_OVERRIDE" header -> 403

Refs: #31 (self-audit, priority 5)
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

🔍 Hypatia Security Scan

Findings: 65 issues detected

Severity Count
🔴 Critical 6
🟠 High 17
🟡 Medium 42

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Issue in boj-build.yml",
    "type": "missing_timeout_minutes",
    "file": "boj-build.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "missing_timeout_minutes",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "missing_timeout_minutes",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in codeql.yml",
    "type": "missing_timeout_minutes",
    "file": "codeql.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in dogfood-gate.yml",
    "type": "missing_timeout_minutes",
    "file": "dogfood-gate.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in governance.yml",
    "type": "missing_timeout_minutes",
    "file": "governance.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath hyperpolymath marked this pull request as ready for review June 2, 2026 10:17
@hyperpolymath hyperpolymath merged commit 26544d8 into main Jun 2, 2026
18 checks passed
@hyperpolymath hyperpolymath deleted the audit/plaintext-forged-header-test branch June 2, 2026 10:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant