Defensive IP-camera security assessment for Termux/Android (rootless) and Linux. Single-file Bash architecture, evidence-first: every finding carries evidence and an explicit verification state — no guessed results, no fake detections.
AUTHORIZED USE ONLY. This tool performs non-destructive verification probes against devices you own or are explicitly permitted to assess. Unauthorized access to devices you do not own is illegal in most jurisdictions. The tool enforces this by design: private-scope targets by default, an interactive authorization gate, and a logged
--allow-publicescape hatch.
- Evidence-weighted fingerprinting — vendor/model/firmware with confidence
scores;
UNKNOWNwhen evidence is insufficient (never guessed). - Vulnerability assessment with 7 verification states —
NOT_CHECKED | NOT_APPLICABLE | NO_EVIDENCE | INCONCLUSIVE | POTENTIALLY_VULNERABLE | LIKELY_VULNERABLE | VERIFIED.VERIFIEDis only emitted on concrete technical evidence (e.g. an XML user list from CVE-2017-7921's unauthenticated endpoint). - RTSP/ONVIF checks — bounded path testing, handshake + authentication-state
detection, timeout-guarded (no hung
ffprobe/ffmpeg, no orphans). - Authentication assessment (opt-in) —
--auth-testonly; capped attempts, lockout delay, stop-on-success; passwords are never printed, logged or exported (SHA-256 ofuser:passonly). - Evidence captures (opt-in) —
--capturessaves RTSP frames with disk-space checks and guaranteed cleanup. - Machine-readable reports — validated JSON + human TXT.
- Safe config — strict
KEY=VALUEparser (nosource), mode0600, env-var override (SHODAN_API_KEY); secrets are redacted from logs. - Leveled logging —
DEBUG/INFO/WARN/ERROR/SECURITYwith rotation. - Scope guard — refuses public targets unless
--allow-public(logged). --self-test— 19 installation/runtime checks.- Shodan lookup — real API queries (optional, key never logged).
Hard: bash >= 4.3, curl.
Recommended: jq, python3, openssl (credential hashing), ffmpeg (RTSP/captures), nmap (LAN discovery accelerator).
Everything missing degrades to an explicit NOT_SUPPORTED — the tool never fabricates capability.
pkg update -y && pkg install -y bash curl jq python3 openssl-tool nmap ffmpegchmod +x cam_scanner.sh
# verify installation (expect: SELF TEST: PASS)
./cam_scanner.sh --self-test
# assess a camera you own
./cam_scanner.sh --target 192.168.1.10
# fast profile, both report formats
./cam_scanner.sh --target 192.168.1.10 --quick --report both
# full assessment incl. RTSP evidence captures
./cam_scanner.sh --target 192.168.1.10 --full --captures
# whole LAN (authorization confirmation required)
./cam_scanner.sh --cidr 192.168.1.0/24
# interactive menuون
./cam_scanner.shReports: ~/.camsec/reports/ · Logs: ~/.camsec/logs/ · Captures: ~/.camsec/captures/
--target IP single IPv4/IPv6 target (private/loopback by default)
--cidr CIDR IPv4 CIDR range (LAN)
--interface NAME network interface for discovery (default: auto-detect)
--quick | --normal | --full scan profile (default: normal)
--timeout SECS per-probe timeout (default: 4)
--ports LIST comma-separated port list
--auth-test enable default-credential check (authorized lab use)
--auth-cred U:P add credential pair (repeatable)
--captures capture RTSP screenshots as evidence
--report txt|json|both
--shodan "QUERY" Shodan host search (key via menu 4 or $SHODAN_API_KEY)
--allow-public permit non-private targets (logged; requires confirmation)
--i-own-targets skip authorization prompt (CI use)
--self-test run the 19-check self test
--deps dependency status report
--version / --help
Exit codes: 0 ok · 1 general · 2 bad args · 3 missing dependency ·
4 target validation/scope failure · 5 scan incomplete.
Constants → Safe config → Logging → UI → Dependency manager → Input validation → Network discovery → Service detection → Fingerprinting → RTSP/ONVIF → Vulnerability assessment → Auth assessment → Evidence collection → Risk engine → Report engine (JSON+TXT) → Cleanup/traps → Self-test → Shodan → CLI parser → Main/menu.
# static + self test
bash -n cam_scanner.sh
shellcheck -S warning cam_scanner.sh # advisory
./cam_scanner.sh --self-test
# integration: full pipeline against a local mock camera (no internet needed)
tests/run_tests.shCI (GitHub Actions) runs the same suite on every push (.github/workflows/ci.yml).
No finding is emitted without WHY_DETECTED / WHAT_WAS_TESTED / WHAT_RESPONSE_WAS_RECEIVED. When evidence is insufficient the result is
INCONCLUSIVE or NO_EVIDENCE — never inflated to look impressive.
MIT — see LICENSE.