65 Commits
Author SHA1 Message Date
c4ch3c4d3 18bd6e3f9a feat(webui,dashboard): add RAM Usage card between Disk Usage and Uptime, live-verified on Pager 2026-08-24 18:12:32 -06:00
c4ch3c4d3 0f31bfe885 fix(portals,capture): round-2 validation fixes, live-verified on Pager
- portals: replace zipfile with struct+zlib ZIP writer in portal download
  (python3-light has no zipfile; GET /api/portals/<name>/download 500ed)
- capture: revive watchdog re-arms the 5 GHz deploy auto-capture if the
  post-deploy radio settle kills it (was: empty pcap, dead tcpdump)
- capture: route GET /api/attacks/capture to status (was unrouted -> 404)

New tests/test_validation_fixes2.py covers each fix (TDD); full suite
(30 modules) green. Live-verified: download CRC-clean via stock zipfile,
capture survived settle window and revived automatically (56 MB pcap),
GET status returns proper JSON.

Round-2 validation report added at docs/validation/ (8/9 attack types
PASS against in-scope networks; enterprise PARTIAL per firmware limits).
2026-08-24 08:23:26 -06:00
c4ch3c4d3 d23ea56364 fix(portals,dns,radio1,capture): live-validation fixes, verified on Pager 24.10.1
- portals: replace zipfile with struct+zlib ZIP reader (python3-light has
  no urllib; import endpoint was dead on device)
- dns hijack: uci add_list/del_list for dhcp.@dnsmasq[0].address (list
  option; plain set was silently dropped from generated dnsmasq config)
- radio1: bridge attack APs into br-lan via network.brlan.ports so
  victims get DHCP/portal reach; wlan1ent runtime-bridged after hostapd
  verify (retry loop may recreate the iface)
- capture: auto-start pinned wlan1mon pcap on 5GHz WPA deploy, teardown
  on stop; loot flows via hc22000 export (crack-verified end-to-end)
- enterprise: pineapd restart after ctrl link + re-assert PineAPE toggles

Documented residual: pineapd refuses forwarding from foreign hostapd
instances (broken pipe), and daemon set_ap rejects radio1 names - so
hostap_handshake rows for radio1 twins and enterprise cred tables cannot
populate without a Hak5 firmware change.

New tests/test_validation_fixes.py covers each fix (TDD); full suite
(29 modules) green.
2026-08-23 21:44:21 -06:00
c4ch3c4d3 88d7141d45 feat(deauth,evilportal,capture): bulk deauth UX, Hak5-compatible Evil Portal, monitor capture fixes
- Recon AP focus sidebar: 'Deauth All Clients' with engagement-scope confirm
- Deauth Targeting card: 'Deauth All' behind the same scope confirmation
- New POST /api/attacks/deauth/bulk (max 32 targets, per-target results)
- Evil Portal tab: import EvilPortalNano-format portal zips into
  /mmc/mk8/portals, serve active portal on port 80 to unauthenticated
  clients via a minimal PHP shim, capture all form POSTs (.logs in stock
  MyPortal.php format + captures.jsonl), dnsmasq address=/#/ DNS hijack
- OpenAP: Evil Portal template dropdown (greyed when none), activated with
  the attack and stopped with it
- Monitor Capture fix: iface-less status now reports whichever monitor is
  actually capturing; pcap dir mkdir'd; tcpdump stderr surfaced instead of
  discarded
2026-08-23 19:50:41 -06:00
c4ch3c4d3 ed50cd7b5a fix(enterprise,deauth,filters): PineAP validation round fixes, live-verified on Pager 24.10.1
- deauth/kick: use full PINEAPPLE_DEAUTH_CLIENT hak5cmd app name (BUG 1)
- _allow_all_ssids: PINEAPPLE_NETWORK_FILTER_MODE deny so karma lets
  clients associate after deploy (BUG 2)
- enterprise inner EAP (BUG 3), two root causes found by live experiment:
  - hostapd never wildcard-matches a bare `*` identity for phase-2
    lookups; eap_users now uses quoted empty prefix `""* ... [2]`,
    which prefix-matches any inner identity
  - pineape_auth_pass=1 forwards inner EAP to pineapd, which has no
    standalone responder; deploy forces 0 and stop restores 1
  Residual: plaintext MSCHAPv2 capture is firmware-blocked on 24.10.1
  (MSG_DEBUG compiled out of the karma wpad; `-f` silently ignored);
  documented in code comments and the validation report.
- ISSUE 4: point pineapd.@hostapd[0].mgmtiface at wlan1wpa during 5 GHz
  WPA deploys so handshakes/loot populate; cleared on stop
- ISSUE 5: radio0 set_ap path polls 90 s across the wifi-reload window
  and retries set_ap once if the iface still has not appeared
- ISSUE 6: skills docs use `llc && eth.type == 0x888e` (firmware tcpdump
  matches 0 frames on `eapol`)
- ISSUE 7: capture state helper detects dead-pid / iface-down, cleans up,
  status reports {running:false, stale:true} instead of zombie running
- tests: fix global os.path monkeypatch leaks between test modules that
  broke test_mk8_events/test_reliability_api under discovery; add
  regression coverage for all fixes above (463 tests green)

Live validation evidence and newly discovered firmware quirks
(DEVICE_FILTER_DELETE no-op, dropbear rate limiting) recorded in
docs/validation/2026-08-23-pineap-validation-report.md.
2026-08-23 18:29:47 -06:00
bzuccaro a04319dfc8 feat(webui,recon): drop PineAP mode card, sort recon report APs by signal
- Remove the Passive/Active/Advanced mode card from the PineAP dashboard
  and move the RF Role (radio1) card into its slot, along with the now
  dead mode state machinery and mode-card-only CSS.
- Sort recon HTML report access points by signal strength (strongest first).
2026-08-23 09:29:10 -06:00
bzuccaro 132cf4d77a fix(reliability): explicit hop baseline restore, immune to stale pager snapshot 2026-08-22 19:37:57 -06:00
bzuccaro 712d381093 fix(reliability): supervisor restores hop baseline unless a role holds the pause 2026-08-22 19:31:15 -06:00
bzuccaro 55d4beb9d4 fix(reliability): probe section existence via uci show, not an option key 2026-08-22 18:59:57 -06:00
bzuccaro 23ca901e82 feat(reliability): supervisor continuously enforces known-good UCI set 2026-08-22 18:37:22 -06:00
bzuccaro b9a64c6560 fix(reliability): supervisor re-parks stock-resurrected dummy STA on interval 2026-08-22 18:31:06 -06:00
bzuccaro 5625310977 fix(reliability): converge runtime after profile restore (park dummy STA, re-raise monitors) 2026-08-22 18:26:21 -06:00
bzuccaro 60db235f0b fix(reliability): converge runtime on uplink revert; bound health endpoint cost (I3,I4) 2026-08-22 16:52:29 -06:00
bzuccaro ba3e1b1ae0 fix(reliability): clear boot marker on graceful shutdown (I1) 2026-08-22 16:51:33 -06:00
bzuccaro eae47d99bf fix(reliability): encode str stdin in device_run; smoke drill path fixes + regression tests 2026-08-22 16:23:50 -06:00
bzuccaro 63528ff794 fix(deploy): unauth health poll, validate-before-gate, fullmatch names, reload-only-on-ok 2026-08-22 15:41:37 -06:00
bzuccaro 1bb15de258 feat(deploy): reliability API routes, atomic releases, version single-source 2026-08-22 15:20:39 -06:00
bzuccaro bace45d6e4 fix(reliability): rfplan review fixes — cli commit, assoc poll, ensure_attack wiring, idle reload 2026-08-22 14:35:12 -06:00
bzuccaro 15cd3c5eb8 feat(reliability): phy1 RF role manager with uplink-on-radio1 2026-08-22 14:20:05 -06:00
bzuccaro a008bb9167 feat(reliability): risky-op preflight snapshots + detached rollback watchdog 2026-08-22 13:56:25 -06:00
bzuccaro 7a27218149 feat(reliability): supervisor sampling, event feed, boot marker 2026-08-22 13:41:49 -06:00
bzuccaro 7d1eb62d75 feat(reliability): START=49 boot guard installed by deploy 2026-08-22 13:26:09 -06:00
bzuccaro 21e308386f feat: include recon identity in exports 2026-08-21 08:31:47 -05:00
bzuccaro a67faecee9 feat: associate recon clients with confirmed networks 2026-08-21 08:26:58 -05:00
bzuccaro 2c9fa8d137 fix: use live macchanger OUI path 2026-08-21 08:20:09 -05:00
bzuccaro 797db1816a feat: resolve recon device manufacturers locally 2026-08-21 08:15:21 -05:00
bzuccaroandCursor 7d48b7ad06 fix: harden UI actions and daemon calls for reliable control (v1.3.2)
Retry and serialize pineapd/hak5 calls, queue virtual-pager keys, and grey out buttons until the pager finishes. Deploy now installs python3-light after factory firmware. Bump version to 1.3.2.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-20 15:49:10 -05:00
bzuccaroandfactory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> cd26553d21 fix: non-disruptive startup checks + clean service lifecycle (v1.3.1)
- Env check is read-only when state is sane: no pineapd command-socket
  writes, no live pool-list commits, no wifi reload; pineapd restarts only
  when a runtime-sensitive UCI value changed or the daemon was down
- Failed monitor repairs now fail the startup contract instead of being
  reported as fixed; runtime pool state is read from active config
- Enterprise AP recovery runs only on device boot (PAGER_WEBUI_BOOT), not
  on every web-service restart
- serve() gates the HTTP port on startup checks with bounded retries and
  shuts down cleanly on SIGTERM/SIGINT; the recon watchdog waits
  interruptibly
- Recon uses a bounded userspace channel scheduler that drives both
  monitor radios over non-DFS channels, with preflight verification,
  serialized starts, and per-cycle error reporting
- payload.sh waits for real readiness on start, fully removes the boot
  service (stop + disable + delete) on stop, and surfaces a
  stopped-but-enabled boot service; deploy.sh refreshes the installed
  init script even when the service is stopped
- Bump version to 1.3.1

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-08-19 12:03:11 -05:00
bzuccaro 6e3968c19a fix: non-disruptive env check — drop wifi reload + misleading hop warning
- STA uplink disable now uses uci commit + ip link set wlan0 down instead of
  wifi reload, so the env check never bounces radios/APs/drops monitors
- Removed the wlan0mon 'hop is off' warning: field-verified hop=0 is normal
  (wlan1mon also reports 0 while scanning both bands); the STA/AP pinning
  checks are the real signals
- recon/status drops wlan0_hopping; UI keeps wlan0_sta + wlan0_pinned pills
2026-08-19 10:55:26 -05:00
bzuccaro 5a72566381 feat: env check auto-disables dummy_radio0 STA (2.4GHz recon root cause)
The stock STA client interface (wlan0) holds phy0's channel, pinning wlan0mon
so 2.4GHz recon captures nothing (verified: iw set channel -> Resource busy
until wlan0 is down). env_check now disables it (uci wireless.dummy_radio0
disabled=1 + wifi reload) at startup and /api/recon/status exposes wlan0_sta
so the recon page can warn if it regresses.
2026-08-19 10:42:26 -05:00
bzuccaro 5eb81b90f1 fix: recon env-check verifies runtime wlan0mon hopping (2.4GHz starvation)
The band UCI config looked correct but pineapd was not hopping wlan0mon at
runtime, so 2.4GHz recon results were entirely absent. env_check now parses
_pineap INTERFACE LIST and warns when wlan0mon hop is off; /api/recon/status
exposes wlan0_hopping and the recon scan bar surfaces it.
2026-08-19 10:29:50 -05:00
bzuccaro 904843307e feat: startup environment check + self-heal (v1.3)
- env_check(): verifies daemon/pineapd/UCI/monitors/recon DB, auto-fixes
  fixable issues and re-verifies; forces runtime SSID-pool broadcast off to
  match the UI (kills the 'pool on but UI shows off' gap)
- server.py --env-check CLI; payload.sh runs it verbosely before starting,
  aborts on core failure
- serve() runs the check at every startup (boot + procd respawn)
- /api/health exposes env report + pool_runtime; /api/recon/status exposes
  wlan0_pinned (2.4GHz under-sampling warning); recon page warns when a
  radio0 AP pins wlan0mon
- recon start failures now include the daemon reason in the UI error
- shared stabilization refactor (_stabilize_uci/PINEAPD_SAFE_UCI/_raise_monitors)
- tests: test_env_check.py (18) + health/recon updates
2026-08-19 10:25:02 -05:00
bzuccaro 52f9f6ecd5 chore: bump version to 1.2; scrub personal details from docs
- Version 1.1 -> 1.2 in the hak5 manifest and MCP serverInfo.
- Removed leaked personal details from process docs: device root password,
  the user's personal iPhone SSID (authorized-test target), the local
  /Users/... checkout path, and the device IP where it appeared alongside
  the password. Replaced with <device-password>, <authorized-test-ssid>,
  <repo>, and <device-ip> placeholders.
2026-08-19 08:21:28 -05:00
bzuccaro 1be93bc24b fix: MCP pineap.set_filter supports delete/clear/allow_all
The tool only accepted set_mode/add, so entries added via MCP could never be
removed. Now passes the full action set through to the same endpoint the UI
uses and returns the resulting mode/entries. Verified on device: add ->
delete round trip leaves the filter empty.
2026-08-19 00:07:08 -05:00
bzuccaro f6b4cadc39 fix: client kick/deauth use full bssid/target/channel deauth form
hak5cmd on this firmware has no CLIENT_KICK command and PINEAPPLE_DEAUTH_CLIENT
requires (bssid, target, channel) — the UI kick/deauth buttons and the MCP
pineap.kick_client tool previously passed only the client MAC, which printed
usage and silently did nothing.

- _deauth_target/_deauth_client_via_iface resolve the client's association
  interface via iwinfo (Access Point + Channel), pick the band-aware inject
  interface, and issue DEAUTH_CLIENT <bssid> <mac> <channel>
- h_client_kick: deny-filter (persistent) + immediate deauth with rc checks
- h_deauth_client: deauth with the full form; 502 with detail when the
  client is not associated
- MCP pineap.kick_client: resolves the client first (no side effects on
  failure), then deny-filter + deauth; verified on device (clean error for
  unassociated clients, filter list restored)
- tests updated for the new command chain
2026-08-19 00:05:42 -05:00
bzuccaro e93359fb69 feat: merge attacks into PineAP menu; auto channel; recon fixes; richer reports
- Rail: Attacks tab removed; PineAP becomes a grouped menu (Evil WPA /
  Evil Open / Evil Enterprise / Impersonation / Clients / Filtering);
  old #/attacks* hashes redirect to their PineAP equivalents.
- PineAP tabs gain Evil Enterprise; stock Open AP / Evil WPA / Enterprise
  pages replaced by the verified one-click launchers (status, capture,
  export, deauth, playbooks).
- Channel selects gain an Auto option: deploy resolves the target SSID's
  last-seen channel from recon.db (verified unit-tested end to end).
- Harness: pi.dev prompt section removed; Copy Token inline; robot icon.
- Recon: compare checkboxes no longer hide the AP list (multi-select
  stays visible, rows highlighted, clients table no longer suppressed);
  Previous Scans buttons moved above the dropdown with a Delete All;
  encryption chips + buckets now distinguish WPA2/WPA3 PSK vs Enterprise
  (AKM suites decoded from recon bitfield bits 32-47); scan JSON carries
  GPS when a fix exists; Reports tab shows a GPS column.
- fix: restore top-level EVIL_ENC definition lost in the repo (deployed
  build had it; repo would have thrown at init).
2026-08-18 22:35:51 -05:00
bzuccaro 1d807a1fcf fix: health check repairs dropped monitors even when pineapd is healthy
wifi reloads during attack deploy/stop drop the monitor interfaces and
pineapd only recovers its primary; the monitor now brings both up
whenever it finds them down, with or without a pineapd failure.
2026-08-18 21:33:11 -05:00
bzuccaro ce1f6a8442 fix: passive health check + hop=0 in stabilization pass
Active PINGs on pineapd's command socket collided with the stock daemon's
own socket writes ('[PineAp] Error writing'), making the daemon watchdog
SIGTERM pineapd every ~30s while hopping. Monitor now checks pidof only
(no socket writes) and the stabilization pass pins wlan1mon hop=0.
2026-08-18 21:05:39 -05:00
bzuccaro b5d9ed39ff fix: health monitor stabilization pass for all pineapd crash sources
Field-verified crash stack on this firmware: SSID-pool broadcast (segfault),
wlan2mon hopping a nonexistent 6GHz iface (segfault), wlan1mon fast-hopping
6GHz channels (ASIO thread exit), and a large refilled pool. The fix path
now enforces: pool broadcast off, pool list cleared, wlan2mon off, wlan1mon
5GHz-only, wlan0mon 2.4GHz-only — idempotent, so collect refills self-heal.
8-minute continuous-PONG stability verified on-device.
2026-08-18 20:47:43 -05:00
bzuccaro adfe8f784f fix: health monitor detects down monitors via ip link flags + disables wlan2mon
operstate reports 'unknown' on monitors (normal), so _iface_up now parses
admin flags from ip link. Discovered a second pineapd SIGSEGV source: the
wlan2mon 6GHz monitor this hardware never creates, hopping on the missing
iface (~85s crash cadence even with the SSID pool off). The monitor now
disables it in the fix path.
2026-08-18 20:26:16 -05:00
bzuccaro d10fba9d1b fix: never re-enable SSID pool broadcast (crash guard) + top-bar health chip
Mode 'active' and the advertise toggle could re-enable the SSID-pool
broadcast that segfaults pineapd. active preset now skips ssidpool/enable
(advertise stays false), the advertise endpoint refuses with an
explanation when the pool is disabled, get_ap reports the real pool
state, and the PineAP overview disables the toggle with a notice. Added
a top-bar health chip (PINEAP OK / POOL OFF / PINEAPD DOWN) polled every
15s.
2026-08-18 20:16:41 -05:00
bzuccaro d5506e2aaf fix: 45s verification window for daemon-applied APs (reload cycle) 2026-08-18 20:03:07 -05:00
bzuccaro e871e49466 feat: local MCP harness (tools/resources/prompts) + Harness UI page
Streamable-HTTP MCP server on POST /mcp: device.state, attack.deploy/stop/
status/deauth/capture/export_hc22000, loot.handshakes/enterprise_creds,
recon.aps/isearch/devices, pineap.kick_client/set_filter tools; recon DB +
bundled opencode skills resources; attack playbook prompts. Cookie or Bearer
auth. Harness page shows endpoint, token, curl snippet, capability explorer
and a copy-paste pi.dev prompt. scripts/harness_stdio.py for stdio-only
agents.
2026-08-18 20:00:13 -05:00
bzuccaro f31b38d1fa feat: enterprise deploy retry loop + karma filters (deny=allow-all) 2026-08-18 19:58:01 -05:00
bzuccaro c33d5d01f3 fix: use MSCHAPV2 wildcard in enterprise eap_users (PAP unsupported) 2026-08-18 19:55:04 -05:00
bzuccaro 603e249999 feat: standalone PineAPE enterprise engine on phy1
The stock daemon's enterprise config generation is broken on this firmware
(it hardcodes eap_server_erp=1, which hostapd rejects), so the enterprise
attack now runs its own karma+PineAPE hostapd instance on wlan1ent/phy1:
iw-created iface, EAP config with catch-all user file, pineape+auth capture
enabled via ctrl, mgmtiface registered in pineapd UCI so captured creds
flow into recon.db (hostap_basic/hostap_chalresp). Boot-recovery redeploys
a live attack after a Mark VIII restart.
2026-08-18 19:53:56 -05:00
bzuccaro a4285496fb fix: health monitor disables SSID pool immediately on PING failure
Ring-buffer SIGSEGV counts were unreliable for growth detection; the pool
broadcast is the only known crash cause, so disable it on first failure.
2026-08-18 19:32:49 -05:00
bzuccaro 2ff0c4d320 feat: Attacks UI (Overview + Evil WPA/Open/Enterprise launchers)
Side-menu Attacks section with deploy/stop launchers, live status card
(device truth), monitor capture toggle, hashcat .hc22000 export + download,
deauth targeting panel, enterprise cred tables and PineAPE toggles.
2026-08-18 19:30:26 -05:00
bzuccaro 01c84caaaa feat: pineapd health monitor with crash-loop auto-fix
15s poll; on PING failure, detects SIGSEGV growth (SSID-pool crash-loop),
disables pool broadcast, restarts pineapd, brings wlan1mon up. Rate-limited
fix actions, /api/health endpoint.
2026-08-18 19:28:32 -05:00
bzuccaro 63fa5ae94a feat: one-click attack orchestration backend (Evil WPA/Open/Enterprise)
Deploy/stop/status/capture/export-hc22000/deauth endpoints. Band-aware
deauth inject (wlan0mon for 2.4GHz), enterprise AP via wlan0ent + PineAPE,
verified writes polled from /sys, hop resumed when no radio1 AP active.
2026-08-18 19:27:25 -05:00