Skip to main content

Presidio security-hardened distribution of ScoutSuite — runs the multi-cloud auditor out of process with hardened defaults, report redaction, and a least-privilege deployment model.

Project description

presidio-hardened-scoutsuite

CI CodeQL License: MIT Python 3.9+

A Presidio security-hardened distribution of ScoutSuite, NCC Group's multi-cloud security auditing tool.

Wrapper, not a fork. ScoutSuite is GPL-2.0. Rather than fork or import it, this project drives the upstream scout CLI out of process and wraps it with hardened defaults, report redaction, supply-chain integrity, and a least-privilege deployment model. That keeps the wrapper a separate, non-derivative work — so this code is MIT — while you still run stock, trusted-upstream ScoutSuite underneath. See LICENSES/README.md.


What "hardened" means here

Axis What you get
Runtime credential & data safety Env scrubbed to cloud creds only; 0700 report dir + umask 0077; secrets redacted out of the report and ScoutSuite's logs; --fail-on-secret gate
Secure-by-default policy Curated, CIS-aligned AWS baseline ruleset applied by default (high-impact IAM/logging/network controls forced to danger)
Supply-chain & build integrity Hash-pinned requirements.lock, CycloneDX SBOM, CodeQL, Dependabot, cosign-signed images + build provenance; release blocked if the lock isn't pinned
Hardened deployment Distroless, non-root, --read-only container; bundled least-privilege AWS audit role (read-only + explicit Deny, MFA + ExternalId trust)

How it works

presidio-scout aws ──▶ launcher ──▶ [ scout aws … ] ──▶ redact ──▶ report_guard ──▶ report/
                       (validate     (subprocess;       (scrub      (CSP + integrity
                        + harden)     env-scoped)        secrets)     manifest)
  1. launcher — validates the provider + pass-through flags (fail-closed allowlist), forces --no-browser and a locked-down --report-dir, wires in the curated ruleset, and scrubs the environment.
  2. subprocess — stock ScoutSuite runs with only the cloud credentials it needs.
  3. redact — credentials are scrubbed out of the report files and ScoutSuite's own output.
  4. report_guard — a strict CSP is injected into the HTML report and a SHA-256 integrity manifest is recorded.

Install

The wrapper has no runtime dependencies and never imports ScoutSuite. You supply scout yourself (recommended: a pinned virtualenv or the container).

pip install presidio-hardened-scoutsuite          # wrapper only (MIT)

# Convenience extra that also installs ScoutSuite (GPL-2.0) into your env:
pip install 'presidio-hardened-scoutsuite[scoutsuite]'

Or use the hardened container (bundles a pinned ScoutSuite):

docker run --rm --read-only --tmpfs /tmp \
  -e AWS_PROFILE=auditor \
  -v "$HOME/.aws:/tmp/.aws:ro" \
  -v "$PWD/scoutsuite-report:/report" \
  ghcr.io/presidio-v/presidio-hardened-scoutsuite:latest \
  aws --report-dir /report

CLI usage

presidio-scout aws                          # audit AWS with the hardened defaults
presidio-scout aws --report-dir ./out       # choose the (0700) report directory
presidio-scout aws -- --profile auditor     # pass-through flags after '--' (allowlisted)
presidio-scout aws --fail-on-secret         # non-zero exit if a secret survives redaction
presidio-scout aws --no-baseline            # use ScoutSuite's default ruleset instead
presidio-scout aws --dry-run                # print the hardened command, run nothing
presidio-scout azure                        # Azure audit with the hardened Azure baseline
presidio-scout gcp                          # GCP audit with the hardened GCP baseline

AWS, Azure, and GCP each ship a curated baseline; other providers fall back to ScoutSuite's default ruleset (with a warning) until their baselines land.

Anything after -- is forwarded to ScoutSuite only if it's on the pass-through allowlist (--profile, --region(s), --services, --skip, --max-rate, …). Flags the launcher owns (--report-dir, --ruleset, --no-browser) and unknown flags are rejected with exit code 2 — a new upstream flag can't silently weaken a run until it's vetted and added.

Exit codes: 0 ok · 2 invalid invocation / scout not found · 3 report guard failure (e.g. --fail-on-secret).


Library usage

from presidio_scoutsuite import build_plan, run, redact_report_dir, guard_report

plan = build_plan("aws", "scoutsuite-report", ruleset="src/presidio_scoutsuite/policy/aws-cis.json")
print(plan.redacted_command())          # scout aws --no-browser --report-dir … --ruleset …

result = run(plan)                      # subprocess.CompletedProcess
redact_report_dir(plan.report_dir)      # scrub secrets out of the report
guard = guard_report(plan.report_dir)   # inject CSP + build integrity manifest
print(len(guard.manifest), "files;", len(guard.html_hardened), "HTML hardened")

Least-privilege audit identities

ScoutSuite needs broad read-only access. Bundled, ready-to-apply identities grant exactly that and nothing else, per cloud:

  • AWS (iam/aws/) — the two managed read-only policies, a supplemental read policy with an explicit Deny on any non-read action, and a trust policy requiring MFA + a random ExternalId.
  • Azure (iam/azure/) — Reader + Security Reader (or a custom */read role with no dataActions, so secret/key values stay unreadable), plus minimal directory read for the Azure AD findings.
  • GCP (iam/gcp/) — roles/viewer + roles/iam.securityReviewer (or a custom role listing only *.list/*.get permissions), assumed via service-account impersonation over a downloaded key.

Curated rulesets

Curated baselines ship for AWS, Azure, and GCP under src/presidio_scoutsuite/policy/ (aws-cis.json, azure-cis.json, gcp-cis.json). Each enables a CIS-aligned subset of ScoutSuite's findings and elevates the high-impact ones to danger. Override with --ruleset PATH or opt out with --no-baseline.

A ruleset's keys are the filenames of finding rules that live inside ScoutSuite. If a baseline names a rule the pinned ScoutSuite doesn't ship (a typo or an upstream rename), ScoutSuite silently drops that control. To catch that, each provider ships a rule-name inventory (policy/<provider>.rules.txt) tracking the pinned upstream version, and a validator checks the baselines against it:

presidio-scout-validate                  # offline: baselines ⊆ checked-in manifests (runs in CI)
presidio-scout-validate --source installed   # release: baselines ⊆ the installed ScoutSuite

CI runs the offline check on every push; the release pipeline runs the installed check against the pinned ScoutSuite so the manifest can't drift from upstream unnoticed. Regenerate a manifest with ruleset.installed_rules("<provider>") (see the header of each .rules.txt).


Roadmap

Version Highlights
0.1.0 Out-of-process hardened launcher, report redaction + guard, AWS-first curated ruleset + least-privilege IAM, hardened container, full supply-chain posture
0.2.0 Azure + GCP curated baselines & least-privilege IAM; ruleset rule-name validation against the pinned ScoutSuite (offline manifest in CI, installed-source drift check at release)
0.3.0 (planned) Deeper report guard (subresource integrity, offline viewer), signed report manifests
0.4.0 (planned) SLSA provenance verification on pull; reproducible-build attestation

Running tests

pip install -e ".[dev]"
pytest --cov=presidio_scoutsuite --cov-report=term-missing
ruff check . && ruff format --check .

Tests run without ScoutSuite installed — the subprocess boundary is injected.


Project structure

presidio-hardened-scoutsuite/
├── src/presidio_scoutsuite/
│   ├── launcher.py        # build/run the hardened scout subprocess
│   ├── redact.py          # secret detection + in-place redaction
│   ├── report_guard.py    # CSP injection + integrity manifest
│   ├── ruleset.py         # baseline rule-name validation (presidio-scout-validate)
│   ├── cli.py             # presidio-scout entrypoint
│   ├── errors.py          # exception hierarchy
│   └── policy/            # curated baselines (aws/azure/gcp-cis.json) + rule manifests
├── iam/{aws,azure,gcp}/   # least-privilege audit identities per cloud
├── tests/
├── Dockerfile             # distroless, non-root
├── requirements.lock      # hash-pinned runtime tree (incl. ScoutSuite)
├── .github/workflows/     # ci, codeql, sbom, release (cosign + provenance)
├── LICENSE                # MIT (this wrapper)
└── LICENSES/README.md     # GPL-2.0 notice for bundled ScoutSuite

License

MIT for this wrapper — see LICENSE. It bundles/installs ScoutSuite (GPL-2.0-only) separately; see LICENSES/README.md.

Security

See SECURITY.md.

SDLC

Developed under the Presidio hardened-family SDLC: https://github.com/presidio-v/presidio-hardened-docs/blob/main/sdlc/sdlc-report.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

presidio_hardened_scoutsuite-0.2.0.tar.gz (35.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

presidio_hardened_scoutsuite-0.2.0-py3-none-any.whl (26.0 kB view details)

Uploaded Python 3

File details

Details for the file presidio_hardened_scoutsuite-0.2.0.tar.gz.

File metadata

  • Download URL: presidio_hardened_scoutsuite-0.2.0.tar.gz
  • Upload date:
  • Size: 35.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for presidio_hardened_scoutsuite-0.2.0.tar.gz
Algorithm Hash digest
SHA256 19eb5e7a0b71ba7ba00465873322d72ae9b79a992cf3170cebf0947a04b11288
MD5 d80db8bc822c93f6dc4820fb2062889f
BLAKE2b-256 7777f762b6b9538b406f851c3a201292641faef60a71dc66c8f3b5e3fa6bc009

See more details on using hashes here.

File details

Details for the file presidio_hardened_scoutsuite-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: presidio_hardened_scoutsuite-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 26.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for presidio_hardened_scoutsuite-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 886f79bd96f4a7e0d7a28101b1baef3a6ceaec1a49e50722e6845a58de1e345c
MD5 020375d1ffdb9519191340f5770b0ce9
BLAKE2b-256 41f56c5dec1f3e6c7a6535bb745aca90aa934a6f102c7ac4c2e144e3383875b0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page