78 Commits
Author SHA1 Message Date
jokob-sk 32eeb327c2 NMAPDEV defalts fix #1852 2026-10-23 12:48:16 +11:00
Jokob @NetAlertX 8fe3b49507 Merge pull request #1860 from netalertx/main
sync
2026-10-23 10:24:47 +09:00
Mauricio CamayoandClaude Opus 5.5 ca4e92c32d Sync + WIFICANARY: attribute synced detections to their node
Fixes found running WIFICANARY on a WiFi satellite node that pushes its
detections to a hub with no WiFi of its own.

Synced plugin objects were stored with syncHubNodeName = "decoded"
instead of the node's name. plugin.py took filename.split(".")[2], but by
the time the hub processes the file decode_and_rename_files() has renamed
it to last_result.<PREFIX>.decoded.<NodeName>.<N>.log, so index 2 is the
literal marker. The parsing now lives in
utils.plugin_utils.get_sync_hub_node_name(), next to the function that
produces these names; it keeps node names that contain dots and returns
"" for local result files.

WIFICANARY's absent_baseline_clone was evaluated per trusted_aps entry,
so with a main AP + range extender pair, a weak clone seen while only the
main AP was in range also raised absent_baseline_clone through the
extender's entry, on top of the correct evil_twin. The baseline now
counts as present if any trusted radio for that SSID is visible;
single-entry behaviour is unchanged.

Leaving WIFICANARY_IFACE blank is how such a hub ingests the node's
detections (core processes the synced files after the plugin runs), but
it logged an unconditional "not set - nothing to scan" every cycle. It is
now a verbose "hub-only mode" message, and the node + hub setup is
documented in the setting description and the plugin README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PzCQWQVz9b2UzqLiGp2mPM
2026-10-22 12:09:53 -05:00
jokob-sk e8c214dda9 PLG: INTERNET plugin fix #1845 2026-10-18 10:25:23 +11:00
jokob-sk 02557f0db5 PLG: INTERNET plugin fix #1845 2026-10-18 10:01:18 +11:00
Alexander Shevchenko 94164829ff docs(unifi): describe import and test helper functions 2026-10-06 11:38:38 +02:00
Alexander Shevchenko 6b76b8c8ea fix(unifi): import wireless SSIDs into device scans
Read essid instead of the UniFi network name, exclude wired clients, and map the plugin result to scanSSID. Label the imported value as SSID.
2026-10-06 10:36:25 +02:00
jokob-sk 067a6a15ef FE+BE: review fixes #1828 #1826 2026-10-02 23:05:02 +10:00
jokob-sk af79016ac8 PLG: FREEBOX presence L3 fix #1828 2026-10-02 22:44:11 +10:00
jokob-sk 0d60071d49 BE+FE: System info -> Performance section 2026-09-28 21:32:16 +10:00
jokob-sk 4aa2a0dddb BE+FE: System info -> Performance section 2026-09-28 14:40:11 +10:00
jokob-sk c5081ba4c1 PLG: MQTT sanitization of input #1816 2026-09-28 07:38:33 +10:00
jokob-sk 6d5760405b PLG: MQTT refactor 2026-09-28 07:03:55 +10:00
jokob-sk 81b28cb15e PLG: MQTT add devVLan devSSID #1816 2026-09-27 09:25:58 +10:00
jokob-sk 2cb637485d FE+LANG: Add Alert Events, Can Sleep and Static IP as selectable Device columns #1815 2026-09-27 08:54:00 +10:00
jokob-sk 6d7517eb8a DOCS+PLG: skill updates, PIHOLEMON corrected source 2026-09-26 10:06:37 +10:00
jokob-sk 127e2c92ee DOCS+PLG: skill updates, ADGUARDIMP more accurate presence determination #1813 2026-09-26 09:41:20 +10:00
jokob-sk 28eced2a25 DOCS: skill updates, WIFICANARY updates 2026-09-26 08:58:46 +10:00
jokob-sk 591b1fadbe Merge branch 'next_release' of github.com:netalertx/NetAlertX into next_release 2026-09-26 07:49:26 +10:00
jokob-sk c04213eb23 PLG: FREEBOX and FRITZBOX didn't respect SET_ALWAYS due to non-matching plugin name in config #1812 2026-09-26 07:49:11 +10:00
Jokob @NetAlertX d838376e9e Merge pull request #1809 from mauricio-camayo/add-wificanary-plugin
Add WIFICANARY plugin - passive WiFi rogue-AP detection
2026-09-25 14:19:37 +10:00
Mauricio CamayoandClaude Sonnet 5 41efcbc971 Address jokob-sk review: dedupe rogue detections, add iw to remaining Dockerfiles
check_trusted_aps() evaluated a rogue AP once per trusted_aps entry sharing
its SSID, so the documented main-AP+extender pattern (same SSID, two
entries) produced duplicate (bssid, motor) rows for a real clone - a
problem once next_release's per-plugin identity-hash dedup guard lands in
main, since it drops a plugin's entire batch on any internal duplicate.
Fixed by deduping once in main() after collecting from all check_*
functions. Also added iw + its setcap to Dockerfile.debian and
.devcontainer/Dockerfile, which the original PR missed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011meLPKCzVpdZyAUfv5U6mm
2026-09-24 20:10:12 -05:00
Mauricio CamayoandClaude Sonnet 5 f7a0c5861e Address CodeRabbit review: extender false-positive + stale README section
- check_trusted_aps() was evaluating every AP sharing a protected SSID
  against every trusted entry for that SSID, not just its own. A main AP
  requiring a stricter accepted security set (e.g. wpa3-only) than a
  separately-trusted extender (e.g. wpa2) caused the extender to be
  flagged as evil_twin/absent_baseline_clone - it was being judged
  against the main AP's accepted set instead of its own. Fixed by
  excluding, from each trusted entry's evaluation, any BSSID that has its
  own separate trusted entry for the same SSID.
- README's "iw isn't in the published image yet" section was already
  stale within the same PR - this branch's own Dockerfile change adds
  iw + setcap, so the image ships it. Replaced with one sentence.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 15:01:16 -05:00
Jokob @NetAlertX 11e1227d7d Merge pull request #1808 from netalertx/main
sync
2026-09-24 10:43:22 +10:00
jokob-sk 6cc092f2ad BE: plugin input improvements 2026-09-24 10:01:52 +10:00
Jokob @NetAlertX 88cf790263 Merge pull request #1805 from netalertx/next_release
Next release
2026-09-24 07:50:23 +10:00
Mauricio CamayoandClaude Sonnet 5 d0a3a5416b Add WIFICANARY plugin - passive WiFi rogue-AP detection
Periodic iw-scan-based detection of the 6 heuristics that don't need
monitor-mode hardware (see issue #1789): pwnagotchi/Pineapple signatures,
evil-twin/open clones, baseline-AP-absent-with-clone, security downgrades,
and duplicate-SSID/different-vendor - all evaluated against a user-curated
trusted-AP baseline (WIFICANARY_trusted_aps). A detection creates a
flagged Devices entry even for BSSIDs that never associate, per the
addendum on the same issue.

- WIFICANARY_TRUSTED_SECURITY is multi-select: an observed encryption
  exactly matching any selected value is accepted; otherwise it's flagged
  if weaker than the strongest selected value (deliberate - comparing
  against the weakest would make multi-select pointless, since anything
  at/above the weakest would silently pass regardless of the rest of the
  selection).
- Added a "known device turned rogue" motor: escalate_known_devices()
  cross-references each detection's BSSID against the Devices table via
  the new DeviceInstance.getAllByMacs(). This covers the BSSID-identity
  half of the issue #1789 addendum's motor 10; the deauth/probe-source-MAC
  half still needs monitor-mode data this plugin doesn't have.
- Vendor is deliberately not looked up by this plugin - any device it
  creates gets devVendor filled in for free by core's own vendor_update
  plugin on its next pass.

43 wificanary unit tests + 10 DeviceInstance.getAllByMacs() tests, all
test_plugin_conventions.py checks pass.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011meLPKCzVpdZyAUfv5U6mm
2026-09-23 15:56:47 -05:00
jokob-sk 7aca7c17f3 BE: FREEBOX dual stack IP fix #1804 2026-09-23 08:17:23 +10:00
jokob-sk 24301cbdbc BE: FREEBOX dual stack IP fix #1804 2026-09-23 07:52:30 +10:00
jokob-sk 38866a64db BE: FREEBOX last scan fix #1804 2026-09-22 08:25:53 +10:00
Mauricio CamayoandClaude Sonnet 5 b175a3b65f Address jokob-sk review: shorten UI description, map scanSourcePlugin
Settings-UI description trimmed to one short line - implementation
detail (Socket Proxy, column mapping, CREATE_DEV behavior) already
lives in README, doesn't belong in the Settings page string.

scanSourcePlugin now maps to a static "DOCKERDISC" value (same
Dummy-column pattern arp_scan already uses), so a container device
created by this plugin gets devSourcePlugin set correctly instead of
NULL - every other CurrentScan-mapped plugin already does this.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011meLPKCzVpdZyAUfv5U6mm
2026-09-20 16:22:12 -05:00
Mauricio CamayoandClaude Sonnet 5 dea6a553fb Address CodeRabbit review: add DOCKERDISC_IMPORT_ON, docstrings
Declares DOCKERDISC_IMPORT_ON (default on) so an operator can fully opt
this plugin out of CurrentScan promotion. Needed because
DOCKERDISC_CREATE_DEV alone doesn't cover it: a macvlan/ipvlan
container's row always carries a real scanMac, so even with
CREATE_DEV off, an already-existing device for that MAC (found
independently by ARP/Nmap) still gets its presence/devLastIP/
devParentMAC updated by this plugin on every run - only IMPORT_ON can
turn that off. The two settings are independent, per jokob-sk's PR
feedback - IMPORT_ON gates promotion for the whole run, CREATE_DEV
gates device creation per row.

Also adds missing docstrings to process_host()/main() (CodeRabbit
docstring-coverage check), matching the style already used elsewhere
in this file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011meLPKCzVpdZyAUfv5U6mm
2026-09-18 20:05:37 -05:00
Mauricio CamayoandClaude Sonnet 5 cfde00048a DOCKERDISC v2: optional device creation for LAN-visible containers
Maps DOCKERDISC to CurrentScan (scanMac/scanCreatesDevice/scanParentMAC/
scanLastIP) so a container on a macvlan/ipvlan network can opt into
creating or confirming its own device, parented to its Docker host.
Gated by a new DOCKERDISC_CREATE_DEV setting (default off). A container
without its own MAC (bridge/overlay/etc.) never creates a device either
way - the framework's blank-scanMac guard blocks the whole group
regardless of the setting.

Reuses the existing objectPrimaryId/extra column definitions (already
host MAC / container IP) to also feed scanParentMAC/scanLastIP, so every
promoted container is auto-parented to its host with no extra plugin
logic. Two new hidden columns (helpVal1/helpVal2) carry the per-container
scanMac/scanCreatesDevice values.

Tests: 33 -> 35, both DOCKERDISC_CREATE_DEV on/off paths asserted.
Live-verified end to end against a real built image (docker-socket-proxy
+ isolated macvlan/bridge test containers), since IMPORT_ON isn't in any
released NetAlertX image yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011meLPKCzVpdZyAUfv5U6mm
2026-09-18 17:14:10 -05:00
Mauricio CamayoandClaude Sonnet 5 091e648e88 Fix DOCKERDISC_HOST_MAC docs and strengthen case-insensitivity test
resolve_host_mac() returns the manually configured MAC immediately,
with no Socket Proxy /info call at all - the config.json text still
described it as a fallback used only when auto-detection fails.
Reworded both the setting's own description and the parent "Docker
hosts" description to match actual behavior.

The case-insensitivity regression test for lookup_device_mac() stubbed
DeviceInstance.getByMac() to return a fixed row regardless of input,
so it passed even without exercising real collation - functionally a
duplicate of test_lookup_device_mac_found. Replaced it with a
delegation check, and added real SQLite-backed coverage for
DeviceInstance.getByMac()'s case-insensitivity in
test/backend/test_device_instance.py. That surfaced a gap in the
shared db_test_helpers.py fixture: its Devices.devMac column was
missing the COLLATE NOCASE that the real schema declares, so it could
not have exercised this behavior. Fixed the fixture to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011meLPKCzVpdZyAUfv5U6mm
2026-09-15 12:57:04 -05:00
Mauricio Camayo b0d1776221 Trim module docstring: drop design-history attribution and verification date
Per jokob-sk's review - unnecessary details belongs in the PR/commit
history, not the docstring (matches CLAUDE.md's own convention: a
docstring describes current behavior, not a changelog of why).
2026-09-15 12:06:04 -05:00
Mauricio Camayo 3b83d2403b Address jokob-sk review: DeviceInstance instead of raw SQL, drop HTML entity/partial translations/dead spec-file reference
- resolve_host_mac()/lookup_device_mac() now use the new
  DeviceInstance.getAllByName()/getByMac() core methods instead of
  querying Devices directly - no more direct SQL access from the plugin.
- config.json: removed the &rarr; HTML entity from a description (plain
  ASCII ->, matching e.g. pihole_monitor's convention), and dropped the
  partial es_es/de_de translations scattered through settings/columns
  (English only now, matching e.g. rest_import) instead of leaving some
  strings translated and others not.
- script.py: removed the two remaining references to
  PLUGIN_DOCKERDISC_SPEC.md, a file that was never included in this PR.
2026-09-15 11:58:10 -05:00
Mauricio Camayo 6a26804a5e Address CodeRabbit review: request timeout budget, shape validation, ambiguous devName, README fix
- DockerHost now takes a shared run deadline instead of a per-request
  timeout duration - every _get() call is capped by whatever's left of
  that budget (and REQUEST_TIMEOUT_DEFAULT as an upper bound), so one
  slow/hanging host can't burn the whole RUN_TIMEOUT and starve every
  other configured host. config.json's hosts param now also sets
  timeoutMultiplier, scaling the outer kill-timeout by host count.
- _get() validates the parsed response's shape (dict for /info, list for
  /containers/json and /networks) before returning it, rejecting a
  malformed/unexpected payload the same as a network failure instead of
  letting a caller crash on it further down.
- resolve_host_mac()'s hostname match now detects more than one device
  sharing that name and treats it as ambiguous (falls back to manual),
  instead of silently picking an arbitrary one via LIMIT 1.
- README: the Socket Proxy is only reachable at 127.0.0.1:2375 under the
  network_mode: host case described above it, not under normal compose
  networking - fixed the doc to not imply either URL works there.
2026-09-14 10:01:40 -05:00
Mauricio Camayo 94a5cd4968 Add DOCKERDISC plugin: enrich existing devices with their Docker containers
Read-only enrichment plugin, not an import/discovery plugin. For each
configured Docker host (via Docker Socket Proxy, never /var/run/docker.sock
directly), lists that host's containers under the host device's own
Device Details -> Plugins -> DOCKERDISC tab.

- Never creates a device, for either a host or a container - matches
  against hosts already discovered the normal way (ARP/Nmap).
- Every container is listed (bridge/overlay included), not only
  macvlan/ipvlan ones - a container only gets its own MAC/IP shown when
  it has a macvlan/ipvlan network.
- Host MAC auto-detected via the Socket Proxy's /info -> Devices.devName
  match, with a manual fallback.
2026-09-14 09:11:34 -05:00
jokob-sk f7fef5d196 FE+BE: plugins config fixes #1784 2026-09-14 08:49:15 +10:00
jokob-sk dd4fc057c8 BE: SQL refactor presence 2026-09-10 22:11:46 +10:00
jokob-sk d9947a2829 BE: conditional device import support, notification supression support during scan #1721 2026-09-10 21:00:50 +10:00
jokob-sk de730e85e9 BE: conditional device import support, notification supression support during scan #1721 2026-09-10 18:41:07 +10:00
jokob-sk c6164798e9 DOCS: plugins 2026-09-10 09:49:40 +10:00
jokob-sk b5d62b73c9 FE: Easier icon add in Settings #1773 2026-09-09 08:08:31 +10:00
jokob-sk ba0077b99d DOCS: plugins 2026-09-07 09:44:37 +10:00
jokob-sk 85325dad93 DOCS: plugins 2026-09-07 09:30:55 +10:00
jokob-sk 18092b3179 DOCS: plugins 2026-09-07 08:24:53 +10:00
jokob-sk d478deddc9 FE+DOCS: custom props icon select fix + docs cleanup 2026-09-06 11:13:21 +10:00
jokob-sk 939e6494ba BE+PLG: mac case sensitivity causing double detection #1775 2026-09-04 08:18:02 +10:00
jokob-sk 4be05c958a BE+PLG: mac case sensitivity causing double detection #1775 2026-09-04 08:08:22 +10:00