Trivy for cloud waste. A scanner that finds orphaned resources and enforces hygiene in CI.
Like tfsec for Terraform or trivy for containers — CleanCloud scans your cloud environment and reports what's wasting money. Run it once for a quick audit, schedule it, or wire it into CI/CD to fail builds on policy violations.
- 20 high-signal detection rules: orphaned volumes, idle databases, empty load balancers, and more
- Estimated monthly waste: per finding and aggregate
- CI-native enforcement (opt-in):
--fail-on-confidence HIGHor--fail-on-cost 100gates your pipeline - Multiple output formats: human-readable, JSON, CSV, and markdown (paste into GitHub PRs or Slack)
- Read-only by design: no deletions, no tag changes, no mutations — ever
- No agents. No telemetry. No SaaS. Runs in your environment, data never leaves
Use cases:
- One-time cloud waste audit — run in CloudShell, see findings in 60 seconds
- Scheduled hygiene scans — cron job or weekly CI run to catch drift
- CI/CD enforcement gates — fail builds when waste exceeds your threshold
Found 6 hygiene issues:
1. [AWS] Unattached EBS Volume — $40/month
2. [AWS] Idle NAT Gateway — $32.40/month
3. [AWS] Unattached Elastic IP — $0/month
...
Estimated monthly waste: ~$147
Regions scanned: us-east-1, us-west-2, eu-west-1
"Solid discovery tool that bubbles up potential savings. Easy to install and use!" — Reddit user
pipx install cleancloud
pipx ensurepath # adds cleancloud to PATH — restart your shell after this
cleancloud demo # see sample findings without any cloud credentialsWhen you're ready to scan your real environment:
cleancloud scan --provider aws --all-regions
cleancloud scan --provider azureGot an AWS or Azure account? Run a real scan in seconds with no local setup.
AWS — AWS CloudShell:
pip install --upgrade cleancloud
cleancloud doctor --provider aws # check what permissions your session has
cleancloud scan --provider aws --all-regionsAzure — Azure Cloud Shell:
pip install --upgrade --user cleancloud
export PATH="$HOME/.local/bin:$PATH"
cleancloud doctor --provider azure # check what permissions your session has
cleancloud scan --provider azureBoth shells authenticate using your portal session — no separate credentials needed.
Permissions vary by account;
doctor tells you exactly what's available before you scan. If permissions are missing, CleanCloud skips those rules and reports what was skipped.
Install troubleshooting
macOS: brew install pipx && pipx install cleancloud
Linux: sudo apt install pipx && pipx install cleancloud
Windows: python3 -m pip install --user pipx && python3 -m pipx ensurepath && pipx install cleancloud
Command not found: cleancloud — Run pipx ensurepath then restart your shell.
externally-managed-environment error — Use pipx instead of pip.
Upgrading from a previous pip install — remove it first to avoid shadowing:
pip uninstall cleancloud && pipx install cleancloud && pipx ensurepathWrong version after install — Run which cleancloud; an old pip install may be shadowing pipx.
Minimum recommended version: v1.6.3 — earlier versions have setup friction. Run cleancloud --version to check.
Found 6 hygiene issues:
1. [AWS] Unattached EBS Volume
Risk : Low
Confidence : High
Resource : aws.ebs.volume → vol-0a1b2c3d4e5f67890
Region : us-east-1
Rule : aws.ebs.volume.unattached
Reason : Volume has been unattached for 47 days
Details:
- size_gb: 500
- state: available
- tags: {"Project": "legacy-api", "Owner": "platform"}
2. [AWS] Idle NAT Gateway
Risk : Medium
Confidence : Medium
Resource : aws.ec2.nat_gateway → nat-0abcdef1234567890
Region : us-west-2
Rule : aws.ec2.nat_gateway.idle
Reason : No traffic detected for 21 days
Details:
- name: staging-nat
- total_bytes_out: 0
- estimated_monthly_cost_usd: 32.40
3. [AWS] Unattached Elastic IP
Risk : Low
Confidence : High
Resource : aws.ec2.elastic_ip → eipalloc-0a1b2c3d4e5f6
Region : eu-west-1
Rule : aws.ec2.elastic_ip.unattached
Reason : Elastic IP not associated with any instance or ENI (age: 92 days)
--- Scan Summary ---
Total findings: 6
By risk: low: 5 medium: 1
By confidence: high: 2 medium: 4
Minimum estimated waste: ~$147/month
(4 of 6 findings costed)
Regions scanned: us-east-1, us-west-2, eu-west-1 (auto-detected)
No cloud account yet? cleancloud demo shows sample output without any credentials.
cleancloud scan --provider aws --all-regions --output markdownPrints a grouped summary you can paste directly into a GitHub PR comment, Slack message, or issue:
## CleanCloud Scan Results
**Provider:** AWS
**Regions:** us-east-1, us-west-2, eu-west-1
**Scanned:** 2026-03-07
**Estimated monthly waste:** ~$147
**Total findings:** 6
| Finding | Count | Est. Monthly Cost |
|---------|------:|------------------:|
| Unattached EBS Volume | 2 | ~$115 |
| Idle NAT Gateway | 1 | ~$32 |
| Unattached Elastic IP | 1 | ~$0 |
| Detached ENI | 1 | — |
| CloudWatch Log Group: Infinite Retention | 1 | — |
**Confidence:** high: 3 · medium: 3
> Generated by [CleanCloud](https://github.com/cleancloud-io/cleancloud) — read-only cloud hygiene scanner for AWS and Azure.Save to a file with --output-file results.md. Without --output-file, it prints to stdout.
For full output examples including doctor, JSON, CSV, and markdown: docs/example-outputs.md
20 rules across AWS and Azure — conservative, high-signal, designed to avoid false positives in IaC environments.
AWS:
- Unattached EBS volumes (HIGH)
- Old EBS snapshots
- Infinite retention CloudWatch Logs
- Unattached Elastic IPs (HIGH)
- Detached ENIs
- Untagged resources
- Old AMIs
- Idle NAT Gateways
- Idle RDS instances (HIGH)
- Idle load balancers (HIGH)
Azure:
- Unattached managed disks
- Old snapshots
- Unused public IPs (HIGH)
- Empty load balancers (HIGH)
- Empty App Gateways (HIGH)
- Empty App Service Plans (HIGH)
- Idle VNet Gateways
- Stopped (not deallocated) VMs (HIGH)
- Idle SQL databases (HIGH)
- Untagged resources
Rules without a confidence marker are MEDIUM — they use time-based heuristics or multiple signals. Start with --fail-on-confidence HIGH to catch obvious waste, then tighten as your team validates.
Full rule details, signals, and evidence: docs/rules.md
Scans exit 0 by default. Opt in to enforcement:
| Flag | Behavior | Exit code |
|---|---|---|
| (none) | Report only, never fail | 0 |
--fail-on-confidence HIGH |
Fail on HIGH confidence findings | 2 |
--fail-on-confidence MEDIUM |
Fail on MEDIUM or higher | 2 |
--fail-on-cost 50 |
Fail if estimated monthly waste >= $50 | 2 |
--fail-on-findings |
Fail on any finding | 2 |
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/CleanCloudCIReadOnly
aws-region: us-east-1
- run: pip install cleancloud
- run: |
cleancloud scan --provider aws --all-regions \
--fail-on-confidence HIGH \
--output json --output-file scan.json- uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- run: pip install cleancloud
- run: |
cleancloud scan --provider azure \
--fail-on-confidence MEDIUM \
--output json --output-file scan.jsonComplete CI/CD guide: docs/ci.md — OIDC setup, enforcement patterns, output formats.
Setup guides: AWS · Azure
CI/CD snippets above use
pip install— correct for ephemeral runners where pipx isolation isn't needed.
- Additional AWS rules (S3 lifecycle, stopped EC2 instances)
- Policy-as-code in
cleancloud.yaml(fail_on_confidence,fail_on_costin config) - Rule filtering (
--rulesflag) - Multi-account scanning (AWS Organizations)
docs/rules.md— Detection rules, signals, and evidencedocs/aws.md— AWS IAM policy and OIDC setupdocs/azure.md— Azure RBAC and Workload Identity setupdocs/ci.md— CI/CD integration guidedocs/example-outputs.md— Full output examplesSECURITY.md— Security policy and threat modeldocs/infosec-readiness.md— IAM Proof Pack, threat model
Found a bug? Open an issue
Feature request? Start a discussion
Questions? suresh@getcleancloud.com