Skip to content

fix(server): fail closed when SOCKET_AUTH_TOKEN is unset (addresses #573 section C)#671

Open
Anexus5919 wants to merge 1 commit into
Somil450:mainfrom
Anexus5919:fix/socket-auth-insecure-default
Open

fix(server): fail closed when SOCKET_AUTH_TOKEN is unset (addresses #573 section C)#671
Anexus5919 wants to merge 1 commit into
Somil450:mainfrom
Anexus5919:fix/socket-auth-insecure-default

Conversation

@Anexus5919
Copy link
Copy Markdown
Contributor

📌 Related Issue

Addresses section C of #573 (the "No auth by default" item). This is intentionally not a "Fixes" link, because #573 also covers payload-limit hardening (sections A, B, D) handled separately by PR #574, so #573 should stay open. Also closes the live-path gap behind #449, whose recommended production guard only ever existed in the now-dead server/src/app.js and was never ported to the live createServer.js.


📝 Description

Makes the Socket.IO server fail closed when SOCKET_AUTH_TOKEN is not configured, instead of silently accepting every unauthenticated connection.

🔹 What has been changed?

  • server/src/app/createServer.js: the auth middleware is now always registered. When SOCKET_AUTH_TOKEN is unset:
    • unauthenticated connections are accepted only when NODE_ENV is explicitly development or test (the intentional local-dev affordance from PR fix: harden Socket.IO backend (CORS allow-list, auth gate, rate limit, frame validation) #278 / feat: add socket auth, rate limiting, and CORS hardening #488),
    • in every other environment, including production and any deployment that leaves NODE_ENV unset, connections are rejected with Error("Server misconfiguration: SOCKET_AUTH_TOKEN is not set"),
    • a matching warning is logged at startup (mirroring the existing insecure-CORS warning in config/socket.js).
    • When a token IS set, validation is unchanged ("Authentication failed: invalid or missing token").
      NODE_ENV is normalized with trim().toLowerCase() so "Production" / " production " are handled correctly.
  • server/package.json: dev now runs with NODE_ENV=development and start with NODE_ENV=production (via cross-env, added as a devDependency), so the local-dev affordance keeps working out of the box and production is explicit.
  • server/tests/integration/auth.test.js: now covers all five states (token set + missing token -> reject, token set + valid -> accept, unset + dev -> accept, unset + production -> reject, unset + no NODE_ENV -> reject), with NODE_ENV / SOCKET_AUTH_TOKEN restored in afterEach and a fast-fail guard so a regression to "accept" fails immediately instead of timing out.
  • server/tests/integration/socket.test.js: pins NODE_ENV so the token-less frame-flow test is deterministic regardless of the ambient environment.

🔹 Why are these changes needed?

SOCKET_AUTH_TOKEN defaults to null (config/constants.js), and the previous if (SOCKET_AUTH_TOKEN) { io.use(...) } registered no auth middleware at all when it was unset, so any client could connect to the live server with no log and no rejection. The production-rejection guard #449 recommended was written into app.js, which is dead code (the live entry is index.js -> createServer.js), so it never ran.

🔹 Why fail closed (reject unless explicitly dev/test) rather than only on NODE_ENV === "production"?

An earlier draft rejected only when NODE_ENV === "production", but an adversarial review showed that fails open in a common case: a production host that never sets NODE_ENV would still accept unauthenticated connections (and the log would even claim "non-production"). For an auth gate, the secure default is to reject whenever the environment is not unambiguously local development. The dev/start scripts set NODE_ENV so normal workflows are unaffected. This is slightly stricter than the warn-only precedent used for the CORS origin in config/socket.js, which is deliberate: an auth bypass is a higher-severity hole than a browser-enforced CORS warning.


🛠️ Type of Change

  • 🐛 Bug Fix (security)

🧪 Testing

✅ Tests Performed

  • Tested locally
  • Build runs successfully (backend)
  • No new console errors
  • Existing functionality verified
  • cd server && npm test -> 13 files, 42 tests passed (40 pre-existing + 2 new auth cases).
  • Also ran with NODE_ENV=production forced -> 42 passed, confirming the suite is robust to the ambient environment and the production-reject path works.

🌐 Browsers Tested

Not applicable (backend change).


📷 Screenshots / Demo (if applicable)

Not applicable (backend logic + tests).


📋 Checklist

  • I have read the project's CONTRIBUTING guidelines
  • My code follows the project style guidelines
  • I have performed a self-review of my code
  • I have tested my changes locally
  • My changes do not introduce new warnings or errors
  • This PR is linked to an existing issue

💬 Additional Notes

Branched from latest upstream/main (834824e). Scope is limited to the auth-by-default item; the memory/disk payload-limit vectors of #573 (A/B/D) are out of scope here and tracked by PR #574.

Behavior change to be aware of: a production deployment that runs without SOCKET_AUTH_TOKEN will now reject socket connections (fail closed) instead of accepting them. That is the intended secure outcome; set SOCKET_AUTH_TOKEN to enable authenticated connections. Local development is unaffected because npm run dev sets NODE_ENV=development.

@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 1, 2026

@Anexus5919 is attempting to deploy a commit to the somiljain2024-4175's projects Team on Vercel.

A member of the Team first needs to authorize it.

@Anexus5919 Anexus5919 marked this pull request as ready for review June 1, 2026 16:24
@Anexus5919
Copy link
Copy Markdown
Contributor Author

@Somil450 Opened this pr to address section C (no auth by default) of this issue. It makes createServer.js fail closed when SOCKET_AUTH_TOKEN is unset outside dev/test. It intentionally does not close this issue, since the payload-limit items (A/B/D) are handled by #574.

Kindly have a review on this pr. Thanks!

@Anexus5919
Copy link
Copy Markdown
Contributor Author

@Somil450 Please have a review this pr. Thanks!

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