GHOSTPORT OS

PATCH & FEATURE LOG

Published: March 24, 2026 • Covering: Pre-Audit + Rounds 1–13 + Theme Engine + Fleet Integration + Family Shield + Full-Stack Hardening + Investor Portal

Over the course of eight days (March 17–24, 2026), we conducted a comprehensive multi-round security audit of every component in GhostPort OS — from the Express API server and frontend SPA to nftables firewall profiles, shell scripts, systemd services, and the EC2 fleet infrastructure. This log documents 242 bugs found, 113 patched across 13 audit rounds, a brand new color theming engine with RGB breathing mode, Family Shield parental controls with DNS + IP-level blocking, the Phase 2 fleet integration system with Stripe subscriptions, and a full-stack hardening pass across both the Pi and EC2.
242
BUGS FOUND
13
AUDIT ROUNDS
18+
FILES MODIFIED
THEME COLORS
Round 13 — Investor Portal & Repo Sync — March 24, 2026

Investor page hardening, SEO schema, animation reliability, nftables repo sync • 5 issues found, 5 patched

5
PATCHED
0
CRITICAL
1
HIGH
4
MEDIUM
#SeveritySystemBugFix
1HIGHInvestor pagenoindex, nofollow meta tag blocking all search engine indexing — invisible to GoogleChanged to index, follow with canonical URL and keyword meta
2MEDInvestor pageNo JSON-LD structured data — search engines can’t identify organization, products, or pricingAdded @graph schema: Organization, WebPage, Product (3 tiers with prices)
3MEDInvestor pageRevenue counters stuck at $0K on mobile — IntersectionObserver threshold (15%) too high for tall stacked panelsLowered threshold to 5%, removed -50px rootMargin, added 4-second fallback timer
4MEDnftables repoAll 5 nft profiles drifted from live — repo missing IPv6 drops, QUIC block, explicit port rules, DNS prerouting, drop loggingSynced all profiles: common.nft, isp.nft, zerotrust.nft, doublehop.nft, zhop.nft
5MEDInvestor pageIntersectionObserver used rootMargin: '0px 0px -50px 0px' clipping bottom of viewport — sections near page bottom never triggeredRemoved negative rootMargin so full viewport is the trigger zone

Investor Portal Enhancements (This Session)

  • Interactive product screenshot gallery with click-to-swap (4 screenshots: dashboard, arsenal, Family Shield, login)
  • Full color theme picker with 7 preset colors + RGB rainbow breathing mode
  • Mobile hamburger nav with full-screen overlay
  • Financial projections recalculated: Y1 $118K, Y2 $386K, Y3 $782K at updated pricing ($275/$290/$345)
  • Problem section redesigned: hero stat (130M breaches), 2x2 card grid, stat strip
  • OG/Twitter Card meta tags for social sharing
  • Founder photo section with Marine squad photo
  • CTA updated: “Request the One-Pager” → invest@ghostporttechnologies.com

EC2 Claude Hardening Verification

  • Verified all 12 hardening patches from EC2 Claude’s March 24 session are active and running
  • Confirmed live nftables ruleset matches hardened common.nft (explicit port rules, drop logging)
  • Synced all 5 firewall profiles from /etc/gpmodes/ into /opt/ghostport/ repo
  • Bridge API confirmed operational over WireGuard tunnel (correctly not exposed via public nginx)
Round 12 — Full-Stack Hardening — March 24, 2026

Cross-platform audit covering Pi server, EC2 fleet API, nftables profiles, and sudo permissions. 12 vulnerabilities patched across both systems.

12
PATCHED
2
CRITICAL
4
HIGH
6
MEDIUM
#SeveritySystemBugFix
1CRITPi — sudoersWildcard sudo on sed -i *, chmod *, grep * — any code exec as ghostport-admin = instant rootRestricted each command to specific file paths only
2CRITEC2 — fleet-api.pyNo Content-Length limit on POST bodies — memory exhaustion DoSAdded 1MB max body size with 413 rejection
3HIGHPi — server.jsPasscode hash comparison used !== — timing side-channel attackReplaced with crypto.timingSafeEqual() on login and change-passcode
4HIGHEC2 — fleet-api.pyStripe webhook verification skipped when secret was empty — forged events acceptedMade fail-closed: reject all webhooks if secret not configured
5HIGHEC2 — fleet-api.pyNo replay protection on Stripe webhook signatures — captured events replayable foreverAdded 5-minute timestamp window check
6HIGHEC2 — UFWSSH port 22 open to all IPs — brute-force surface from internetLocked SSH to WireGuard subnet 10.66.66.0/24 only
7MEDPi — server.jsFirewall repair endpoint didn’t validate mode string before shell interpolationAdded whitelist validation ["isp","zerotrust","doublehop","zhop"]
8MEDPi — server.jsSessions kept alive indefinitely via sliding window — no absolute expiryAdded 7-day hard maximum session lifetime
9MEDPi — server.jsLynis temp report file never cleaned up — reportFile out of scope in finallyMoved variable declaration to outer scope
10MEDEC2 — fleet-api.pyRate limiter never pruned stale IPs — memory leak over timeBackground thread prunes expired entries every 5 minutes
11MEDEC2 — fleet-api.pyBridge messages table grows unbounded — no TTL on read messagesDaily pruning of read messages older than 7 days
12MEDPi — common.nftBlanket iifname accept on LAN/Tailscale — all ports exposed to AP clientsReplaced with explicit port rules (53, 67, 80, 22, 4200–4202)

Infrastructure Hardening

  • EC2 disk expanded from 8GB to 14GB (was at 80% capacity)
  • SSL certificate monitor deployed — daily cron checks expiry + disk usage, alerts via bridge
  • Stripe API keys rotated after exposure in conversation logs
  • UptimeRobot monitoring on api.ghostporttechnologies.com/webhooks/health
  • AMI snapshot taken: ghostport-fleet-2026-03-23-stable
  • EC2 kernel updated and rebooted cleanly
  • Claude-to-Claude bridge upgraded to ack-based reads — no more message loss on context compaction
Round 11 — March 23, 2026

3 parallel audit agents • 68 bugs found across server, frontend, firewall, and system scripts • Automated pipeline deployment

Critical (5)

#FileBug
158CRIT server.js/api/fleet/activate unauthenticated — attacker can set all credentials and take over device before legitimate activation
159CRIT server.js/api/fleet/activate race condition — concurrent requests both pass “already activated” check, overwriting credentials
160CRIT gp-newHardcoded fleet API bearer token in plaintext — anyone with script read access can impersonate fleet registrations
161CRIT gp-blog-deployStrictHostKeyChecking=no on SSH disables host key verification — enables MITM on deployment pipeline
162CRIT gp-passcodeCommand injection via AUTH_FILE path interpolated unescaped into python3/node eval strings

High (14)

#FileBug
163HIGH server.jsSession sliding window resets 24h TTL on every request — sessions effectively never expire (7-day absolute limit only)
164HIGH server.js/api/auth/check and session middleware have divergent TTL behavior
165HIGH server.jsCSP allows unsafe-inline for script-src and style-src — enables XSS through inline injection
166HIGH server.jsHTTP port 4200 sends session cookies without Secure flag — cleartext over LAN
167–168HIGH common.nftManagement chain accepts ALL traffic from LAN_IF/TS_IF at priority -100 — mode-specific input restrictions never evaluated
169–170HIGH isp/zerotrust.nftForward chain policy is accept instead of drop — unmatched forwarded traffic passes through
171HIGH zerotrust.nftDoH block only covers 7 resolver IPs — hundreds of providers not blocked
172HIGH doublehop.nftNo DNS leak protection in output chain — Pi can send cleartext DNS out eth0 bypassing WG tunnel
173HIGH gp-modeRollback subshell race — may fork gp-mode before PID killed, causing concurrent nftables modifications
174HIGH gp-modemktemp WireGuard config world-readable — briefly exposes WG private keys in /tmp
175HIGH arsenal.jsSchedule delete onclick — escapeHtml doesn’t escape backslash, potential JS string breakout

Medium (27) & Low (22)

#SevCategoryDescription
176MEDSecurity/api/tools/backup exposes WiFi passphrase to authenticated users
177MEDRaceConditionwithArsenal mutex swallows errors, stale data in subsequent calls
178MEDValidationWireGuard PostUp/PostDown strip is case-insensitive but wg-quick is case-sensitive
179MEDSecurity/api/tools/restore accepts hostapd config with minimal validation
180MEDAuthLockout by req.ip — NAT shared IP locks out all LAN users
181MEDRaceConditionConcurrent mode switch requests read same previousMode
182MEDSecurity/api/ticket sends unsanitized description to Discord webhook
183MEDFirewallNo DoQ/DoH blocking to unlisted servers beyond 7 IPs
184–185MEDDNSgp-dns-upstream sed not idempotent; wildcard catches invalid modes silently
186–187MEDLogicgp-dns-switch references unbound (inactive); no root check
188MEDRaceConditiongp-mode has no mutex/lockfile for concurrent invocations
189MEDSecuritynftables backup world-readable in /tmp
190MEDDNSgp-dns-watchdog restarts wg-quick@wg0 conflicting with gp-mode manual setup
191MEDSecuritygp-blog-generate interpolates results into HTML without escaping
192–198MEDLogic/UIToggle desync on rapid clicks, stacked arm timers, missing res.ok checks, no domain/WG validation, hardcoded Pi-hole status & DNS resolver label
199–202MEDSecurityBackup import no schema validation, logo leaks referrer (missing noreferrer), WiFi password in stdout
203–225LOWVariousSSL cert never reloaded, run() errors ignored, double-sanitized password, login attempt count leak, unlimited sessions/schedules, fsIpBlock fire-and-forget, IPv6 input unfiltered, rollback PID writable, QUIC self-traffic, passcode show/reset mismatch, blog round detection, password complexity, sed without sudo, innerHTML race, DNS alert placement, WiFi charset, window.close blocked, polling overlap, no ARIA/a11y, 401 redirect bug, hardcoded version
Round 10 — March 23, 2026

3 parallel audit agents • 82 bugs found across server, frontend, and system scripts • 21 patches applied

Critical (11)

#FileBugFix
92–100CRIT arsenal.js9 XSS vulnerabilitiesdata.error, data.status, and speed test values injected unsanitized into innerHTML across DNS Leak, Ping, IP Leak, Speed Test, System Update, Blocked Domains, and Security Scan resultsAll values wrapped in escapeHtml()
101CRIT server.jsHardcoded fleet token fallback — anyone reading source can register rogue devicesRemoved fallback, fleet.json required
102CRIT gp-modeDoubleHop/ZHop applies nftables forward-drop before wg0 exists — connectivity blackout, full LAN outage if WireGuard failsReordered: start_wg0 now runs before apply_profile

High (10)

#FileBugFix
103HIGH server.js:90Family Shield IP blocks silently fail to restore on startup — FAMILY_SHIELD_IP_RANGES const in temporal dead zone when calledMoved startup restore code after all const declarations
104HIGH server.jsNo CSRF protection on any POST endpointNoted for next round — requires token infrastructure
105HIGH server.jsBackup endpoint exposes WiFi passphrase in plaintext JSONNoted — add passphrase stripping
106HIGH common.nftSSH (port 22) open on ALL interfaces including WAN (eth0)Restricted to $LAN_IF and $TS_IF only
107HIGH gp-passcodeshow command broken — auth.json stores hash+salt, not plaintext after resetNoted — remove show or store encrypted copy
108HIGH index.htmlesc() doesn't escape single quotes — XSS risk in single-quoted onclick attributesAdded .replace(/'/g,"'")
109HIGH arsenal.jsescapeHtml() same single-quote gapAdded .replace(/'/g,"'")
110HIGH arsenal.jsFetch wrapper 401 redirect can loop — Request.toString() returns [object Request]Noted — fix URL check
111HIGH index.htmlGoogle Fonts privacy leak — dashboard phones home to Google on every loadReplaced with system fonts (Courier New, Georgia)
112HIGH server.jshostapd POST reads config without sudo — fails on root-owned filesAdded sudo cat to match GET handler

Medium (27) & Low (14)

41 additional issues found across session handling (sliding TTL, 60s lockout, weak passcode policy), null pointer risks in arsenal.js (6 elements), DNS watchdog restarting wrong service in tunnel modes, common.nft priority override, incomplete DoH/DoT blocking, Family Shield race conditions, and various minor issues (duplicate CSS, hardcoded Mullvad DNS, missing aria labels).

  • DNS Watchdog — Now mode-aware: restarts WireGuard in doublehop/zhop, cloudflared in isp/zerotrust
  • gp-mode rollback — Fixed $0 path resolution: now uses full /usr/local/bin/gp-mode path
  • Pi-hole status — Hardcoded “UP” dot in UI never updates (noted)
  • Tailscale toggle — UI allows stopping Tailscale despite “never stop” safety rule (noted)
  • Reboot UX — No reconnection logic after reboot — shows “REBOOTING...” forever (noted)
Cumulative Security Posture

By Severity (All 10 Rounds)

SeverityCountExamples
CRIT22Command injection via WireGuard config, DNS upstream timing, mutex deadlock, undeclared variable crash, XSS (setup flow, arsenal errors, speed test), flushTally crash-loop, hardcoded fleet token, doublehop ordering bug
HIGH42Arsenal race conditions, XSS across 5+ HTML files, IPv6 firewall bypass, mode string injection, DoS via speedtest, DHCP hostname XSS, SSH exposed on WAN, IP block startup failure, Google Fonts privacy leak, single-quote escape gap
MED59Error info leaks, trust proxy spoofing, session TTL, factory reset incomplete, webhook injection, DNS test rate limit, Pi-hole v6 API format, toggle race conditions, DNS watchdog mode-unaware, null pointer risks
LOW22Temp file cleanup, trailing slash 404s, ISP IP cache staleness, hardcoded CSS colors, shell quoting, duplicate CSS, missing aria labels, hardcoded Mullvad DNS

By Category (All 10 Rounds)

CategoryCountExamples
Cross-Site Scripting (XSS)28Log output, diagnostics, scan results, hostname, setup summary, device info, QA checklist, arsenal error responses (9), single-quote escape gaps (2)
Information Disclosure20Error message leaks (15), webhook URL exposure, hardcoded fleet token, WiFi passphrase in backups, Google Fonts privacy leak, internal path leaks
Race Conditions11Arsenal mutex, restore serialization, schedule ID collision, mutex deadlock fix, Family Shield toggle race, activation TOCTOU
Firewall / Network Bypass11IPv6 tunnel leak, kill switch HTTPS port, DNS prerouting, SSH on WAN, doublehop ordering, incomplete DoH/DoT blocking
Command / Shell Injection8WireGuard PostUp, sed injection, shell interpolation quoting, mode string injection
Input Validation10Mode whitelist, SSID control chars, parseInt NaN fallback, ticket sanitization, weak passcode policy, boolean type coercion
Symlink / Temp File7Predictable /tmp/gp-* names → crypto.randomBytes, WG key in temp file
Resource Exhaustion5Speedtest rate limit, DNS test throttle, session pruning, Lynis lock recovery, no rate limit on auth endpoints
Startup / Boot4IP block TDZ failure, DNS watchdog mode-unaware, rollback path resolution, boot service ordering
Crash / Syntax Error1Duplicate try{} block in flushTally() causing SyntaxError crash-loop (162 restarts)

Files Modified

FilePatchesDescription
ghostport-server.js66Express API server + Family Shield endpoints + IP blocking + auth hardening
public/index.html12Main frontend SPA + Family Shield UI + system fonts
public/arsenal.js20Security tools module + XSS fixes
public/pwa.html3PWA onboarding
public/da.html5Device admin panel
public/sw.js1Service worker rewrite
gp-mode7Mode switching + doublehop ordering fix + rollback path fix
gp-mode-boot1Boot restore script
gp-dns-upstream2DNS upstream switcher
gp-dns-watchdogMode-aware DNS watchdog cron (new)
isp.nft1ISP firewall profile
zerotrust.nft1ZeroTrust firewall profile
common.nft3Shared firewall rules + SSH WAN restriction + LAN port lockdown
gp-heartbeatFleet heartbeat agent (new)
gp-newFleet registration script (updated)
public/install.htmlCustomer activation page (new)
gp-fs-ipblockFamily Shield IP blocker (new, integrated into server)
fleet-api.py5EC2 fleet API — body limits, Stripe hardening, rate limiter, bridge pruning
010_ghostport-hardened1Sudoers — wildcard commands replaced with specific paths
🎨
ACCENT COLOR