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
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
scoutCLI 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. SeeLICENSES/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)
- launcher — validates the provider + pass-through flags (fail-closed
allowlist), forces
--no-browserand a locked-down--report-dir, wires in the curated ruleset, and scrubs the environment. - subprocess — stock ScoutSuite runs with only the cloud credentials it needs.
- redact — credentials are scrubbed out of the report files and ScoutSuite's own output.
- 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 explicitDenyon any non-read action, and a trust policy requiring MFA + a randomExternalId. - Azure (
iam/azure/) —Reader+Security Reader(or a custom*/readrole with nodataActions, 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/*.getpermissions), 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19eb5e7a0b71ba7ba00465873322d72ae9b79a992cf3170cebf0947a04b11288
|
|
| MD5 |
d80db8bc822c93f6dc4820fb2062889f
|
|
| BLAKE2b-256 |
7777f762b6b9538b406f851c3a201292641faef60a71dc66c8f3b5e3fa6bc009
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
886f79bd96f4a7e0d7a28101b1baef3a6ceaec1a49e50722e6845a58de1e345c
|
|
| MD5 |
020375d1ffdb9519191340f5770b0ce9
|
|
| BLAKE2b-256 |
41f56c5dec1f3e6c7a6535bb745aca90aa934a6f102c7ac4c2e144e3383875b0
|