No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-06 00:35:37 +02:00
prompts pi-security-audit v1.0.0: /security-audit LAN audit plugin 2026-10-05 21:35:13 +02:00
skills/security-audit Termux/android support for the documented loopback safe-test (127.0.0.1/32 only) 2026-10-06 00:35:37 +02:00
.gitignore pi-security-audit v1.0.0: /security-audit LAN audit plugin 2026-10-05 21:35:13 +02:00
package.json pi-security-audit v1.0.0: /security-audit LAN audit plugin 2026-10-05 21:35:13 +02:00
PLAN.md pi-security-audit v1.0.0: /security-audit LAN audit plugin 2026-10-05 21:35:13 +02:00
README.md README: real git install URL with v1.0.0 pin 2026-10-05 22:24:47 +02:00

pi-security-audit

A pi package adding /security-audit — a phased, read-only LAN security audit: host discovery → TCP port scan → service/OS fingerprinting → CVE matching → a self-contained interactive HTML report of your local network. Stdlib-only Python 3, no sudo, Linux only.

Install

# from git (pinned to the v1.0.0 tag)
pi install git:https://git.cyfrowynomada.com/CyfrowyNomada/pi-security-audit@v1.0.0

# or from a local checkout
pi install ~/Projects/pi-security-audit

Then run /reload in an active pi session; /security-audit appears in command completion (pi list shows the package).

Usage

/security-audit                 # derive the target network from the default route, gate, audit
/security-audit 10.0.0.0/24     # explicit target network
/skill:security-audit 10.0.0.0/24   # force form if the thin template fails to route
Argument Required Meaning
[cidr] no Target IPv4 network. Default: derived from ip route show default. Undecidable → the runbook asks you for it (the discovery script exits 2 with a message otherwise).

The audit workdir defaults to ./security-audit/ — evidence in <out>/evidence/, report in <out>/report/index.html. Ask for a different one and all five phases will use it; re-running against the same workdir resumes (completed phases are skipped).

Authorization & scope policy

  • Own networks only. Audit only LANs you own or administer. The skill's step-0 scope gate shows the exact CIDR, the scannable host count, and the full rate-cap table, and requires your explicit confirmation before a single packet is sent.
  • Loopback safe-test. 127.0.0.1/32 targets this host only and bypasses the confirmation gate — the built-in way to try the pipeline safely. It expects a local sshd on 127.0.0.1:22 (the fingerprint phase asserts an SSH banner there).
  • Hardcoded, unloosenable caps — 32 concurrent probes, ≥250ms sleep between port-scan batches, 10s hard timeout per fingerprint probe, 100-request CVE budget with ≥1s spacing. No CLI flag can loosen them; they are constants in the scripts.
  • Read-only. The scripts connect, read banners, and write evidence locally; they never modify remote hosts and never call xdg-open.

Phases

  1. discover — scripts/discover.py Finds this host's IP (UDP sockname) and the gateway (default route), both overridable, then sweeps the network for live hosts via unprivileged ICMP ping sockets, /proc/net/arp deltas, and pre-scan residents, cross-verified by TCP touches on 22/80/135/139/445. Writes evidence/hosts.json (with meta: {self_ip, gw_ip, cidr, platform}) plus a sample re-verification agreement score. Exits 2 with a clear message if the CIDR is undecidable or the platform is not Linux.
  2. ports — scripts/ports.py Scans every discovered host against a pinned list of 39 common TCP ports under hard caps (4 sockets/host, 32 global, ≥250ms between per-host batches, 2s timeouts, one 5s extra pass for hosts showing 0 open). An ss-based anchor cross-checks the audit host's own listeners, degrading to "n/a" if ss is unavailable. Writes evidence/ports.json.
  3. finger — scripts/finger.py Fingerprints each open port: banners, TTL-based OS buckets, SMB minimum-protocol negotiation, RDP exposure hints; individual probe families degrade to "unavailable" rather than failing the phase. A built-in dry gate fingerprints 127.0.0.1:22 first and asserts an SSH banner (needs local sshd). Writes evidence/services.json.
  4. cve — scripts/cve.py Matches fingerprinted products against cve.circl.lu with version-range containment checks, per-URL caching under evidence/cve-cache/, and verbatim raw responses archived in evidence/cve/. Offline or throttled → entries are honestly marked "CVE check unavailable"; --selftest exercises the containment logic offline. Writes evidence/cve-summary.json.
  5. report — scripts/report_html.py Renders <out>/report/index.html, a self-contained interactive report, from the evidence; missing phases degrade to "pending" badges — never a fake all-clear. Prints the report path.

Requirements

  • Linux (needs /proc/net/arp and unprivileged SOCK_DGRAM ICMP; other platforms exit loudly with code 2 and record evidence/platform-guard.json)
  • Python ≥ 3.10 — stdlib only, no pip installs, no sudo
  • Internet access only for phase 4; phases 1–3 and 5 are LAN-local / offline

Smoke test

Quick offline checks: python3 skills/security-audit/scripts/cve.py --selftest, and the loopback --dry-run gates on discover.py / ports.py. A full loopback end-to-end run (/security-audit 127.0.0.1/32, sshd on :22 required) is exercised by the T3 verification pass (see PLAN.md, Milestone M2).

Troubleshooting

  • "could not derive the LAN network" (exit 2) — pass an explicit target: /security-audit 10.0.0.0/24.
  • "unsupported platform" (exit 2) — run on a Linux host (e.g. the pi machine itself); the condition is recorded in evidence/platform-guard.json.
  • "CVE check unavailable" badge — normal when offline or cve.circl.lu is unreachable; it is not an all-clear.
  • A phase reported "already complete, skipping" — resume semantics: valid evidence in the same --out short-circuits the phase; re-run that script with --force to redo it.
  • finger aborts at its dry gate — no sshd listening on 127.0.0.1:22; start one first.