Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Releases: emrecdr/netlens

v0.4.0

04 Jun 15:32
@emrecdr emrecdr

Choose a tag to compare

Added

  • Bluetooth capability callouts: 24 new curated capability entries
    covering every BLE finding template.
    Every BLE check (gatt_misconfig,
    pairing, privacy, spoofing, mesh, beacons, companion_app,
    continuity_leak, tracking, plus platform notices and the
    bettercap escalation) now constructs its Finding with an explicit
    template="..." id, and a matching entry in
    security/capabilities.CAPABILITIES describes the attacker
    capability in plain language. The HTML report and netlens demo
    terminal output render the curated "What this means" callout for
    BLE findings just like they do for IP-side ones.
  • New Capability.attacker_context value "radio-range" covers BLE
    findings whose threat model is "an attacker within Bluetooth range"
    rather than "an attacker on the same LAN". The lead-in phrase
    becomes "An attacker within Bluetooth range could:" in both the
    HTML report and demo terminal output. All 24 BLE entries use this
    context.
  • SQLite schema migrates V7 → V8: bluetooth_findings.template
    column added.
    History-replayed BLE findings (netlens demo --scan-id <id> on a stored BLE scan) now carry their template id
    through and the capability callout renders for them too. Migration
    is idempotent via column-existence check; pre-V8 BLE rows have
    NULL template and fall back to the generic capability description.

Added

  • netlens demo --scan-id <id> and --latest-scan — historical
    replay.
    Reuses the existing HistoryStore.load_scan(scan_id) /
    list_scans(limit=1) paths to demonstrate against a stored scan
    instead of running a fresh one. Findings carry their template ids
    via the V7 schema migration, so the same curated "What this means"
    callouts render for replayed findings. Flags are mutually exclusive;
    both unset preserves the existing live-scan behavior.
  • make watch target — re-runs the test suite via entr whenever a
    .py file under src/ or tests/ changes. Optional system dep;
    prints an install hint if entr is missing instead of failing
    cryptically.

Changed

  • Capability descriptions now carry an attacker_context field
    selecting the lead-in phrase used by the report and demo terminal
    output. Three values: "lan" (default — "An attacker on the same
    LAN could:"), "user-browser" (DNS rebinding — "A public web page
    the device owner visits could:"), "lan-to-wan" (UPnP IGD control
    — "An attacker on the LAN could pivot WAN exposure to:"). The
    framing is now accurate for the two findings whose threat model
    isn't a same-subnet attacker.
  • dns_rebinding capability rewritten — now correctly describes the
    attacker as the device owner's browser (driven by an attacker-
    controlled web page), not a same-LAN attacker. Previous framing was
    technically misleading.
  • unauth_upnp_dangerous capability tagged attacker_context="lan-to-wan"
    to make the WAN-exposure pivot legible in the report rendering.
  • HTML report's "What this means" callout styles moved from inline
    style="..." attributes into the existing <style> block as
    .capability-callout rules. Easier to theme, lighter markup.

Added

  • 18 additional verify_command entries — coverage doubles from
    14 to 32 of 59 templates.
    Curated one-line commands for the
    highest-leverage remaining finding types:

    • Printers: unauth_ipplpstat -h {address};
      unauth_jetdirect → PJL status query via nc {address} 9100.
    • Cameras: unauth_rtsp / rtsp_default_credsffprobe against
      the RTSP URL (with or without creds).
    • TLS: weak_tls_cipher / old_tls_protocol
      nmap --script ssl-enum-ciphers;
      expired_tls_cert / self_signed_certopenssl s_client +
      x509 -noout -dates / -issuer / -subject.
    • HTTP: http_only_admincurl -v http://{address}/;
      dangerous_http_methodscurl -X OPTIONS -i http://{address}/.
    • MQTT: mqtt_full_controlmosquitto_pub to own topic;
      mqtt_subscribe_allmosquitto_sub -t '#' -C 5 -W 5.
    • UPnP: unauth_upnp_service / exposed_upnpnetlens demo
      against the device (recurses through the existing UPnP capture).
    • CoAP: coap_resources_exposedcoap-client -m get coap://{address}/.well-known/core.
    • ARP: arp_ip_mac_conflictarp -n {address} (compare
      against evidence MACs).
    • BLE: ble_pairing_dual_modenetlens probe {address};
      ble_bettercap_extra_devicesudo bettercap -eval 'ble.recon on; sleep 30; ble.show; quit'.

    The remaining 27 templates without a verify_command are
    intentional skips: passive-observation findings (beacons, Apple
    Continuity, PII in BLE names), reference-only findings (cve_found,
    firmware_outdated, favicon_identified), or commands too complex
    to reduce to one line (dns_rebinding, rogue_dhcp_server,
    llmnr_active, nbtns_active, gratuitous_arp_flood,
    ble_findmy_separated, ble_tracking_*, ble_mesh_*,
    ble_macos_gatt_blocked). The structural test
    (test_every_verify_command_substitutes_without_leftover_braces)
    catches any new template with a broken substitution before merge.

Refactored

  • Extracted shared finding-panel renderer to output/finding_panel.py.
    Before: three commands (netlens demo, netlens risks,
    netlens bluetooth) each had its own ~50-line copy of the same
    "render finding as Rich Panel with capability headline + lead-in +
    action bullets + verify_command" code. The render shape evolved
    three times in three places this session. Now there is one
    build_actionable_panel(address, finding) → Panel builder and one
    render_actionable_section(rows, console) that filters to
    CRIT/HIGH and prints panels. Three consumers collapse to a few
    lines each. Net: ~90 lines removed, single source of truth for the
    panel shape, identical rendered output verified by the 10 existing
    verify-command tests.

Added

  • netlens correlate --json and --verbose flags. --json
    emits the correlations as a single JSON payload to stdout
    (suitable for jq consumption); --verbose expands the per-signal
    score breakdown in the rendered table when the matcher exposes it.
    Brings correlate to CLI-flag parity with scan, risks,
    bluetooth, demo, traffic, segment, topology, history,
    diff, devices.

  • netlens watch --json and --verbose flags. --json switches
    the loop from a live status table to JSONL output — one object per
    cycle on stdout with cycle, scan_id, timestamp, devices,
    findings, and (when --verbose) the full diff payload. Suitable
    for piping into a log aggregator. Webhook delivery still fires
    independently when --webhook-url is also set.

  • README documents the "What this means / What to test next" UX
    introduced this session (curated capability callouts +
    copy-pasteable verify commands), the netlens bluetooth --verify
    interactive walk-through, and the make-target convenience
    targets
    including the new make bluetooth-verify. The Quick
    Start now references the Makefile so contributors don't have to
    memorise the uv run incantations.

  • netlens risks now renders capability + verify-command callouts
    for CRIT/HIGH findings.
    After the existing per-severity tables,
    an "Actionable findings (N CRIT/HIGH) — what to test next:" block
    prints one panel per finding showing the title, evidence, curated
    capability headline, and the substituted verify command (e.g.
    netlens demo 192.168.1.50 --prove-creds). Closes the gap where
    the most-frequently-run command had no actionable next-step
    rendering despite having all the data available.

  • BLE HTML report parity for capability callouts. Every CRIT/HIGH
    BLE finding in the standalone HTML audit report (netlens bluetooth --report PATH) now ships with a collapsible "What this means" panel
    showing the curated attacker capability, attacker-context-aware
    lead-in ("An attacker within Bluetooth range could:"), bulleted
    action list, and verify-command block. Brings the BLE HTML report
    to feature parity with the IP scan HTML report.

  • make bluetooth-verify Makefile target — runs the BLE audit with
    the interactive --verify walk-through enabled, so the new
    guided y/N-per-finding flow is discoverable via make help.

  • 10 new tests covering the render_verify_command helper (substitution,
    None handling, literal-placeholder pass-through), a structural test
    asserting every curated verify_command substitutes cleanly without
    leftover braces, integration tests for the risks-table actionable
    section, and a BLE-HTML-context test verifying capability blocks
    attach to CRIT/HIGH findings only.

  • verify_command per Capability — copy-pasteable next-step tests.
    Each curated capability entry can now carry a one-line command the
    user can run to verify or actively demonstrate the finding on their
    own device. {address} is substituted with the device's IP or BLE
    MAC at render time. Currently wired for the highest-leverage finding
    types: ble_gatt_writable_no_auth
    netlens probe {address}, ble_manufacturer_mismatch
    python scripts/bt_read_all.py {address}, ble_pairing_discoverable,
    ble_companion_app_match, default_creds_ssh/default_creds_http/
    default_creds_admin_panelnetlens demo {address} --prove-creds,
    default_creds_telnet/open_telnettelnet {address},
    default_snmp_communitysnmpwalk -v 2c -c public {address} system,
    unauth_admin_panelcurl -sS http://{address}/ | head -20,
    unauth_mqttmosquitto_sub -h {address} -t '#' -C 5,
    anonymous_ftp, unauth_upnp_dangerous. The render layer surfaces
    the command in three places: netlens demo's per-finding panel,
    the HTML report's "What this means" capability callout, and the
    JSON bundle (capability.verify_command).

  • **netlens bluetooth now rend...

Read more
Assets 2
Loading

v0.3.0

02 Jun 08:13
@emrecdr emrecdr

Choose a tag to compare

Architecture-level refactor release. Introduces netlens.net as the
canonical home for shared transport primitives (probe HTTP client, port
constants, scheme helper) and documents the layering rule that keeps
feature modules from cross-importing each other for plumbing. Fixes a
silent cross-store MAC-case mismatch via a v5 → v6 schema migration,
re-roots netlens risks to read from history by default (saving an
unintentional live scan on every invocation), and collapses N+1 SQLite
patterns in load_scan and post-scan baseline drift. Bluetooth checks
now fan out concurrently. All 14 HTTP probe sites flow through a single
probe_client() factory with consistent secure-by-default knobs.

Architecture

  • Introduced netlens.net as the canonical home for shared transport
    primitives. probe_client (formerly security/_http_client.py),
    HTTPS_PORTS, HTTP_SERVICE_NAMES, and the new scheme_for_port()
    helper now live there. Eighteen feature-module call sites import from
    netlens.net instead of cross-importing from security/credentials.
    Deleted the orphaned security/_http_client.py. Documented the
    layering rule in CLAUDE.md (cli → orchestration → feature modules → storage/output → net → models).
  • Replaced the
    scheme = "https" if port in HTTPS_PORTS else "http" ternary
    duplicated across six probe modules with a single
    scheme_for_port(port) helper.

Fixed

  • MAC case mismatch across stores (silent data bug). The devices.mac
    column was stored lowercase (ARP-side normalization) while baselines.mac
    and device_profiles.mac were stored uppercase (profiles-side normalization).
    Cross-store queries by MAC silently returned zero results — most visible
    in netlens devices show <MAC> --history. The two divergent
    normalize_mac() implementations are unified into a single
    lowercase-canonical helper in netlens.fingerprint.mac_lookup. Schema
    migrates v5 → v6 in place: UPDATE device_profiles SET mac = LOWER(mac)
    and the same for baselines. Idempotent via WHERE mac != LOWER(mac).
  • netlens risks no longer triggers a full live scan on invocation. It
    now reads the most recent scan from history (matching the post-scan
    "Next Steps" panel's promise of Show findings (N found)). Pass
    --scan-id to target a specific stored scan or --rescan to force a
    live audit. A positional network argument still implies --rescan
    to avoid showing stale history for the wrong subnet.

Changed

  • HistoryStore.load_scan no longer issues 3 queries per device. Ports,
    findings, and services are now batched into one query per child table
    (1 + 1 + 3 instead of 1 + 1 + 3N round-trips). Large stored scans
    open noticeably faster in netlens report and netlens risks.
  • HistoryStore.save_scan now auto-prunes past the 500 most recent
    scans. Long-running watch sessions no longer grow history.db
    without bound. FK cascade wipes the device/port/finding/service rows.
  • _attach_baseline_findings (post-scan baseline drift) now reads all
    baselines in a single query (ProfileStore.get_latest_baselines)
    instead of one SQLite open + WAL pragma per device MAC.
  • Bluetooth checks fan out via asyncio.gather instead of running
    serially per device. An audit pass now scales with the slowest check,
    not the sum of all checks. Per-check exception isolation preserved.

Security

  • All HTTP probe traffic now routes through a single
    netlens.security._http_client.probe_client() factory with
    consistent secure-by-default knobs (verify=False for self-signed
    IoT certs, follow_redirects=False for SSRF defence, identifying
    User-Agent: NetLens/<version> so operators can recognise probes
    in their logs). Replaces 14 inline httpx.AsyncClient(verify=False, ...)
    instantiations across security/*.py and fingerprint/*.py. The
    webhook client (notify/webhook.py) and the SSDP discovery client
    (discovery/ssdp.py) keep their own configuration — they're not
    probe traffic.

Internal

  • make_finding(*, severity, title, description, evidence, template, **vars)
    factory in security/remediation.py collapses the
    Finding(... remediation=render_remediation("X", ip=ip, port=port))
    boilerplate repeated across 38 probe sites (security/*.py,
    traffic/arp_anomalies.py, snmp/community.py,
    discovery/dhcp_probe.py, bluetooth/checks/cve.py,
    fingerprint/favicon.py). Template vars are stringified inside the
    factory so callers can pass port=int.
  • Severity.rank property + ALL_SEVERITIES_BY_RANK tuple added to
    models/finding.py as the single source of truth for severity sort
    order. Replaces hand-rolled _SEVERITY_ORDER lists in panels.py,
    risks_table.py, scan_dashboard.py, bluetooth_table.py, and
    the stringly-typed _SEVERITY_PRIORITY dict in deviation_table.py.
    DEVIATION_SEVERITY_RANK promoted to profiles/models.py.
  • severity_badge() helper in output/theme.py replaces the
    f"[{style}]LABEL[/{style}]" markup repeated across three renderers.
  • HTTPS_PORTS and HTTP_SERVICE_NAMES consolidated to one definition
    in security/credentials.py. Six modules
    (protocols.py, tls.py, admin_panels.py, dns_rebinding.py,
    rest_api.py, fingerprint/banner_grab.py) now import the canonical
    copy instead of redeclaring it.
  • Stale noqa: PLC0415 deferred imports removed from
    history/store.py (load_scan / load_bluetooth_scan). No real
    cycle existed; imports hoisted to module top.
Loading

v0.2.0

02 Jun 08:13
@emrecdr emrecdr

Choose a tag to compare

The biggest release since 0.1.0. Three new pillars: a 10-phase
Bluetooth security audit (netlens bluetooth) with industry-standard
coverage (firmware-CVE pipeline, beacon/continuity parsers, anti-stalking
detection, companion-app DB, optional active write-probe), a WiFi
security audit
surfacing WPS / PMKID / WEP / Open findings end-to-end
through the CLI and HTML report, and cross-radio correlation
(netlens correlate) that joins WiFi/IP devices with their BLE adverts
into a single device view. Adjacent additions: interactive netlens probe for one-target BLE GATT exploration, netlens watch --webhook-url
for change notifications, behavioral baseline drift findings, and a
self-contained scripts/ toolkit (bt_connect_demo.py, bt_read_all.py,
bt_control.py) for hands-on BLE exploration outside the main CLI.
Adds the optional [bluetooth] extra (uv sync --extra bluetooth) for
bleak + pyyaml. SQLite history schema migrates v3 → v4 → v5 in place;
existing IP-scan history is preserved.

Added

  • New netlens bluetooth subcommand — industry-standard BLE security
    audit. Ten phases shipped:

    • Phase 1 Passive BLE discovery via bleak, advertisement
      fingerprinting (manufacturer ID lookup, service UUIDs, RSSI), BLE
      address-type detection (Public / Random Static / RPA / Random
      Non-Resolvable), persistence to SQLite history.
    • Phase 2 GATT enumeration of the Device Information Service
      (firmware/hardware/software revision, manufacturer string, model
      number, serial number, PnP ID) plus a 3-stage CVE pipeline:
      NVD CPE search → NVD keyword-search fallback → offline curated
      chipset DB (vulnerable_chipsets.yaml) covering the SweynTooth
      family across Cypress / TI / Nordic / Espressif chipsets,
      BrakTooth on Intel and Qualcomm, BleedingTooth (Linux host-side),
      and KNOB. GATT enum is allowlist-gated by default — connections
      only attempted for devices in ~/.netlens/bluetooth_allowlist.txt;
      --connect-all overrides with a 5-second consent banner.
    • Phase 3 iBeacon / Eddystone (UID/URL/TLM/EID) / AltBeacon
      parsing, Bluetooth Mesh detection, and service-UUID device
      classification (Heart Rate Monitor, Smart Lock, AirTag,
      Eddystone beacon, etc.).
    • Phase 4 Apple Continuity Protocol parsing (Handoff, AirDrop,
      Nearby Info, Wi-Fi Settings, AirPods, FindMy separated) and
      Microsoft Swift Pair parsing. Surfaces detached-AirTag warnings,
      Wi-Fi-setup social-engineering windows, and PII in laptop names.
    • Phase 5 Curated checks: pairing-mode posture (discoverable +
      connectable, dual-mode BR/EDR + LE), writable-without-auth GATT
      characteristics, manufacturer-ID ↔ DIS string spoofing, PII in
      advertised name (apostrophe-s, room labels, MAC fragments), and
      BLE address-randomization posture (Public / Random Static flagged
      as trackable).
    • Phase 6 Curated companion-app fingerprint DB
      (companion_apps.yaml) with 15+ products: AirTag, Tile, Chipolo,
      SmartTag, August / Schlage / Yale / Wyze locks, Apple Watch,
      Fitbit, Garmin, Sonos, AirPods, Hue, LIFX. CVE attachment per
      product where published.
    • Phase 7 Active write-probe (--probe-writes) — writes a
      benign 0x00 to writable GATT characteristics to confirm or
      mitigate Phase 5 "writable-no-auth" findings. Allowlist-gated by
      default; --probe-writes-all overrides with a 5-second consent
      banner. Outcomes classified as success / auth_required /
      timeout / disconnect.
    • Phase 8 Cross-scan tracking / stalking detection. Reuses the
      history DB to score fingerprint persistence across the lookback
      window (default 10 scans). Flags devices appearing in ≥60% of
      scans across ≥2 location tags as MEDIUM (or HIGH when also matched
      by the companion-app DB). Special handling for AirTag-class
      beacons that rotate identifiers — surfaces persistent FindMy-class
      presence even when individual AirTag identifiers can't be
      deduped. ~/.netlens/bluetooth_owned.txt suppresses tracking
      findings for the user's own devices.
    • Phase 9 Platform escalation engines (best-effort augmentation,
      silently skipped when unavailable):
      • macOS system_profiler SPBluetoothDataType -json parser
        enumerates paired Classic Bluetooth devices (keyboards, speakers,
        gamepads — invisible to BLE-only bleak scanning) with their real
        MAC addresses, and cross-references with discovered BLE devices
        to mark host-paired ones as trusted.
      • Linux invokes bettercap when the binary is on PATH; parses
        its JSON event stream for ble.device.new and
        ble.device.service.discovered events; merges into the device
        records.
    • Phase 10 Standalone HTML audit report (--report PATH).
      Self-contained: inlined CSS, no network requests, severity-coloured
      findings table, beacon detail, continuity-protocol breakdown.
      Reuses the existing Jinja2 environment + autoescape config from
      netlens.reports.generator.ReportGenerator so any future HTML-
      escaping hardening applies automatically.

    CLI flags: --duration, --connect/--no-connect, --connect-all,
    --gatt-timeout, --gatt-concurrency, --allowlist, --skip-cve,
    --offline-only, --probe-writes, --probe-writes-all,
    --tracking/--skip-tracking, --tracking-lookback,
    --tracking-threshold, --owned-devices, --skip-escalation,
    --report PATH, --location, --json, --verbose. Ships behind
    the [bluetooth] extra: uv sync --extra bluetooth.

  • New first-class netlens probe subcommand: the interactive BLE
    GATT control-surface probe that previously lived as a stand-alone
    script (scripts/bt_control_probe.py) is now discoverable via
    netlens --help. Same flags (--list, --latest, --write,
    --payload, --no-notify, --timeout) and same workflow — enumerate
    characteristics, mark writable ones, optionally drop into a REPL or
    fire a one-shot targeted write. Registered as a leaf command (not a
    sub-typer) so the natural netlens probe <address> --write <uuid>
    invocation works without the options-before-positional gotcha that
    applies to the other invoke_without_command=True subcommands.
    The stand-alone script remains as a DEPRECATED shim so older
    pip-installed copies keep working.

  • New read_full_value(client, char) helper in netlens.bluetooth.gatt
    that loops read_gatt_char past the ATT-MTU saturation thresholds
    (20, 244, 251, 509, 512, 514) and concatenates the resulting chunks
    so callers see the full payload — not just the first chunk truncated
    at the BLE PDU ceiling. Returns (bytes, truncated_flag) where the
    flag is True when the read hit the max_size safety cap (default
    4096) or the per-call iteration cap (8). Defences against pathological
    backends include duplicate-chunk detection (some bleak backends ignore
    offset and return the same first bytes on every call) and partial-read
    preservation on mid-loop exceptions. Wired into netlens probe's
    REPL r <index> path and the --write read-back so Chromecast-style
    gzipped config blobs come out whole instead of truncating at 512B.
    netlens probe also now prints the negotiated MTU at connect so the
    user has the context to interpret a ⚠ truncated annotation.

  • BLE device fingerprints now expose their contributing signals
    (manufacturer ID, manufacturer-data prefix, sorted service UUIDs,
    advertised name) alongside the SHA-256 hash. The hash contract is
    unchanged so existing tracking state survives — what's new is
    BluetoothDevice.fingerprint_components (Pydantic field) and a
    matching bluetooth_devices.fingerprint_components_json SQLite
    column (V4→V5 migration; non-destructive ALTER TABLE ADD COLUMN,
    pre-V5 rows return None). netlens bluetooth -v prints a
    per-device "fingerprint signals" line so users can see why two
    adverts collapsed to the same device — an explainability story
    increasingly expected of security tooling.

  • netlens bluetooth --load-external-checks flag enabling community-
    contributed BLE checks from ~/.netlens/checks/*.py. Each module
    exposes a register() -> list[BluetoothCheck]. Loader executes
    arbitrary Python from disk so it is opt-in and prints a 5-second
    consent banner matching the existing --connect-all /
    --probe-writes-all UX. Built-in check names cannot be shadowed;
    import failures, missing register(), and type mismatches log a
    WARNING and are skipped without crashing the scan.

  • Four new entries in companion_apps.yaml covering devices empirically
    observed in the user's environment:

    • LG webOS TV (vendor 0x00C4, name regex [LG] webOS TV...,
      confidence high) — carries real CVE-2023-6317 (RootedWebOS
      auth-bypass on HTTP service ports 3000/3001 enabling RCE; webOS
      4-7 until vendor patch in early 2024). Adds a new tv category.
    • LG DS60Q Soundbar (vendor 0x00C4, model-code name regex,
      confidence medium) — cves: []. Identification surfaces
      remediation guidance on top of the existing curated
      manufacturer-mismatch HIGH-severity check that already fires
      for this device. Adds a new soundbar category.
    • Polar Heart-Rate Sensor / Fitness Tracker (vendor 0x0501 +
      standard HR service 0x180D + Polar name patterns,
      confidence medium) — cves: []. Live HR is cleartext-by-spec,
      so identification + the "power off when not in use" remediation
      are the actionable surface. Matches MOTION_* (Polar Verity
      Sense) plus the broader Polar strap family.
    • Apple AirPods / Beats (name-PII leak) (vendor 0x004C +
      AirPods/Beats name regex, confidence low) — cves: [].
      Personalised device names like "Alice's AirPods Pro" leak owner
      identity to passive BLE listeners; the entry's remediation tells
      the user to rename the device. Mirrors the AirTag/Tile
      "iden...
Read more
Loading

v0.1.1

28 Apr 10:19
@emrecdr emrecdr

Choose a tag to compare

Post-0.1.0 polish release: fixes the Live scan dashboard against
multiple sources of frame tearing (third-party log noise, per-CPE NVD
warnings, render-wrapper clobber), tightens visual hierarchy by merging
two adjacent panels, calms the spinner cadence to a less frantic pulse,
and corrects the privilege-recovery instructions in the HTML report.

Changed

  • Scan dashboard merges "Scan Stages" and "Current Activity" into a
    single "Scan Progress" panel. The two adjacent panels read as one
    region anyway and any tearing of the Live frame visually duplicated
    both — collapsing them halves that surface and tightens the visual
    hierarchy.
  • Scan dashboard active-stage spinner now uses an arc rotation
    (◜◠◝◞◡◟) instead of subtle braille dots, so motion is visibly
    obvious during long-running stages.
  • Spinner cadence calmed from 600 ms full rotation (~1.67 Hz) to
    2.0 s (~0.5 Hz). The faster rate was inherited from a popular
    default but only became observable once the freeze bug below was
    fixed; in motion it read as frantic. 2 s reads as a confident
    pulse — slow enough to be ambient, fast enough to signal liveness.

Fixed

  • Per-CPE NVD lookup failures (almost all of which are 404s — the
    CPE simply has no record in NVD) no longer log at WARNING. They
    now log at DEBUG with a corrected message ("No NVD result" rather
    than "NVD API unreachable"). Per-device WARNINGs were tearing the
    Live dashboard region the same way the SSDP Connection lost
    noise did, and the level was wrong: a missing CPE record is not
    actionable. Real network outages are still discoverable under
    --verbose / DEBUG.
  • HTML report's "ran without root" banner now spells out the full
    recovery command (sudo -E uv run netlens scan) instead of just
    sudo -E. On macOS, sudo without -E resets HOME and PATH,
    causing uv run to resolve a different venv path under /var/root
    and the python process to come back with a non-zero EUID — so the
    banner you were trying to escape just reappeared. -E preserves
    the env so uv run lands on the editable project venv as root.
  • Scan dashboard no longer torn by stray Connection lost log lines
    from third-party libraries. ssdp.aio logs "Connection lost" at
    ERROR level on every M-SEARCH teardown — even successful ones where
    exc=None — and stdlib's logging.lastResort handler routes that
    to stderr outside Rich's Console, fragmenting the Live region.
    The scan command now bumps ssdp, asyncssh, telnetlib3, and
    aiohttp loggers to CRITICAL via a new
    netlens.output.log_policy.silence_noisy_libraries() helper before
    entering the dashboard.
  • Scan dashboard active-stage spinner now actually animates during
    silent stages. The dynamic-render wrapper installed in __enter__
    was being clobbered by Live.update(...) on every event callback,
    leaving auto-refresh ticks repainting a static snapshot — the
    spinner appeared frozen on whatever frame was current at the last
    callback. Switched event-driven repaints to Live.refresh() so the
    wrapper survives and each tick re-evaluates state.
  • Scan dashboard no longer leaves a tall blank gap between the Live
    Counters panel and the post-scan summary; the live region now ends
    at its natural height instead of claiming the full terminal.
  • Post-scan KPI cards (Devices / Critical / High / Medium / Low) now
    pack tightly instead of being spread across the full terminal width
    with large gutters.
Loading

v0.1.0

28 Apr 06:48
@emrecdr emrecdr

Choose a tag to compare

Initial release.

Added

  • Network discovery via ARP, mDNS, SSDP, and DHCP rogue detection.
  • Fingerprinting stage: nmap port/service scans, MAC vendor lookup, SNMP
    probing, banner grabbing, favicon hashing, adaptive nmap chunk sizing.
  • SNMP deep-walk stage with interface/ARP/routing table extraction.
  • Device classification across 12 categories with confidence scoring.
  • Security audit: default credentials (SSH/Telnet/HTTP), CVE lookup via
    NVD, firmware staleness, TLS analysis, admin-panel discovery, UPnP
    control surface, MQTT injection, REST API exposure, DNS rebinding,
    protocol security, dangerous HTTP methods, printer vulnerabilities.
  • Traffic analysis stage: packet capture, DNS extraction, anomaly
    detection.
  • WiFi audit: nearby networks, rogue AP detection, encryption audit.
  • Topology mapping (gateway → switches → devices).
  • Per-device profiles, scan history, and diff between scans (SQLite).
  • Self-contained HTML reports (Jinja2, all CSS inline).
  • Live multi-region scan dashboard with per-stage spinner, elapsed
    clock, and device/finding counters; keeps animating during silent
    stages and shows Traffic Analysis · Ns / Ms against --capture-time.
  • Adaptive device table with priority tiers and inter-row separators
    for wrapped multi-line cells.
  • Theme system (--theme {auto,dark,light}) with semantic tokens.
  • Global CLI flags: --version/-V, --quiet/-q, --no-color,
    --no-progress, --theme.
  • VERSION file as single source of truth for hatchling, runtime
    netlens.__version__, and the CLI flag.
  • Release runbook in docs/RELEASING.md.
Loading

AltStyle によって変換されたページ (->オリジナル) /