GHOSTPORT OS

PATCH & FEATURE LOG

Published: March 23, 2026 • Covering: Pre-Audit + Rounds 1–10 + Theme Engine + Fleet Integration + Family Shield

Over the course of seven days (March 17–23, 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, and systemd services. This log documents 225 bugs found, 96 patched across 11 audit rounds, a brand new color theming engine with RGB breathing mode, Family Shield parental controls with DNS + IP-level blocking, and the Phase 2 fleet integration system with Stripe subscriptions.
225
BUGS FOUND
11
AUDIT ROUNDS
18+
FILES MODIFIED
THEME COLORS

Pre-Audit Fixes — March 17, 2026

Scripts: fix-permissions.py, fix-restore-btn.py, fix-security-bugs.py, fix-round2.py, fix-mode-and-nft.sh, fix-dns-upstream.py, fix-pihole-cmd.py, fix-arsenal-race.py, fix-install-banner.py

#SeverityFileBugFix
1MEDpublic/index.htmlRestore button missing from repair panelAdded backup restore UI button
2HIGHghostport-server.jsFile permissions too open on config filesEnforced 0600 on auth.json, pihole.json, arsenal.json
3CRITghostport-server.jsWireGuard config accepts PostUp/PostDown directives — arbitrary root command executionStrip dangerous directives (PostUp, PostDown, PreUp, PreDown, SaveConfig) on upload
4HIGHghostport-server.jsHostapd SSID/password not validated — newline injection into config fileAdded regex validation for SSID (1-32 chars, no newlines) and password (8-63 printable ASCII)
5HIGHghostport-server.jsSchedule deletion command injection via unsanitized ID in sed commandAdded regex validation: schedule IDs must match /^[a-z0-9]+$/
6HIGHghostport-server.jsMissing input validation on mode switch — arbitrary string passed to shellWhitelist validation: mode must be one of isp, zerotrust, doublehop, zhop
7MEDghostport-server.jsHostapd config read via shell cat — unnecessary shell invocationSwitched to fs.readFileSync with sudo fallback
8CRITgp-mode / nftablesDNS leak monitor nftables rules used invalid mixed tcp/udp syntaxSplit into separate accept+drop rules matching kill switch pattern
9CRITgp-mode / gp-dns-upstreamDNS upstream switch called before mode file update — reads OLD mode, applies wrong DNSMoved gp-dns-upstream call to after modefile write in every mode case
10MEDghostport-server.jsPi-hole API called via deprecated CLI syntaxUpdated to Pi-hole v6 REST API
11HIGHghostport-server.jsArsenal config race condition — concurrent read-modify-write on kill switch, MAC, QUIC togglesIntroduced withArsenal(fn) mutex pattern for atomic operations
12MEDghostport-server.jsArsenal.json not created on first boot — all toggles fail with ENOENTAdded default file creation with correct ownership on startup

Round 1 — March 18, 2026

Script: fix-bugs-march18.py • 13 patches applied

#SeverityFileBugFix
13CRITgp-modeDNS upstream called inside apply_profile() before modefile update — wrong DNS server appliedMoved to post-modefile write for all 4 modes
14HIGHghostport-server.jsKill switch toggle uses raw readArsenal/writeArsenal — race conditionWrapped in withArsenal() mutex
15HIGHghostport-server.jsMAC randomization toggle uses raw readArsenal/writeArsenalWrapped in withArsenal() mutex
16HIGHghostport-server.jsQUIC block toggle uses raw readArsenal/writeArsenalWrapped in withArsenal() mutex
17MEDghostport-server.jsHostapd config read via sudo cat shell commandChanged to fs.readFileSync with graceful fallback
18MEDghostport-server.jsBackup version missing from export metadataAdded version: "1.0" to backup JSON

Round 2 — March 18, 2026

Scripts: fix-bugs-round2.py, fix-ads-tally.py, fix-pwa-sw.py, fix-install-route.py • XSS, session, and feature fixes

#SeverityFileBugFix
19HIGHpublic/index.htmlLog function XSS — msg inserted into innerHTML without escapingAdded HTML entity escaping before interpolation
20HIGHpublic/index.htmlDiagnostics output XSS — c.name, c.detail, c.fix unescaped in innerHTMLAdded esc() helper function, escaped all diagnostic fields
21HIGHpublic/arsenal.jsSecurity scan output XSS — warning/suggestion id, message, fix unescapedWrapped all fields in escapeHtml()
22MEDghostport-server.jsAds tally file not created on startup — privacy-preserving counter failsCreated /etc/ghostport/ads-tally.json with correct ownership
23MEDghostport-server.jsSessions never pruned — memory leak over timeAdded pruning interval every 10 minutes, removes expired sessions
24MEDpublic/sw.jsService worker was self-destruct script — PWA not installableReplaced with minimal network-only SW with fetch handler for Chrome installability
25LOWghostport-server.jsNo public route for install pageAdded /install.html, /install, and /qr routes before auth middleware

Round 3 — March 18, 2026

Script: fix-bugs-round3.py • 6 bugs, 6 patches

#SeverityFileBugFix
26HIGHghostport-server.jsSchedule add uses raw readArsenal/writeArsenal — race condition with other Arsenal opsWrapped in withArsenal() mutex
27HIGHghostport-server.jsSchedule delete uses raw readArsenal/writeArsenalWrapped in withArsenal() mutex
28LOWghostport-server.jsTemp file /tmp/gp-sched-line never cleaned up after cron creationAdded fs.unlinkSync after tee
29MEDghostport-server.jsFactory reset incomplete — doesn't clear ads tally, cron schedules, or temp filesAdded cleanup for ads-tally.json, ghostport-schedules, and temp files
30HIGHgp-mode-bootNo fallback if saved mode fails on boot — device stuck with broken firewallAdded 30-second timeout + automatic ISP fallback on failure
31MEDghostport-server.jsreq.ip spoofable via X-Forwarded-For headerSet app.set("trust proxy", false)

Round 4 — March 18, 2026

Script: fix-bugs-round4.py • 9 bugs, 12 patches

#SeverityFileBugFix
32CRITghostport-server.jswithArsenal() mutex deadlock — thrown error breaks promise chain permanently, all future Arsenal operations hangError handler catches and logs without re-throwing — chain stays alive
33HIGHghostport-server.jsstopKillSwitch() reads mode from file and passes to exec() without validation — command injection via compromised modefileAdded whitelist validation before execution
34HIGHghostport-server.jsstartKillSwitch() recovery path same issueAdded whitelist validation
35HIGHghostport-server.jsWireGuard stats: parseInt(rx || 0) returns NaN on corrupted data; no array bounds check on tab-split outputAdded parseInt(x, 10) || 0 fallback and filter(line => parts.length >= 7)
36MEDghostport-server.jsRestore endpoint: fs.unlinkSync(tmpWg) crashes on permission errorWrapped in try-catch
37MEDghostport-server.jsRestore endpoint: fs.unlinkSync(tmpHap) same issueWrapped in try-catch
38MEDghostport-server.jsKill switch: concurrent toggle + monitor causes state mismatch if interval becomes staleClears stale interval before starting new one
39MEDghostport-server.jsSchedule ID collision — Date.now().toString(36) same millisecond = same IDAppended 4 random hex chars via crypto.randomBytes(2)
40MEDghostport-server.jsSession TTL fixed at 24h — active user kicked at expiry even during useSliding window: session.created = Date.now() on each valid request
41LOWghostport-server.jsISP IP cache never expires — DNS leak detection uses stale data if ISP changesAdded 1-hour cache expiry with ispIpCacheTime timestamp

Round 5 — March 18, 2026

Script: fix-bugs-round5.py • 7 bugs, 10 patches

#SeverityFileBugFix
42CRITghostport-server.jsispIpCacheTime used but never declared — DNS leak monitor crashes with ReferenceError on first runAdded let ispIpCacheTime = 0 declaration
43HIGHghostport-server.jsNo rate limit on /api/tools/speedtest — DoS vector via repeated 60-120 second system commandsAdded 2-minute cooldown between speed tests
44HIGHghostport-server.jsLynis scan flag lynisScanRunning not reset on exception — one crash permanently locks scanningMoved reset to finally block
45MEDghostport-server.jsTrouble ticket description/contact accept newlines — webhook message injectionStrip \r\n, cap description at 500 chars, contact at 100
46MEDghostport-server.jsError responses leak internal paths, stderr, and webhook URLsSanitized all error messages to generic strings
47LOWghostport-server.js/login/ with trailing slash returns 404Changed route to regex: /^\/login\/?$/
48LOWghostport-server.js/install/ with trailing slash returns 404Changed route to regex: /^\/install\/?$/

Round 5b — March 19, 2026

Script: fix-bugs-round5b.py • 9 bugs across 5 files • Deep audit of previously unaudited files

#SeverityFileBugFix
49CRITpublic/pwa.htmlXSS in setup summary — user-supplied name and email interpolated into innerHTML unescapedAdded esc() helper, escaped name, serial, and email fields
50CRITpublic/pwa.htmlXSS in log rendering — l.msg inserted into innerHTML without escapingWrapped in esc()
51HIGHpublic/da.htmlXSS in QA error handler — e.message rendered as raw HTMLAdded esc() helper, escaped error message
52HIGHpublic/da.htmlXSS in log entries — l.message and l.timestamp unescapedEscaped both fields
53HIGHpublic/da.htmlXSS in device info — all API-sourced device fields rendered as raw HTMLEscaped labels and values
54HIGHpublic/da.htmlXSS in QA checklist — c.name and c.detail unescaped in innerHTMLEscaped both fields
55HIGHisp.nftMissing IPv6 drop in forward chain — clients can bypass routing via IPv6 tunnelsAdded meta nfproto ipv6 counter drop to forward chain
56HIGHzerotrust.nftMissing IPv6 drop in forward chain — DNS lock bypass via IPv6Added meta nfproto ipv6 counter drop to forward chain
56bMEDgp-dns-upstreamSilent failures — no error reporting if config file missing or sed replacement failsAdded file existence check and post-sed verification with error output

New Feature — Theme Color Engine

🎨 Infinite Color Picker + RGB Breathing Mode

The GhostPort Command Deck now supports full UI color customization. Every element — accents, backgrounds, borders, text, glows — adapts to your chosen color in real time.

Round 6 — March 21, 2026

Script: fix-bugs-round6.py • 9 patches across server & firewall

#SeverityFileBugFix
57 HIGH ghostport-server.js Schedule deletion endpoint had copy-pasted finally block from Lynis scanner — resetting unrelated lynisScanRunning flag and returning wrong error message ("Security scan failed") Removed wrong finally block, fixed error message to "Failed to delete schedule"
58 HIGH ghostport-server.js 6 locations used predictable temp file names in /tmp/ (e.g. /tmp/gp-hostapd.conf) — symlink attack vector on world-writable directory Added gpTmpFile() helper using crypto.randomBytes(8) for unique names. Applied to hostapd, WireGuard, restore, MAC randomization, and schedule writes
59 MED ghostport-server.js Restore endpoint exposed e.message in error response — could leak filesystem paths or command output Replaced with generic "Config restore failed" message, logs details server-side
60 MED ghostport-server.js DNS leak check used curl -4 (IPv4 only) — wouldn't detect IPv6 DNS leaks Switched to dual-stack curl -s to catch both v4 and v6 leak types
61 LOW ghostport-server.js Gateway and speedtest ping commands passed IPs without shell quoting Added single-quote wrapping around interpolated IP variables for defense-in-depth
62 MED ghostport-server.js Restore endpoint used systemctl restart wg-quick@wg0 but gp-mode manages wg0 directly via ip/wg commands — service conflicts with existing interface Replaced with gp-mode reapply for consistency with how WireGuard is actually managed
63 MED ghostport-server.js Kill switch nftables rules only allowed port 4200 (HTTP dashboard) but not 4201 (HTTPS) — would lose dashboard access over HTTPS during kill switch activation Added port 4201 to kill switch accept rules
64 LOW public/index.html Three CSS classes (.mode-desc, .log-msg.info, .arsenal-desc) used hardcoded green hex values that didn't respond to theme color switching Replaced #6a9a6a and #5a8a5a with var(--text-dim)
65 LOW common.nft Ports 80 and 443 had accept rules open to all interfaces — redundant since policy is accept but misleading Already cleaned up (found pre-fixed during verification)

Round 7 — March 21, 2026

Script: fix-bugs-round7.py • 18 patches across 4 categories

#SeverityFileBugFix
66–80 MED ghostport-server.js 15 endpoints exposed raw e.message in error responses. Child process errors could leak filesystem paths, command names, or internal system details to authenticated clients All error responses now return generic messages ("Operation failed", "Mode switch failed", etc.). Full details logged server-side with console.error()
81 HIGH ghostport-server.js DHCP lease hostname from dnsmasq not HTML-escaped in /api/arsenal/clients response. A device with <script> in its hostname could inject into the client list UI Wrapped hostname in escapeHtml()
82 MED ghostport-server.js POST /api/arsenal/dnstest had no rate limiting. Could be spammed to flood external DNS lookups and ifconfig.me requests, causing resource exhaustion Added 30-second cooldown (same pattern as speedtest's 2-minute throttle)
83 HIGH ghostport-server.js Restore endpoint wrote directly to /etc/ghostport/arsenal.json without the withArsenal() mutex. Concurrent arsenal operations (toggle, schedule add) could corrupt the config file Wrapped in await withArsenal() to serialize writes

Bug Fix — March 21, 2026

Post-Round 7 hotfix • Server crash-loop recovery

#SeverityFileBugFix
84 CRIT ghostport-server.js Duplicate try{} block in flushTally() from a prior round patch caused a SyntaxError on startup — server entered a crash-loop with 162 restarts before detection Collapsed duplicate try blocks into a single try/catch/finally structure

Phase 2 — Fleet Integration (March 21, 2026)

Heartbeat Agent (gp-heartbeat)

Systemd timer-driven agent that checks in with the EC2 fleet server every 5 minutes. Each heartbeat sends the device’s firmware version, uptime, and current mode. The fleet server responds with subscription status and any pending commands (e.g., mode change, config update).

Install Page (/install)

Customer-facing dark-themed activation page served at /install. Users enter their license key to activate the device. The page auto-provisions the router without requiring prior authentication.

/api/fleet/activate Endpoint

No-auth device setup endpoint. Accepts a license key, registers the device with the fleet server, and returns freshly generated credentials for the customer.

gp-new --auto

Non-interactive factory provisioning mode for the gp-new registration script. Enables headless device setup during manufacturing or bulk deployment without manual prompts.

Stripe Subscription Integration

Three-tier subscription model with webhook-driven license management. Stripe events flow to the EC2 fleet server, which updates each device’s subscription status. The Pi’s heartbeat agent picks up changes on its next check-in.

EC2 Fleet API Pipeline

End-to-end subscription lifecycle: Stripe webhook fires on payment events → EC2 fleet server updates the device record → Pi heartbeat picks up the new subscription status on next 5-minute check-in.

New Feature — Family Shield (March 22, 2026)

🛡 Parental Controls with DNS + IP Blocking

Family Shield is a dual-layer parental control system that combines Pi-hole DNS filtering with nftables IP-range firewall rules. DNS blocking alone can’t stop apps like TikTok that use CDN fallbacks and hardcoded IPs — so we added firewall rules that block entire ASN-owned IP ranges at the packet level.

Family Shield — Bugs Fixed During Development

#SeverityComponentBugFix
85HIGHServerPi-hole v6 _suggestions API returns array format, not object — device discovery and shielding brokenRewrote parsing for {clients: [{addresses, names}]} format in 3 endpoints
86HIGHServerPi-hole v6 lists API requires ?type=block as query parameter, not in JSON bodyAdded query parameter to all POST/PUT list endpoint URLs
87MEDFrontendToggle race condition — load() polling overwrites toggle state during API callsAdded fs.busy flag, load() skips when busy
88MEDConfigfamily-shield.json owned by root, server runs as ghostport-adminFixed ownership with chown ghostport-admin:ghostport-admin
89MEDPi-holeSession exhaustion — default max 16 sessions burned by debug restartsBumped to 64 via pihole-FTL --config webserver.api.max_sessions 64
90HIGHPi-holeGravity database corruption from repeated FTL restarts — tables missingRebuilt gravity.db from scratch, re-added blocklists and groups
91MEDBlockingTikTok DNS blocking ineffective — app uses Akamai CDN fallbacksAdded nftables IP-range blocking for ByteDance ASN ranges

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,"&#39;")
109HIGH arsenal.jsescapeHtml() same single-quote gapAdded .replace(/'/g,"&#39;")
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).

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.js61Express API server + Family Shield endpoints + IP blocking
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.nft2Shared firewall rules + SSH WAN restriction
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)

What’s Next