Skip to content

fix(security): close the open security advisories for v3.8.50 - #11028

Merged
diegosouzapw merged 5 commits into
release/v3.8.50from
fix/sec-advisories-v3850
Aug 21, 2026
Merged

diegosouzapw merged 5 commits into
release/v3.8.50from
fix/sec-advisories-v3850

Conversation

@diegosouzapw

@diegosouzapw diegosouzapw commented Aug 21, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Full triage + fix pass over the open GitHub Security Advisories against
release/v3.8.50. Every STILL-REAL / PARTIAL finding is fixed here (TDD:
failing test → fix → green); the already-fixed, false-positive and
junk advisories were closed separately. Full triage: _tasks/research/2026-08-21-security-advisories-triage.md.

Each fix credits its reporter in the commit body. ⚠️ base-red inherited: #9985.

RCE / auth-bypass / SSRF

Advisory Sev Fix
GHSA-jphr-2gw7-xrwp / GHSA-hf57-cqmx-p4gr Critical ACP version-probe restricted to a version flag (no node -e sink)
GHSA-jvqc-mp9f-q936 High authz matcher matches client aliases case-insensitively (/V1/… no longer skips it)
GHSA-mghq-58h3-qcqj High /api/db-backups in ALWAYS_PROTECTED (no anonymous DB dump/replace)
GHSA-mg76-rhpx-gvw3 / GHSA-gxv4-955v-v6cm High OAuth import/auto-import require manage scope + auto-import routed through LOCAL_ONLY
GHSA-wgwc-crjm-pmwv Low credential auto-import routes excluded from PUBLIC → reach the LOCAL_ONLY gate
GHSA-4f49-hj64-448x High SSRF guard before every executor fetch() (base/glm/nlpcloud)
GHSA-7x63-xvp5-w2jc High AWS region validated on the device-code route before any outbound fetch
GHSA-v54m-6rm3-p565 High /a2a honors REQUIRE_API_KEY
GHSA-cpv3-xr7r-xf8q High MCP memory tools bind to the authenticated caller (IDOR)
GHSA-2phc-xp22-9f56 / GHSA-m3cj-q455-6wfr Med per-key policy enforced for a bare x-api-key
GHSA-9q3h-mjm5-f4gj (F1) Mod chatgpt-web-codex-doctor added to the spawn-veto

Credential / info exposure & hardening (operator chose "harden without breaking")

Advisory Sev Fix
GHSA-62vw-4m6w-cqqq / GHSA-p855-p6fm-76r3 High WebDAV password masked from non-management callers
GHSA-7px7-29v2-m97p Med CORS Origin echoed only for credential-carrying/preflight requests (anonymous cross-origin no longer)
GHSA-mvf8-qc78-5mxm High health payload reduced for anonymous callers; REQUIRE_API_KEY kept false (local-first) per operator choice
GHSA-wg9p-6m2g-4v27 Med embedded-service port adoption is now opt-in (a 2xx no longer proves identity)

Validation

  • npm run typecheck:core clean · ESLint clean on all changed files (only pre-existing suppressed no-restricted-imports remain, untouched)
  • 357 tests green across the touched areas (authz, cors, acp, api-key, mcp, executor, oauth, services, a2a, health) + every new TDD test
  • Next's build-time matcher validator accepts the case-insensitive matcher

Notes / deferred (documented in the triage doc)

  • c7cg's flagship "shipped shared secrets" claim is a false positive (.env never in the tarball; per-install randomBytes generation; fail-closed login). The INITIAL_PASSWORD=CHANGEME warning and 0.0.0.0 bind are documented local-first posture.
  • 9q3h F2 (strict-loopback vs loopback-OR-LAN doc divergence) + F3 (a tier→veto CI gate) are defense-in-depth follow-ups; F1 is fixed here.
  • The embedded-UI CSP hardening (wg9p second half) is a follow-up.

…ents

POST /api/acp/agents lets a client register a custom agent controlling both
`binary` and `versionCommand`. The version probe runs execFileSync(binary,
args); the binary-match check alone still admits an eval argument on a
matching interpreter (`node -e …`, `python -c …`, `ruby -e …`), which is
arbitrary code execution with no shell metacharacter. `/api/acp/agents` is
already LOCAL_ONLY (#7948) so the remote/anonymous vector is closed, but a
loopback/LAN caller with requireLogin=false — or any authenticated caller —
could still reach the sink.

resolveVersionProbe() now restricts untrusted (requireBinaryMatch) probes to
a bare binary or a single recognized version flag, so no code-running argument
can pass. Built-in agents (requireBinaryMatch=false) are unaffected.

Reported by @c111mb3r via GHSA-jphr-2gw7-xrwp and GHSA-hf57-cqmx-p4gr.
…eLogin=false

/api/db-backups/export and /import sat outside ALWAYS_PROTECTED_API_PATHS, so with
requireLogin=false an anonymous caller could stream the full SQLite database
(api_keys, provider credentials, OAuth tokens) or replace it wholesale. Adding
/api/db-backups to the Tier-2 allowlist requires a credential for all three
sibling routes, matching the trade-off /api/settings/database already makes.

Reported by @ntdat812 via GHSA-mghq-58h3-qcqj.
…hz matcher

Next compiles the proxy matcher from `regexp.source` only, dropping
path-to-regexp's case-insensitive flag, so `/v1/:path*` never matched `/V1/...`
while the rewrite layer (flag kept) still routed it to the handler — an
unauthenticated inference bypass via uppercase / mixed-case paths (/V1, /V1BETA,
/CHAT, /RESPONSES, /CODEX, /MODELS). Expressing the casing inside a
path-to-regexp custom group (`([vV]1)`) survives the flag-drop. classify.ts
normalizes the control segment case so uppercase aliases resolve to CLIENT_API
(honoring REQUIRE_API_KEY) instead of the management fallback.

Reported by @Evgeny-SPB via GHSA-jvqc-mp9f-q936.
The manage-scope bypass veto's precise early-deny keys on
SPAWN_CAPABLE_PATTERNS, but /api/providers/{id}/chatgpt-web-codex-doctor — a
LOCAL_ONLY route that spawns a subprocess via getTunnelRuntimeStatus() — was in
LOCAL_ONLY_API_PATTERNS without a matching spawn-capable pattern, so the two
layers had drifted. Add the pattern plus a regression test asserting every
regex-tier LOCAL_ONLY spawn route is covered, so the veto's exact early-deny
stays in sync with the tier.

Reported by @Zandereins via GHSA-9q3h-mjm5-f4gj (finding 1).
Keeps the new security regression tests within the tests/ no-explicit-any budget and removes an unused eslint-disable directive flagged by the linter.
@diegosouzapw
diegosouzapw merged commit 6082924 into release/v3.8.50 Aug 21, 2026
13 of 22 checks passed
@diegosouzapw diegosouzapw changed the title fix(security): close 4 STILL-REAL advisory findings (ACP RCE hardening, db-backups tier, uppercase authz bypass, spawn-veto drift) fix(security): close the open security advisories for v3.8.50 Aug 21, 2026
Sa3id23 pushed a commit to Sa3id23/OmniRoute that referenced this pull request Aug 21, 2026
…g, db-backups tier, uppercase authz bypass, spawn-veto drift) (cheaper-inference#11028)

⭐5 — 4 achados STILL-REAL de advisories de segurança, cada um com TDD (RED→GREEN) e crédito ao reporter original: ACP RCE hardening (resolveVersionProbe), db-backups Tier-2 allowlist, uppercase authz bypass (matcher case-insensitive), spawn-veto drift (chatgpt-web-codex-doctor). typecheck/lint limpos, suíte authz/acp/cors verde. UNSTABLE é o base-red inherited cheaper-inference#9985, já documentado no corpo da PR.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…g, db-backups tier, uppercase authz bypass, spawn-veto drift) (cheaper-inference#11028)

⭐5 — 4 achados STILL-REAL de advisories de segurança, cada um com TDD (RED→GREEN) e crédito ao reporter original: ACP RCE hardening (resolveVersionProbe), db-backups Tier-2 allowlist, uppercase authz bypass (matcher case-insensitive), spawn-veto drift (chatgpt-web-codex-doctor). typecheck/lint limpos, suíte authz/acp/cors verde. UNSTABLE é o base-red inherited cheaper-inference#9985, já documentado no corpo da PR.
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.

2 participants