Skip to content

Repository files navigation

BluePy — infrastructure security scanner (alpha)

A CLI-first infrastructure security scanner that runs KISA-based hardening checks over SSH and reports PASS / FAIL / MANUAL per rule.

Python License Status


⚠️ Honest-alpha status (read this first)

BluePy is an early alpha. It ships only the checks whose logic has been causally verified with branch-covered tests against real command output. Everything else from the legacy KISA rule corpus is treated as experimental and is excluded from the default scan because its YAML→validator mappings are unreliable (some legacy validators returned unconditional PASS or could never PASS). Shipping those as a "133-rule scanner" would give a false sense of safety, so we don't.

What this means concretely:

  • Default scan = verified checks only (a small set, see the table below).
  • Unverified checks carry experimental: true in their rule YAML and only run with --include-experimental (clearly labelled, not trusted).
  • The known false-PASS validators (check_u02, check_u06, check_w03) were deleted, not hidden.
  • Windows transport (WinRM) exists in the codebase but is release-hidden for v0.1 (no verified Windows checks; no Windows live-test fixture yet).

Scope

Track Transport v0.1 status
Linux SSH (asyncssh) active — verified subset exposed
macOS SSH (asyncssh) active — verified subset exposed
Windows WinRM (pywinrm) engine present, release-hidden / deferred

Verified check set (exposed by default)

"Verified" means the validator has PASS + FAIL + MANUAL branch-covered causal tests with anchored matchers, exercised against real command output.

Rule Check Command Proof level
U-18 /etc/passwd owner/permission ls -l /etc/passwd Linux live e2e (Docker fixture, real SSH)
U-19 /etc/shadow owner/permission ls -l /etc/shadow Linux live e2e (Docker fixture, real SSH)
M-01 System Integrity Protection (SIP) csrutil status macOS validator causal tests + 1 local capture
M-02 FileVault full-disk encryption fdesetup status macOS validator causal tests + 1 local capture
M-05 Automatic updates defaults read … AutomaticCheckEnabled macOS validator causal tests

Proof levels differ by track and we state that honestly: the Linux verified checks are proven by a live end-to-end scan (real SSH against a Docker fixture); the macOS checks are proven by branch-covered validator causal tests plus a one-time real local command capture, with live SSH confirmation performed manually (CI runners have no macOS+Remote Login target).

Everything not in this table is experimental and hidden unless you pass --include-experimental.


Install

BluePy uses uv and is pinned to Python 3.12 (.python-version). The default install pulls only the minimal scan-path dependencies (pydantic, pyyaml, asyncssh).

# 1) install uv (if needed)
curl -LsSf https://astral.sh/uv/install.sh | sh    # or: pip install uv

# 2) install Python 3.12 + minimal scan-path deps
uv sync

Run from the repository root with uv run — the validators do import src.* and the rules path is relative (config/rules), so the scanner runs in-place. There is no installable wheel or standalone binary in v0.1.

Quick start

# scan a remote Linux server (verified checks only), human-readable table
uv run python -m src.cli.commands scan --host <HOST> --user <USER> --password <PW> --platform linux

# machine-readable counts
uv run python -m src.cli.commands scan --host <HOST> --user <USER> --password <PW> --platform linux --json

# include unverified (experimental) checks too
uv run python -m src.cli.commands scan --host <HOST> --user <USER> --key <KEYFILE> --include-experimental

CLI reference

bluepy scan --host HOST --user USER (--password PW | --key KEYFILE)
            [--port N] [--rules-dir config/rules]
            [--platform linux|macos|windows] [--server-id ID]
            [--format table|plain] [--json]
            [--include-experimental] [--insecure]
  • Authentication: pass exactly one of --password / --key (key wins if both).
  • --platform: linux/macos use SSH; windows uses WinRM (uv sync --extra windows).
  • --format table (default) prints a per-rule table; --format plain prints a one-line summary. --json always emits the frozen counts payload below.
  • --include-experimental: also run unverified checks (default: verified-only).
  • --insecure: disable SSH host-key verification (MITM risk; see Security).

--json output schema (frozen, 7 keys)

{"server_id":"...","platform":"linux","total":2,"passed":1,"failed":1,"manual":0,"score":50.0}

The security posture (how many checks FAILED) lives in the JSON counts, never in the exit code.

Exit codes

Code Meaning
0 scan completed
2 connection failure
3 rules load failure
4 usage / argument / auth error
1 unexpected runtime error

Optional dependency extras

The default install is the minimal scan path. Everything else is optional:

uv sync --extra gui       # PySide6 GUI (deferred / unsupported in v0.1)
uv sync --extra report    # openpyxl / reportlab / jinja2
uv sync --extra db        # sqlalchemy / alembic
uv sync --extra windows   # pywinrm (Windows targets)
uv sync --extra full      # everything

Security

BluePy is a security tool, so it must not undermine its own transport:

  • SSH host-key verification is strict by default. A first connection to an unknown host fails unless its key is in your known_hosts.
  • --insecure disables host-key verification for that run and prints a warning. Use it only for throwaway lab targets; it exposes you to MITM. It is not used by the live test harness (the harness seeds the fixture host key and connects on the strict path).

To report a vulnerability, see SECURITY.md.

Verification

# unit + integration tests (Docker-free)
uv run pytest tests/unit tests/integration

# Docker-free causal/logic tests for the acceptance harness + verified set
uv run pytest tests/acceptance/test_acceptance_logic.py

# live end-to-end acceptance (real SSH against a committed Docker fixture)
uv run python tests/acceptance/run_acceptance.py

The live harness in tests/acceptance/run_acceptance.py brings up a committed fixture (seeded so /etc/shadow is 400 → U-19 PASS and /etc/passwd is 644 → U-18 FAIL), then proves a real config-driven scan and binds the CLI --json counts to the in-process result. It needs a Docker daemon: locally on Apple Silicon use colima (brew install colima docker docker-compose && colima start); in CI the native Docker on the Linux runner is used (the harness is runner-agnostic — colima is only the local path).

Provenance

Rule definitions derive from the KISA infrastructure security guide (https://www.kisa.or.kr), cross-referenced with the CIS Benchmarks. The legacy 2017 rule corpus was migrated mechanically and many mappings are unreliable; v0.1 only vouches for the verified set above and exposes the rest as experimental.

Deferred (not in v0.1)

  • Windows track exposure (engine present, release-hidden).
  • TUI front-end (planned v0.2).
  • PySide6 GUI.
  • Remediation / auto-fix exposure (engine present, not exposed).
  • Full repair of the scrambled legacy KISA mappings.

Contributing

See CONTRIBUTING.md — including how a check graduates from experimental to the verified set (branch-covered causal tests + anchored matchers).

License

MIT.

About

No description, website, or topics provided.

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages