EASM + Baseline Comparison + Evidence-First
Know your attack surface. Track what changes.
CASM continuously maps your external attack surface and tracks what changed - turning security scanning into security intelligence.
CASM is an attack surface tracking and analysis system that:
- π Discovers - Maps your external attack surface (HTTP, DNS, TLS)
- β Verifies - Checks security configurations and headers
- π Tracks - Baseline comparison shows exactly what changed
- π Reports - Evidence-ready compliance reporting (SARIF, Markdown, PDF)
Unlike traditional scanners that give you snapshots, CASM tracks changes over time - answering the critical question: "What's different from last week?"
- Authorization-first. Operates only within explicit scope and rate limits.
- Safe verification by default. No destructive actions, no payloads, no brute force.
- Evidence-first. Findings are backed by raw, redacted evidence.
- Modular architecture. Brain (Python) orchestrates, Hands (Go) execute.
Current focus: EASM-style discovery + safe verification + evidence-first reporting.
- SARIF output for CI integration
- Evidence JSONL for automation
- A dual-audience Markdown report (executive + technical) for
casm run. - PDF reports with a "Changes Since Last Scan" section when a baseline exists.
CASM is designed for authorized testing only and enforces:
- Default dry-run mode
- Scope guard allowlists (domains, IPs, ports, protocols)
- Deterministic blocking with reason codes
- Rate limiting and concurrency caps
brain/: Python orchestration + policy enforcement
core/: Domain logic (scope, policy, findings, reporting)ports/: Interfaces (tool gateway, evidence store, publisher)adapters/: Implementations (tool runners)cli/:casmCLI entrypointtests/: Offline-first unit tests
hands/: Go tools for safe verification
cmd/probe/: TCP connect checkscmd/http_verify/: HTTP metadata and header checkscmd/dns_enum/: DNS enumeration (passive + active)pkg/: Shared code
contracts/: JSON schemas + fixtures
schemas/: Tool request/response schemasfixtures/: Deterministic fixtures for tests
runs/: Evidence + reports output
- Python 3.11+ recommended
- Go 1.21+
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt -r requirements-dev.txt
python -m pip install -e .
Build the Go tools:
make build-hands
Run DNS enumeration:
casm run dns-enum --config scopes/scope.yaml --domain example.com
Run tests:
make test
Run http_verify via CLI:
casm run http-verify --scope scopes/scope.yaml --dry-run=false
Note: casm run http-verify writes evidence.jsonl, results.sarif, and targets.jsonl in runs/<engagement>/<run>/ but does not generate a report yet.
Unified pipeline:
casm run unified --config scopes/scope.yaml --sarif-mode local
Unified pipeline with imported targets (skips probe):
casm run unified --config scopes/scope.yaml --targets-file targets/target02-harness.json --sarif-mode local
Detailed unified report (includes per-endpoint findings):
casm run unified --config scopes/scope.yaml --targets-file targets/target02-harness.json --sarif-mode local --detailed
Diff two runs (SARIF):
casm diff --old runs/<engagement>/<run_id>/results.sarif --new runs/<engagement>/<run_id>/results.sarif
Include unchanged findings in the diff report:
casm diff --old runs/<engagement>/<run_id>/results.sarif --new runs/<engagement>/<run_id>/results.sarif --include-unchanged
Targets file format (JSON harness):
{
"targets": [
{ "url": "https://127.0.0.1:8443/health", "method": "HEAD" },
{ "url": "https://localhost:8444/headers/none" }
]
}
Outputs are written to runs/<engagement>/<run_id>/ by default and include targets.jsonl, evidence.jsonl, results.sarif, and report.md.
Evidence viewer:
casm evidence --path runs/<engagement>/<run_id>/evidence.jsonl --type http_response --tool http_verify --limit 20
Whole-line search (default contains scope):
casm evidence --path runs/<engagement>/<run_id>/evidence.jsonl --contains localhost:8444
Field-limited search (error scope only):
casm evidence --path runs/<engagement>/<run_id>/evidence.jsonl --contains "tls:" --contains-scope error
Show only today's http errors:
casm evidence --path runs/<engagement>/<run_id>/evidence.jsonl --type http_error --since 2026-02-01T00:00:00Z
Show a narrow window around an incident:
casm evidence --path runs/<engagement>/<run_id>/evidence.jsonl --since 2026-02-01T17:34:00Z --until 2026-02-01T17:36:00Z
Timestamps follow RFC3339; if no timezone is provided, UTC is assumed.
# Install from PyPI
pip install g2cv-casm
# Or install from source checkout
pip install -e .
# Scan your infrastructure
casm run unified --config scopes/scope.yaml --targets-file targets/target-harness.example.json
# Compare to previous run
casm diff --old runs/baseline/results.sarif --new runs/current/results.sarifEvidence is written as JSONL (one JSON object per line). Key fields include:
engagement_id,run_idtool_name,tool_versiontype(e.g.,tcp_connect,run_result)target(e.g.,example.com:443)timestamp(UTC)status(success|timeout|error|blocked)duration_msdata(structured, redacted)data.canonical_url(stable, normalized URL for comparisons)data.finding_fingerprints(stable identifiers for findings tied to the event)schema_version(semantic version for evidence schema)- SARIF
properties.severityis set per rule, and SARIFlevelmaps to that severity - SARIF includes
properties.schema_versionat the top level and per run
A centralized redaction step is applied to evidence data and persisted tool logs to scrub obvious secrets.
- The Markdown report is dual-audience:
- Executive Summary (metrics + top recommendation)
- Technical Summary, Scope & Method, Limitations, Assets Observed, Findings, Telemetry
- Findings are grounded in evidence IDs for traceability.
- SARIF 2.1.0 export includes normalized findings only (not telemetry-only events).
Migration:
casm migrate --input runs/<engagement>/<run_id> --out runs/<engagement>/<run_id>-migrated
Environment defaults are documented in .env.example.
Key scope fields (see scopes/scope.yaml):
seed_targets: initial hostnamesallowed_domains,allowed_ipsallowed_ports,allowed_protocolsmax_rate,max_concurrencyper_attempt_timeout_ms,tool_timeout_msactive_allowed,auth_allowed
For development workflow, see CONTRIBUTING.md.
Release versioning is tag-driven (vMAJOR.MINOR.PATCH).
CASM is licensed under the GNU Affero General Public License Version 3 (AGPLv3).
This means:
- β Free to use and modify
- β Free for internal use
- β Must share modifications if you run CASM as a network service
- β Commercial licenses available for proprietary use
For commercial licensing inquiries: contact@g2cv.com
Copyright (C) 2026 G2CV Solutions