SurfaceScope is a no-frills CLI that discovers assets, probes exposure and summarizes cloud risks. It can run in a deterministic demo mode (for screenshots and walkthroughs) or a real mode using your inputs (targets JSON, domain and optional cloud data). Outputs include a plain-text report, a lightweight single-file HTML dashboard and an optional JSON context dump.
- Zero mandatory deps (stdlib only).
- Optional: DNS bruteforce via
dnspythonand live AWS snapshot viaboto3. - Windows-friendly: Ships with
docs/demo_suite.ps1for quick demos.
- Shadow Discovery
- Demo mode: Synthetic but realistic findings (A/CNAME/NXDOMAIN, dangling CNAMEs).
- Real mode: Apex + common subdomains (
www, api, dev, staging, test) viasocket/nslookup. - Optional wordlist bruteforce when
dnspythonis installed (--dns-wordlist).
- Exposure Grading
- Quick port probes for a host list with simple policy-based grade (LOW / MED / HIGH ⚠).
- Fetches minimal HTTP/HTTPS server banners when 80/443 open.
- Supports async probing (
--async-probe) for faster sweeps.
- Cloud Footprint Summary
- Offline JSON summary (
--cloud-json) or live AWS snapshot (--aws-livewithboto3). - Flags public S3 buckets and wide-open SGs (0.0.0.0/0 → 22/3389).
- Counts buckets, instances, IAM roles and shows top flags in HTML.
- Offline JSON summary (
- Artifacts
- Plain text report (
surface-scope-reports/*.txt). - Single-file HTML dashboard (cards + full text).
- JSON with module contexts (machine-readable).
- Plain text report (
- Safety & CI
--no-writedry run (prints output paths but writes nothing).--quietto suppress console output except errors.- Deterministic demo via
--demo-seed.
No installation required for base usage (stdlib only).
Optional extras:
# DNS bruteforce (optional)
pip install dnspython
# Live AWS snapshot (optional)
pip install boto3For
--aws-live, ensure your AWS creds are available (env vars, shared config or an instance profile).
# all-in-one demo scan with HTML + JSON artifacts
python surface_scope.py run --demo -d acme.corp \
--policy paranoid --demo-seed 1337 \
--html-out surface-scope-reports/demo.html \
--json-out surface-scope-reports/demo.json# probe a fixed list of hosts and summarize cloud JSON
python surface_scope.py run \
--targets docs/targets.json \
--cloud-json docs/aws_demo.json \
--timeout 1.5 \
--html-out surface-scope-reports/run.html \
--json-out surface-scope-reports/run.json# basic real discovery (apex + common subdomains) then grade
python surface_scope.py run -d yourcorp.com \
--html-out surface-scope-reports/yourcorp.html
# add bruteforce if dnspython is installed
python surface_scope.py run -d yourcorp.com \
--dns-wordlist wordlists/common.txt --dns-workers 50 \
--html-out surface-scope-reports/yourcorp-brute.html# requires boto3 and valid AWS credentials
python surface_scope.py run --aws-live \
--html-out surface-scope-reports/aws.htmlRun -h for the latest help:
usage: surface-scope [-h] {discover,grade,cloud,run,scan,selftest} ...
SurfaceScope: Attack-surface & exposure mapping
positional arguments:
{discover,grade,cloud,run,scan,selftest}
discover Discover shadow assets via DNS and simple heuristics
grade Probe discovered hosts and compute exposure scores
cloud Summarize offline IaC or AWS JSON assets
run Run all modules and export a combined report
scan Alias of 'run' - execute all modules
selftest Run a minimal self test
options:
-h, --help
usage: surface-scope run [-h] [--domain DOMAIN] [--cloud-json CLOUD_JSON]
[--targets TARGETS] [--ports PORTS] [--timeout TIMEOUT]
[--limit LIMIT] [--out OUT] [--json-out JSON_OUT]
[--policy {minimal,balanced,paranoid}] [--demo]
[--demo-seed DEMO_SEED] [--policy-json POLICY_JSON]
[--html-out HTML_OUT] [--quiet] [--no-write]
[--dns-wordlist DNS_WORDLIST] [--dns-workers DNS_WORKERS]
[--dns-timeout DNS_TIMEOUT] [--aws-live] [--async-probe]
Key arguments:
--domain, -d: Domain for discovery (demo or real).--targets: JSON file of{"host": "..."}objects (used bygrade).--cloud-json: Offline cloud snapshot JSON (S3/EC2/IAM/SGs).--aws-live: Live AWS account snapshot viaboto3(optional dep).--ports: Comma list of ports to probe (default22,80,443,445,3389).--timeout: Per-probe timeout seconds (default1.0).--limit: Discovery cap (default100).--policy: Grading thresholds:minimal | balanced | paranoid.- To override thresholds, use
--policy-json(see below).
- To override thresholds, use
--policy-json: Custom JSON thresholds. Label becomescustom(filename).--demo/--demo-seed: Synthetic, repeatable results for demos.--dns-wordlist/--dns-workers/--dns-timeout: Enable bruteforce (requiresdnspython).--async-probe: Faster port scanning via asyncio.--html-out: Write a single-file HTML dashboard.--json-out: Write machine-readable JSON context.--out: Write the plain-text report. Default path is auto-generated.--quiet: Suppresses all console output except errors.--no-write(dry run): Prints results but does not write files.
Note on custom policies:
--policyonly acceptsminimal|balanced|paranoid. To supply your own thresholds, keep--policy balanced(or any built-in) and add--policy-json docs/policy.json. The report label will showcustom(policy.json).
--domain -d (required)
--limit
--demo
--dns-wordlist (requires dnspython)
--dns-workers
--dns-timeout
--out
--targets (required)
--ports
--timeout
--demo
--async-probe
--out
--cloud-json # offline JSON
--aws-live # live AWS via boto3
--demo
--out
Quick smoke test: python surface_scope.py selftest
Built-in:
minimal:high_any = {22,3389,445},med_num_open = 3balanced:high_any = {22,3389,445},med_num_open = 2paranoid:high_any = {22,3389,445,21,23},med_num_open = 1
A host is HIGH if it exposes any high_any port and also exposes web or multiple services.
Otherwise, MED if open_port_count >= med_num_open. Else LOW.
Custom thresholds file (example docs/policy.json):
{
"high_any": [22, 3389, 445, 21],
"med_num_open": 1
}Use it with:
python surface_scope.py run --demo -d acme.corp \
--policy balanced --policy-json docs/policy.json- Text:
surface-scope-reports/surface-scope-YYYYMMDD-HHMMSS.txt(or--outpath)- Includes discovery, exposure table, banners, cloud summary, “What this means” and a Risk Summary.
- HTML:
--html-out <path>- Single file with four KPI cards (LOW/MED/HIGH/Cloud Flags), Top Flags list and the full text report.
- JSON:
--json-out <path>- Machine-readable module contexts + metadata (e.g.,
probes,flags, effective policy label, etc.).
- Machine-readable module contexts + metadata (e.g.,
On Windows (PowerShell 7+ recommended):
pwsh .\docs\demo_suite.ps1This script:
- Creates demo inputs:
docs/targets.json,docs/aws_demo.json,docs/policy.json - Runs:
- Demo paranoid run (HTML + JSON)
scanalias demo (HTML)- Real run from local inputs (HTML + JSON)
- Quiet mode demo
- Dry run demo (
--no-write)
Each command is checked for non-zero exit codes and the script stops on failure.
- DNS bruteforce: Install
dnspython. Wordlist results are appended to discovery. - AWS live: Install
boto3. The tool useslist_buckets,get_bucket_acl/policy_status,describe_security_groups/instancesandlist_roles. - Banners: HTTP/HTTPS banners are best-effort (raw sockets + TLS handshake).
- Async probes: Use
--async-probefor large target sets.
argument --policy: invalid choice: 'custom'- Use
--policy-jsonwith a valid built-in (--policy balanced --policy-json docs/policy.json).
- Use
- “No files written” when expecting artifacts
- Check you didn’t pass
--no-write. Also ensure you provided--html-out/--json-outif you want those.
- Check you didn’t pass
- AWS errors/missing creds
- Configure credentials via env vars or
~/.aws/*or run inside an environment with an instance profile.
- Configure credentials via env vars or
- Use real-mode responsibly and only against assets you own or are authorized to test.
- The tool does minimal, non-intrusive probing (TCP connect + banner fetch). Increase timeouts carefully to avoid false negatives.