mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 13:38:31 +00:00
fix(security): scope OAuth callback postMessage targets and re-enable TLS verification on DNS-bypass fetch (#998)
Two findings, neither blocked by anything else:
1. src/app/callback/page.js — the OAuth callback page posted the
{ code, state } payload to window.opener with targetOrigin "*", so any
page that opened the popup against the well-known redirect_uri received
the live OAuth code. The expectedOrigins list was already computed but
never used. Iterate over it and pass the origin per send.
2. open-sse/utils/proxyFetch.js — createBypassRequest() set
rejectUnauthorized: false on the HTTPS request that runs after the
Google-DNS-resolved real-IP fallback (used for cloudcode-pa.googleapis,
GitHub Copilot, Cursor, AWS LLM endpoints). Combined with servername:
parsedUrl.hostname this gave SNI-correct connections that nonetheless
ignored cert validation, so an on-path attacker could swap in their
own cert and read the user's API tokens / prompts. Drop the flag.
Detected by Aeon + semgrep (javascript.browser.security.wildcard-postmessage-configuration
+ problem-based-packs.insecure-transport.js-node.bypass-tls-verification).
Severity: HIGH (#1) / MEDIUM (#2).
CWEs: CWE-1385 (#1), CWE-295 (#2).
Co-authored-by: aeonframework <aeon@aeonframework.dev>
This commit is contained in:
co-authored by
aeonframework
parent
c7c1074f28
commit
52c38cf94c
@@ -155,8 +155,13 @@ async function createBypassRequest(parsedUrl, realIP, options) {
|
||||
socket.connect(HTTPS_PORT, realIP, () => {
|
||||
const reqOptions = {
|
||||
socket,
|
||||
// SNI + cert hostname are validated against the hostname the caller
|
||||
// asked for, not the IP we connected to. This keeps the DNS-bypass
|
||||
// (avoiding /etc/hosts MITM) while still rejecting on-path attackers
|
||||
// that present a different cert. The MITM_BYPASS_HOSTS targets are
|
||||
// all public-CA-issued (Google / GitHub / AWS / Cursor) so default
|
||||
// verification works without any extra trust store.
|
||||
servername: parsedUrl.hostname,
|
||||
rejectUnauthorized: false,
|
||||
path: parsedUrl.pathname + parsedUrl.search,
|
||||
method: options.method || "POST",
|
||||
headers: {
|
||||
|
||||
Reference in New Issue
Block a user