[object Object]

← back to Ken

Ken auth: close IP-bypass hole before public reverse-proxy exposure

531d5a7be90b1372c2a4fd04b2ac2c1c418b8f0c · 2026-08-04 14:23:05 -0700 · Steve Abrams

- Drop 45.61.58.125 (Kamatera) from the auth-bypass whitelist so proxied
  public traffic must pass login (basic-auth / Google OAuth), not auto-trust.
- isWhitelistedIP() now keys off req.socket.remoteAddress (real TCP peer)
  instead of the client-controllable X-Forwarded-For header — a public
  visitor can no longer forge `X-Forwarded-For: 127.0.0.1` to bypass auth.
- Loopback (127.0.0.1/::1) bypass retained so the safe-mode guard keeps working.

Prep for serving ken.agentabrams.com via Kamatera reverse-proxy to Mac2.

Files touched

Diff

commit 531d5a7be90b1372c2a4fd04b2ac2c1c418b8f0c
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Aug 4 14:23:05 2026 -0700

    Ken auth: close IP-bypass hole before public reverse-proxy exposure
    
    - Drop 45.61.58.125 (Kamatera) from the auth-bypass whitelist so proxied
      public traffic must pass login (basic-auth / Google OAuth), not auto-trust.
    - isWhitelistedIP() now keys off req.socket.remoteAddress (real TCP peer)
      instead of the client-controllable X-Forwarded-For header — a public
      visitor can no longer forge `X-Forwarded-For: 127.0.0.1` to bypass auth.
    - Loopback (127.0.0.1/::1) bypass retained so the safe-mode guard keeps working.
    
    Prep for serving ken.agentabrams.com via Kamatera reverse-proxy to Mac2.
---
 kalshi-dash/server.js | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/kalshi-dash/server.js b/kalshi-dash/server.js
index dd0cf54..6fcc6b4 100644
--- a/kalshi-dash/server.js
+++ b/kalshi-dash/server.js
@@ -27,7 +27,11 @@ const AUTH_USER = process.env.ADMIN_USER || 'admin';
 const AUTH_PASS = requiredEnv('ADMIN_PASSWORD');
 const SESSION_COOKIE = 'kalshi_session';
 const SESSION_MAX_AGE = 30 * 24 * 60 * 60; // 30 days in seconds
-const WHITELISTED_IPS = ['127.0.0.1', '::1', '45.61.58.125', 'localhost'];
+// Auth-bypass ONLY for genuinely local callers (the safe-mode guard, local admin).
+// 45.61.58.125 (Kamatera) removed 2026-08-04: Ken is now reverse-proxied from
+// Kamatera to serve ken.agentabrams.com, so proxied PUBLIC traffic must NOT be
+// treated as trusted — every public visitor must pass login (basic-auth / OAuth).
+const WHITELISTED_IPS = ['127.0.0.1', '::1', 'localhost'];
 
 // ── Slack Alerts ──
 const SLACK_WEBHOOK = process.env.SLACK_WEBHOOK_URL || '';
@@ -448,7 +452,11 @@ function getClientIP(req) {
 }
 
 function isWhitelistedIP(req) {
-  const ip = getClientIP(req);
+  // SECURITY: key the auth-bypass off the real TCP peer ONLY, never the
+  // client-controllable X-Forwarded-For header. Behind the Kamatera reverse
+  // proxy a public visitor could send `X-Forwarded-For: 127.0.0.1` to forge a
+  // local-trust bypass; socket.remoteAddress cannot be spoofed by the client.
+  const ip = req.socket?.remoteAddress || '';
   return WHITELISTED_IPS.some(w => ip.includes(w));
 }
 

← 0d924a3 chore: lint + refactor (mkMarket readability), v1.0.3 (sessi  ·  back to Ken  ·  chore: v1.0.4 (session close) — auth hardening for public ke f1bde08 →