coldpass

TayHCode/homelab-netguard

GitHub ↗ · How this check works

Per-setup public labels: Linux / Haiku: Works

Static status badge · SVG · read-only JSON. Embed with ![Coldpass status](https://coldpass.dev/badge/TayHCode--homelab-netguard.svg).

agent-harness

Works

The recorded run passed on 1 setup.

Answers apply to each recorded setup, revision and operation. Earlier observations remain in Run details.

Tested on Linux
PlatformHaikuLuna
Linuxyesour test failed; no repo verdict

Linux / Haiku 5.5: yes · Oct 27, 2026 · 051d76e68c84 · claude-code / 2.1.310 (Claude Code)
Recorded operation: python3 netguard.py --config <guest-path>

Linux / Luna: our test failed; no repo verdict · Oct 27, 2026 · 051d76e68c84
Recorded operation: No working operation verified.

Does what it says
2 of 2 claims checked out
  • Each run discovers devices on the LAN and checks TCP ports, then writes a plain-English report: Real input produced the expected result: Observed device at <internal-ip>: 22

    Source: Each run discovers devices on your LAN, checks an explicit list of TCP ports,

    Input: config <guest-path> (lan <internal-ip>/24, ports 1-1024 and listed ports, fresh output_dir)

    Expected: report lists the observed device with its open port

    Command: python3 netguard.py --config <guest-path>

    Observed: Observed device at <internal-ip>: 22. Next step: review these ports and the device owner. ## Coverage - Scan observed 1 hosts. Network scan complete; log coverage complete across 1 sources. - Local model triage is unavailable. Next step: check the model service; the findings below still apply. Proposed actions require human review. No actions executed. Phone notifications are disabled.

  • The baseline is never promoted automatically; a fresh run with no approved baseline says so: Real input produced the expected result: No approved network reference exists.

    Source: The baseline is an explicit snapshot and is never promoted automatically.

    Input: config <guest-path> (fresh output_dir, no approve-baseline run)

    Expected: report states no approved network reference exists

    Command: python3 netguard.py --config <guest-path>

    Observed: No approved network reference exists. Next step: review the observed inventory and explicitly approve a reference. - Observed device at <internal-ip>: 22. Next step: review these ports and the device owner. ## Coverage - Scan observed 1 hosts. Network scan complete; log coverage complete across 1 sources. - Local model triage is unavailable. Next step: check the model service; the findings below still apply. Proposed actions require human review. No actions executed. Phone notifications are disabled.

MCP
No
Local or hosted
local
Local: runs on your machine
Needs keys or browser
None seen
Maintained
Maintained
actively maintained: last commit 3 days ago; 2 commits and 0 merged PRs in 90 days; 0 open issues, 0 open PRs; no releases

Last commit Oct 23, 2026

Setup time
12 min 26 s
12 min 26 s to a working result
Issue
none found in recorded check
Examples
1 of 1 ran as expected
  • Run unit tests with python3 -m unittest discover -s tests -v: command completed successfully

    Source: README.md Quick start step 4

    Input: repository tests directory

    Expected: all 37 unit tests pass

    Command: python3 -m unittest discover -s tests -v

    Observed: known_fields_never_appear_in_markdown (test_netguard.PersistenceTests.test_report_unknown_fields_never_appear_in_markdown) ... ok test_config_rejects_scope_and_options (test_netguard.ScopeTests.test_config_rejects_scope_and_options) ... ok test_discovery_excludes_offline_inventory_and_scan_is_bounded (test_netguard.ScopeTests.test_discovery_excludes_offline_inventory_and_scan_is_bounded) ... ok test_xml_diff_and_closed_only_host (test_netguard.ScopeTests.test_xml_diff_and_closed_only_host) ... ok ---------------------------------------------------------------------- Ran 37 tests in 7.248s OK

Cycles
1 of 1 ran as expected
  • A scheduled netguard run executes the scanner with a config every 30 minutes: Triggered one cycle by hand (run-once: manual invocation of the same netguard.service ExecStart command (with a fresh config path) instead of waiting for systemd; normal trigger: systemd timer fires netguard.service 30 minutes after each completed run): # Attention needed Netguard 20261027T121308.934903Z - No approved network reference exists. Next step: review the observed inventory and explicitly approve a reference. - Observed device at <internal-ip>: 22. Next step: review these ports and the device owner. ## Coverage - Scan observed 1 hosts. Network scan complete; log coverage complete across 1 sources. - Local model triage is unavailable. Next step: check the model service; the findings below still apply. Proposed actions require human review. No actions executed. Phone notifications are disabled.

    Source: systemd/netguard.timer

    Input: config <guest-path> (fresh output_dir <guest-path>, no systemd or /opt install)

    Expected: one complete scan cycle writes a report reporting the observed device

    Command: python3 netguard.py --config <guest-path>

    Observed: # Attention needed Netguard 20261027T121308.934903Z - No approved network reference exists. Next step: review the observed inventory and explicitly approve a reference. - Observed device at <internal-ip>: 22. Next step: review these ports and the device owner. ## Coverage - Scan observed 1 hosts. Network scan complete; log coverage complete across 1 sources. - Local model triage is unavailable. Next step: check the model service; the findings below still apply. Proposed actions require human review. No actions executed. Phone notifications are disabled.

Evidence
README behavior checked
Agent interfaces
CLI
CLI

Observed interfaces were exercised by the checker. Documentation alone does not confirm compatibility.

Tested with
Claude Code / Haiku 5.5
  • Linux: Claude Code / Haiku 5.5 · agent 2.1.310 (Claude Code) · Checked operation passed · Oct 27, 2026 on 051d76e68c84

Each entry describes its recorded operation and source revision.

Safety
Earlier check of this revision: Made outbound connections: yes (hosts not recorded) by <guest-path>

Review signals across current setups: connection review.

Repository processes attempted these non-loopback connections; proxies can hide the final hostname. 18157 distinct locations. 43 attributed processes.

Reviewed as expected for a test run: attempted writes that failed, so nothing was written.

Full event, path and process lists for each observed setup:

Run details

Haiku 5.5

Native agent · Checked operation passed

Checked operation python3 netguard.py --config <guest-path>

Agent-reported scope: Run a local network scan with netguard.py, review the report, and approve the baseline; then rescan and confirm no new findings

Run details
run
TayHCode--homelab-netguard-claude-haiku-5-5-1793102422039556559
date
Oct 27, 2026
time to working
745.7s
product hosting / execution
Local command in the guest
recorded operation scope
product operation
model
claude-haiku-5-5
agent / version
claude-code / 2.1.310 (Claude Code)
platform
linux
reported cost
$0.016821
Recorded source
https://github.com/TayHCode/homelab-netguard
Backend
hyperv
Tool transport
mcp-assigned-vm
Requested source pin (not an observed revision)
{"commit": "051d76e68c84a947754d46eb4be0652c6b2167b4", "url": "https://github.com/TayHCode/homelab-netguard"}
Test version
readme-d5b140d3c0f8b95c2dd6fe6fc381a303cacb92679582c22317d8e78b572f0cf2
revision
051d76e68c84a947754d46eb4be0652c6b2167b4
Whose fault: not assigned · resolved

Safety: Review signals: 1 connection review.

Review signals: 1 connection review.

Reviewed as expected for a test run: attempted writes that failed, so nothing was written.

Repository processes attempted these non-loopback connections; proxies can hide the final hostname. 18157 distinct locations. 43 attributed processes.

OSV scanned supported lockfiles; unpinned dependencies and unsupported formats are outside this check.

A short run cannot establish that code is safe.

Connections show IP addresses; proxies can hide the final hostname.

Tracing covers dispatched commands and their children, not the whole OS; guest root can interfere with tracing.

Full safety evidence →

Answers recorded for this run
  • Each run discovers devices on the LAN and checks TCP ports, then writes a plain-English report: Real input produced the expected result: Observed device at <internal-ip>: 22

    Source: Each run discovers devices on your LAN, checks an explicit list of TCP ports,

    Input: config <guest-path> (lan <internal-ip>/24, ports 1-1024 and listed ports, fresh output_dir)

    Expected: report lists the observed device with its open port

    Command: python3 netguard.py --config <guest-path>

    Observed: Observed device at <internal-ip>: 22. Next step: review these ports and the device owner. ## Coverage - Scan observed 1 hosts. Network scan complete; log coverage complete across 1 sources. - Local model triage is unavailable. Next step: check the model service; the findings below still apply. Proposed actions require human review. No actions executed. Phone notifications are disabled.

  • The baseline is never promoted automatically; a fresh run with no approved baseline says so: Real input produced the expected result: No approved network reference exists.

    Source: The baseline is an explicit snapshot and is never promoted automatically.

    Input: config <guest-path> (fresh output_dir, no approve-baseline run)

    Expected: report states no approved network reference exists

    Command: python3 netguard.py --config <guest-path>

    Observed: No approved network reference exists. Next step: review the observed inventory and explicitly approve a reference. - Observed device at <internal-ip>: 22. Next step: review these ports and the device owner. ## Coverage - Scan observed 1 hosts. Network scan complete; log coverage complete across 1 sources. - Local model triage is unavailable. Next step: check the model service; the findings below still apply. Proposed actions require human review. No actions executed. Phone notifications are disabled.

Examples

  • Run unit tests with python3 -m unittest discover -s tests -v: command completed successfully

    Source: README.md Quick start step 4

    Input: repository tests directory

    Expected: all 37 unit tests pass

    Command: python3 -m unittest discover -s tests -v

    Observed: known_fields_never_appear_in_markdown (test_netguard.PersistenceTests.test_report_unknown_fields_never_appear_in_markdown) ... ok test_config_rejects_scope_and_options (test_netguard.ScopeTests.test_config_rejects_scope_and_options) ... ok test_discovery_excludes_offline_inventory_and_scan_is_bounded (test_netguard.ScopeTests.test_discovery_excludes_offline_inventory_and_scan_is_bounded) ... ok test_xml_diff_and_closed_only_host (test_netguard.ScopeTests.test_xml_diff_and_closed_only_host) ... ok ---------------------------------------------------------------------- Ran 37 tests in 7.248s OK

Cycles

  • A scheduled netguard run executes the scanner with a config every 30 minutes: Triggered one cycle by hand (run-once: manual invocation of the same netguard.service ExecStart command (with a fresh config path) instead of waiting for systemd; normal trigger: systemd timer fires netguard.service 30 minutes after each completed run): # Attention needed Netguard 20261027T121308.934903Z - No approved network reference exists. Next step: review the observed inventory and explicitly approve a reference. - Observed device at <internal-ip>: 22. Next step: review these ports and the device owner. ## Coverage - Scan observed 1 hosts. Network scan complete; log coverage complete across 1 sources. - Local model triage is unavailable. Next step: check the model service; the findings below still apply. Proposed actions require human review. No actions executed. Phone notifications are disabled.

    Source: systemd/netguard.timer

    Input: config <guest-path> (fresh output_dir <guest-path>, no systemd or /opt install)

    Expected: one complete scan cycle writes a report reporting the observed device

    Command: python3 netguard.py --config <guest-path>

    Observed: # Attention needed Netguard 20261027T121308.934903Z - No approved network reference exists. Next step: review the observed inventory and explicitly approve a reference. - Observed device at <internal-ip>: 22. Next step: review these ports and the device owner. ## Coverage - Scan observed 1 hosts. Network scan complete; log coverage complete across 1 sources. - Local model triage is unavailable. Next step: check the model service; the findings below still apply. Proposed actions require human review. No actions executed. Phone notifications are disabled.

Local or hosted: local

What the agent did

Run a local network scan with netguard.py, review the report, and approve the baseline; then rescan and confirm no new findings

cd <guest-path> && pwd && ls -la && id -u && python3 --version && ls <guest-path> /inputs 2>&1 | head -20 && git -C . rev-parse HEAD 2>&1 | head -1
cd <guest-path> && cat README.md 2>/dev/null | head -200
cd <guest-path> && which nmap; nmap --version 2>&1 | head -1; cat config.example.json; echo; ls tests .coldpass; cat .gitignore; sudo -n true && echo SUDO_OK
cd <guest-path> && python3 netguard.py --help 2>&1 | head -60
sudo apt-get -o DPkg::Lock::Timeout=300 update -qq 2>&1 | tail -3; sudo apt-get -o DPkg::Lock::Timeout=300 install -y -qq nmap 2>&1 | tail -3; which nmap && nmap --version | head -1
cd <guest-path> && python3 -m unittest discover -s tests -v 2>&1 | tail -15
ip -4 -o addr show | awk '{print $2, $4}'; ip route | head -3; cd <guest-path> && grep -n "def load_config\|output_dir\|lan_cidr\|def main\|argparse\|--config" netguard.py | head -60
cd <guest-path> && sed -n 1,80p verify_live.py
mkdir -p <guest-path> && cd <guest-path> && cat > config.json <<'EOF'
{
  "lan_cidr": "<internal-ip>/20",
  "hosts": {"server": "<internal-ip>"},
  "local_host": "server",
  "dns_hosts": [],
  "optional_hosts": [],
  "ports": "1-1024,3389,5432,6379,8080,8443,11434",
  "output_dir": "<guest-path>",
  "model": "dolphin3:8b",
  "dns_paths": [],
  "auth_paths": ["/var/log/auth.log"],
  "suspicious_domains": []
}
EOF
python3 -I -c 1 2>/dev/null; python3 -m json.tool config.json >/dev/null && echo CONFIG_OK; time timeout 1500 python3 netguard.py --config config.json > <guest-path> 2><guest-path>; echo RC=$?; tail -c 1500 <guest-path>; tail -c 600 <guest-path>
cd <guest-path> && grep -n "nmap" netguard.py | head -30; ls -la <guest-path> 2>&1
cd <guest-path> && sed -i 's#<internal-ip>/20#<internal-ip>/24#; s#netguard-run1#netguard-run2#' config.json && cat config.json && time timeout 1500 python3 netguard.py --config config.json > <guest-path> 2><guest-path>; echo RC=$?; cat <guest-path> | head -60; tail -c 400 <guest-path>
cd <guest-path> && sed -n 696,760p netguard.py
cd <guest-path> && python3 netguard.py --config config.json --approve-baseline > <guest-path> 2>&1; echo RC=$?; cat <guest-path> | head -30
cd <guest-path> && python3 netguard.py --config config.json > <guest-path> 2>&1; echo RC=$?; head -30 <guest-path>
cd <guest-path> && ls systemd && cat systemd/netguard.timer && echo ---- && cat systemd/netguard.service
mkdir -p <guest-path> && cd <guest-path> && for n in probe claim-scan claim-baseline cycle; do cat > $n.json <<EOF
{
  "lan_cidr": "<internal-ip>/24",
  "hosts": {"server": "<internal-ip>"},
  "local_host": "server",
  "dns_hosts": [],
  "optional_hosts": [],
  "ports": "1-1024,3389,5432,6379,8080,8443,11434",
  "output_dir": "<guest-path>",
  "model": "dolphin3:8b",
  "dns_paths": [],
  "auth_paths": ["/var/log/auth.log"],
  "suspicious_domains": []
}
EOF
done; ls -la <guest-path>; python3 -m json.tool <guest-path> > /dev/null && echo OK; ls <guest-path>
mkdir -p <guest-path> && cd <guest-path> && cat > probe.json <<'EOF'
{"kind":"cli","argv":["python3","netguard.py","--config","<guest-path>"],"cwd":"<guest-path>","output_directory":"<guest-path>","expected_returncode":1,"expected_text":"Observed device at <internal-ip>: 22"}
EOF
cat > claims.json <<'EOF'
[
{"kind":"claim","claim":"Each run discovers devices on the LAN and checks TCP ports, then writes a plain-English report","source":"Each run discovers devices on your LAN, checks an explicit list of TCP ports,","input":"config <guest-path> (lan <internal-ip>/24, ports 1-1024 and listed ports, fresh output_dir)","expected":"report lists the observed device with its open port","probe_kind":"cli","argv":["python3","netguard.py","--config","<guest-path>"],"expected_returncode":1,"expected_text":"Observed device at <internal-ip>: 22","output_directory":"<guest-path>","cwd":"<guest-path>"},
{"kind":"claim","claim":"The baseline is never promoted automatically; a fresh run with no approved baseline says so","source":"The baseline is an explicit snapshot and is never promoted automatically.","input":"config <guest-path> (fresh output_dir, no approve-baseline run)","expected":"report states no approved network reference exists","probe_kind":"cli","argv":["python3","netguard.py","--config","<guest-path>"],"expected_returncode":1,"expected_text":"No approved network reference exists.","output_directory":"<guest-path>","cwd":"<guest-path>"}
]
EOF
python3 -m json.tool claims.json >/dev/null && python3 -m json.tool probe.json >/dev/null && echo JSON_OK
cd <guest-path> && cat > cycles.json <<'EOF'
{"detected":true,"checks":[{"claim":"A scheduled netguard run executes the scanner with a config every 30 minutes","source":"systemd/netguard.timer","quote":"OnUnitInactiveSec=30min","schedule":"systemd timer fires netguard.service 30 minutes after each completed run","method":"run-once: manual invocation of the same netguard.service ExecStart command (with a fresh config path) instead of waiting for systemd","input":"config <guest-path> (fresh output_dir <guest-path>, no systemd or /opt install)","expected":"one complete scan cycle writes a report reporting the observed device","kind":"cli","argv":["python3","netguard.py","--config","<guest-path>"],"expected_returncode":1,"expected_text":"Observed device at <internal-ip>: 22","output_directory":"<guest-path>","cwd":"<guest-path>"}]}
EOF
cat > examples.json <<'EOF'
[{"kind":"example","claim":"Run unit tests with python3 -m unittest discover -s tests -v","source":"README.md Quick start step 4","input":"repository tests directory","expected":"all 37 unit tests pass","argv":["python3","-m","unittest","discover","-s","tests","-v"],"cwd":"<guest-path>","expected_text":"Ran 37 tests"}]
EOF
python3 -m json.tool cycles.json >/dev/null && python3 -m json.tool examples.json >/dev/null && echo OK; ls -la
cd <guest-path> && <env-var>=<guest-path> python3 -I <guest-path> --validate --replay 2>&1 | tail -c 4000; echo RC=${PIPESTATUS[0]}
cd <guest-path> && <env-var>=<guest-path> python3 -I <guest-path> --validate --replay > <guest-path> 2><guest-path>; echo RC=$?; python3 -I -c 'import json,sys;d=json.load(open("<guest-path>"));print({k:v for k,v in d.items() if k not in ("replay",)} if isinstance(d,dict) else d)' 2>&1 | head -c 2500; echo; head -c 600 <guest-path>
cd <guest-path> && cat > report.json <<'EOF'
{"outcome":"working","fault_owner":null,"operation":"Run a local network scan with netguard.py, review the report, and approve the baseline; then rescan and confirm no new findings","operation_scope":"Single host on a /24 LAN (<internal-ip>/24), discovery plus TCP port check of 1-1024,3389,5432,6379,8080,8443,11434, Python 3.12.3 standard library, nmap 7.94. Local model triage (Ollama), DNS/AdGuard, ntfy notifications, and systemd installation were not set up (optional in the README).","steps":["sudo apt-get -o DPkg::Lock::Timeout=300 install -y nmap","python3 -m unittest discover -s tests -v","Copy config.example.json to config.json and edit it (lan_cidr <internal-ip>/24, hosts server=<internal-ip>, local_host server, empty dns_hosts/optional_hosts, output_dir absolute)","python3 netguard.py --config config.json","python3 netguard.py --config config.json --approve-baseline","python3 netguard.py --config config.json"],"deviations":["nmap was not installed in the guest; installed with sudo apt-get -o DPkg::Lock::Timeout=300 install -y nmap (nmap 7.94SVN).","First scan used lan_cidr <internal-ip>/20 (guest address <internal-ip> in /20). Discovery reported 'Local network discovery failed' with 0 hosts because the nmap -sn sweep of 4094 addresses hit the 90-second limit in netguard.py. Narrowed lan_cidr to <internal-ip>/24 and reran; discovery then completed.","config.example.json hosts (192.168.1.x) and /var/lib/netguard output_dir were replaced with the guest's own address and a /tmp output directory, since the README's Quick start does not require the example addresses.","Probes, claims and cycle runs use separate fresh configs in <guest-path> with fresh output_dirs under <guest-path> so replay does not reuse the approved baseline.","Cycle: the systemd timer (netguard.service every 30 min) was not installed; one cycle was triggered by hand using the same ExecStart command with a fresh config.","Local model triage was unavailable (Ollama not installed), so reports say so; the README states findings still apply.","Notifications disabled (no ntfy topic). DNS checks not exercised (no dns_hosts).","verify_live.py (README Live verification) was not run; it would listen on TCP 47653 and needs extra setup."],"stuck_step":null,"main_blocker":null,"plain_failure":null,"suggested_fix":"None required for the documented operation. For full coverage: install Ollama with the model dolphin3:8b, configure ntfy and DNS hosts if wanted, and widen lan_cidr only with enough nmap time (the /20 sweep exceeds the 90-second discovery limit in netguard.py)."}
EOF
python3 -m json.tool report.json >/dev/null && echo REPORT_OK; ls -la <guest-path>

No product verdict. Run record.