- 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.
- Landscape card mirrors Encryption: headline text removed; square 112px
ring (drawn height 112, CSS fixed square, no more ellipse) + HTML legend
(dot + label + count) for Access Points / Clients / Unassociated. The
canvas previously had no legend and the '90' headline never matched the
dominant arc; the legend makes every count visible and labeled.
- Legend markup generalized: .recon-enc-* -> .recon-chart-* shared by both
cards; shared chartLegendEntry() builder; landscape skips zero slices.
- .recon-toggle now flex-wraps (was overflowing 'Auto-collect handshakes'
past the card edge at narrow widths; card min-width inner is ~142px vs a
233px label).
Verified on device via CDP at 1200px and 860px viewports: landscape ring
112x112 square with Access Points 92 / Clients 291 / Unassociated 760;
encryption card intact; toggle label stays inside the 184px card (wraps to
2 lines, no card overflow); zero JS exceptions.
The enc canvas was drawn at 233x120 internally but .recon-chart-box canvas
forced width:100%/height:100% onto a ~233x115 box, scaling the bitmap and
flattening the ring. #recon-encryption is now a static 112px square with the
doughnut drawn at height 112, so internal and CSS pixels match (1:1) and the
circle stays circular. Verified on device: box and bitmap both 112x112,
card fits without overflow, legend intact, no JS exceptions.
- Ring and legend now derive from reconEncBucket's actual family keys
(WPA2-PSK, WPA3-Personal, WPA2-Enterprise, ...) instead of the six
nominal buckets that never matched encCounts, so the ring drew an
empty ring and the legend was always blank on WPA2-dominated data.
Ordering via RECON_ENC_ORDER; colors cycle RECON_ENC_COLORS.
- Legend div had class but no id while drawCharts looked it up with
getElementById — the population block silently never ran. Added the id.
Verified on device via CDP: legend lists Open 9, WEP 1, WPA2-PSK 44,
WPA3-Personal 20, WPA3-Enterprise 5 with per-family dot colors; no JS
exceptions.
A hung read can no longer stall the recon/pineap poll loops (AbortController).
Writes keep no client abort: radio deploys legitimately take up to 45s
server-side. Cache-bumped api.js.
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.
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
- Top 5 recon cards restyled as stat cards: value + sub-line + mini chart,
consistent 190px anatomy; Handshakes links to the handshakes page;
Previous Scans shows count/latest plus a compact picker + action row
- Channel map records lobe geometry (canvas.__reconLobes / __reconLobesHit);
hovering lists the networks under the cursor, click pins the tooltip,
mouseleave hides it; empty states hide the tooltip too
- Recon focus sidebar gains 'Send to PineAP — Twin this network': routes to
Evil WPA (psk2/sae/owe from recon encryption) or OpenAP (with BSSID) and
prefills the form; one-shot PineAPPrefill is consumed by the attack
launcher and never auto-deploys or leaks into manual forms
- Existing Actions verified end-to-end and hardened: capture/stop handshake
sync the auto-collect toggle, examine buttons disable while pending
- Recon resilience: loadDetail retries after failed render or 503 (no more
permanently blank page), scan-list errors surface in the scan bar, poll
guard prevents overlapping loads, chart draws are individually isolated
- Auto-collect toggle re-syncs from get_config on the slow poll so the UI
tracks the pager's own settings
- 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).
pineapple-control gains the uplink-pins-phy0 constraint, the five-part
pineapd crash stack, and the standalone PineAPE engine recipe; wifi-deauth
gains the field-verified passive-capture finding (clients that refuse the
evil twin still produce crackable 4-ways of the real AP, [B,1,2,3,4]).
Evil WPA playbook hint mentions the passive fallback. Skills are served to
agents via MCP resources.
Evil WPA/Open pages now show a state-aware playbook (current step
highlighted, contextual hint) and the Deauth Targeting panel
auto-fills the live attack SSID and refreshes clients automatically.
Enterprise page gains a playbook hint card.
The notification bell now receives event-driven alerts: new handshake
captures, new enterprise credentials, pineapd down/recovery and monitor
drops (15s poll, diffs against last-seen state). Dashboard gains an
Attacks / PineAPd / Recon live status row.
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.
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.
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.
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.
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.
The Attacks shell created its content div but never attached it to the
document, so all launcher cards rendered into a detached subtree (tabs
only were visible). Bumped views.js cache version in index.html.
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.
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.
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.
get_ap now reports radio0, radio1 and enterprise APs separately from UCI
(never a stored/cached branch), with radio channel fallback. Mode is
derived from live enabled/collect state instead of showing 'unknown';
device truth wins over stale stored presets.
- Delete the Survey stack (sampler, handlers, routes, view, recordings);
Scanning gains AP compare (cap 6), whole-page selection filter, channel
map (20 MHz lobes, the radio does not report width), and auto-follow
that prefers the newest non-empty scan
- Richer HTML scan reports: stat cards, band/encryption breakdowns,
channel occupancy, color-coded signal cells, GPS line only on a fix
- Harden live recon: bounded + retried scan-detail reads (503 on lock),
serialize recon starts (409 + scan_remaining while running), GPS and
archive discovery move to a 30s poll, GPS_GET skipped when gpsd is down
- Read-only history for pineapd-rotated databases (error-*/diagnostic-*):
archives list/detail/download endpoints, Previous Scans optgroup,
delete disabled, traversal-guarded
- Status flags: hopper-radio-offline and history-reset banners; empty
scans greyed in the picker
- Tests: recon suite grows to 99 cases; all 14 modules green
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Reconnaissance surveys (GPSD-tethered scan recording), OUI vendor
lookup for client/AP tables, survey/report pages, and the matching
test_recon.py suite. Co-authored with the recon-feature agent whose
work was finished in this checkout.