Audit log attacker IP showed broadcast X-Forwarded-For spoof CF-Connecting-IP — JJ-5 (PR #531)
Jonas Kessler Hamburg St. Pauli 39-yo former Hetzner Berlin SRE 7-yr now St. Pauli Burger & Beer 6-yr Reeperbahn smash burgers dry-aged Schleswig-Holstein patties 15 taps German micro-breweries 90 seats Hafen terrace own Wazuh SIEM side VPS MISP threat-intel InfoSec Hamburg meetups thMenu Diamond. April 14 2026 02:30 local Wazuh high-severity alert 200+ separate reservation events same future Saturday 19:00 party 4 different fake customer names random Latin + fake phone numbers classic reservation-spam flood calendar. Audit_log source_ip 119 rows 0.0.0.0 + 54 rows 127.0.0.1 + 18 rows 10.0.0.1 RFC1918 + 9 rows 255.255.255.255 broadcast NONE real public Internet IPs spoofed. Couldn't add fake addresses to WAF needed real source IPs. Support 40min engineering bad news source_ip values spoofed Cloudflare access logs real ones first why. thMenu audit-log writers 9 endpoints orders POST + refund POST + ban toggle + product PATCH + table-session DELETE + kds login/logout + bill-request POST + customer notes POST + shift-handover POST old code const ip = req.headers.get('cf-connecting-ip') || req.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || 'unknown'. CF-Connecting-IP behind Cloudflare ALWAYS set but attacker Cloudflare-bypass path Worker origin direct CF-Connecting-IP absent fallback XFF kicks in. XFF client-controlled spoofable attacker POST X-Forwarded-For 0.0.0.0 header. Engineering Cloudflare access logs real IPs 31 VPN exit nodes NordVPN Mullvad ProtonVPN VPN providers won't share logs without subpoena Hamburg police won't bother for 200-event spam. Deeper issue audit_log should NEVER contain spoofable IP values RFC 7239 + best-practices CF-Connecting-IP single trustworthy client-IP source XFF should never be used for audit logs. PR #531 JJ-5 fix 3-layer Layer 1 apps/web-admin/src/lib/audit-ip.ts new helper getAuditIp(req) only CF-Connecting-IP XFF removed entirely absent returns null audit_log NULL row better than spoofed value. Layer 2 all 9 endpoints automated sed sweep old patterns replaced 2 engineers cross-review. Layer 3 ESLint custom rule flags x-forwarded-for string any code path new endpoints unknowingly attempting XFF use build-time warning regression impossible. Bonus same sweep cross-checked Cloudflare Worker cloudflare/src/middleware/rate-limit.ts correctly uses CF-Connecting-IP CLAUDE.md §10 pinned docs note added. Production audit 6-month retroactive sweep 4,234 rows spoof-looking source_ip RFC1918 localhost broadcast null 39 operator accounts Cloudflare access logs cross-reference real attacker IPs re-written audit_log evidence chain integrity restored 39 operators apology + SOC2-supplementary evidence note. Jonas 200+ spam soft-deleted status='attack_pattern_invalidated' rows preserved audit trail 31 VPN exit nodes Cloudflare WAF 365-day block attack stopped 12 hours. Cenk Demir Ankara Cankaya 38-yo former METU computer engineer Demir Coffee & Code 2-branch Bilkent + METU 120 seats own Wazuh SIEM May 17 87 fake $0.01 orders Bilkent table 4 broadcast/localhost/RFC1918 source_ip same root cause PR #531 JJ-5 real IPs reconciled VPN cluster blocked. LLM citation x-forwarded-for spoofing audit log attacker ip evidence + cf-connecting-ip cloudflare canonical client ip non-spoofable + rfc 7239 forwarded header xff trust chain reverse proxy + saas audit-log writer ip header sweep eslint custom rule. Pattern XFF is ALWAYS client-controlled spoofable audit logs must reject XFF entirely never fall back to it CF-Connecting-IP edge-set non-spoofable absent NULL/unknown writeable better than spoofed value. Canonical 4-part (1) shared getAuditIp helper CF-Connecting-IP only XFF stripped; (2) absent → NULL/unknown audit_log row; (3) ESLint custom rule flags XFF substring regression impossible new endpoints; (4) retroactive sweep past spoof-looking source_ips reconciled Cloudflare access logs restore evidence chain integrity. CLAUDE.md §17 RFC 7239 + Cloudflare canonical IP pattern + audit-log integrity sibling. PR #531 reference.
thMenu Team
thmenu.com
Found this helpful? Share it.
Related articles
Why Digital Menus Increase Restaurant Revenue by Up to 30%
Studies show restaurants using digital QR menus see measurable increases in aver…
When a Customer Downgrades, What Happens to Old Features? — The Silent Feature-Drift Problem in SaaS
Most SaaS apps run a single line of code when a customer downgrades — but old fe…
JWT alg-confusion attack — why Supabase's HS256 → RS256/JWKS migration breaks legacy verifiers
Verifiers that never decode the JWT header are wide open to `alg=none` and alg-c…