11# Cloud Misconfig Scanner
22
3+ [ ![ CI] ( https://github.com/frangelbarrera/Cloud-Misconfig-Scanner/actions/workflows/ci.yml/badge.svg )] ( https://github.com/frangelbarrera/Cloud-Misconfig-Scanner/actions/workflows/ci.yml )
34[ ![ Python] ( https://img.shields.io/badge/Python-3.9+-blue.svg )] ( https://www.python.org/ )
45[ ![ License: MIT] ( https://img.shields.io/badge/License-MIT-yellow.svg )] ( LICENSE )
56[ ![ AWS] ( https://img.shields.io/badge/AWS-S3-orange.svg )] ( https://aws.amazon.com/s3/ )
67[ ![ Last Commit] ( https://img.shields.io/github/last-commit/frangelbarrera/Cloud-Misconfig-Scanner )] ( https://github.com/frangelbarrera/Cloud-Misconfig-Scanner )
78
8- > A Python CLI tool for detecting misconfigurations in cloud storage services. Currently supports ** AWS S3 with real API scanning** . Azure Blob and GCP Storage are on the roadmap.
9+ > A Python CLI tool for detecting misconfigurations in cloud storage services. ** AWS S3 is fully supported with real API scanning. ** Azure Blob and GCP Storage currently run in simulated mode ( roadmap) .
910
1011## Features
1112
1213### AWS S3 (Active)
13- - ** Real API scanning** via boto3 (uses your AWS credentials)
14- - ** Account-level Public Access Block ** verification
15- - ** Bucket-level Public Access Block ** per bucket
14+ - ** Real API scanning** via boto3 (auto-detects your AWS credentials)
15+ - ** Account-level Block Public Access (BPA) ** verification
16+ - ** Bucket-level BPA ** per bucket (all four flags checked)
1617- ** Server-side encryption** detection
1718- ** Versioning** status check
18- - ** Bucket ACL** analysis (public-read, public-read-write)
19- - ** Bucket Policy** analysis (public ` Principal: * ` )
20- - ** Access logging** verification
19+ - ** Bucket ACL** analysis — flags ` AllUsers ` / ` AllAuthenticatedUsers ` grants as CRITICAL
20+ - ** Bucket Policy** analysis — flags ` Principal: "*" ` Allow statements as CRITICAL
21+ - ** Server access logging** verification
22+ - ** MFA Delete** status check (when versioning is enabled)
23+ - ** Simulated mode** as a graceful fallback when no AWS credentials are present
24+ - ** YAML-driven rules** — all finding metadata lives in ` cms/checks/aws_s3_rules.yaml ` , consistent with Azure/GCP
2125
2226### Azure Blob (Roadmap)
2327- Simulated mode only (real SDK integration planned)
3034### Prerequisites
3135- Python 3.9+
3236- AWS account with read-only S3 permissions (for real scanning)
33- - AWS credentials configured (` ~/.aws/credentials ` or environment variables )
37+ - AWS credentials configured (` ~/.aws/credentials ` or ` AWS_ACCESS_KEY_ID ` / ` AWS_SECRET_ACCESS_KEY ` env vars )
3438
3539### Installation
3640
3741``` bash
3842git clone https://github.com/frangelbarrera/Cloud-Misconfig-Scanner.git
3943cd Cloud-Misconfig-Scanner
44+
45+ # Runtime dependencies
4046pip install -r requirements.txt
47+
48+ # OR: editable install (also registers the console script)
49+ pip install -e .
4150```
4251
4352### Usage
4453
45- #### Real AWS S3 Scan
54+ #### Real AWS S3 Scan (default behaviour)
4655``` bash
47- # Using default AWS profile
56+ # Auto-detects credentials and runs in real mode
4857python cms.py --provider aws
4958
50- # Using specific profile
59+ # Using a specific profile
5160python cms.py --provider aws --profile my-profile
5261
5362# JSON output
5463python cms.py --provider aws --format json
5564
56- # HTML report (saved to report.html)
57- python cms.py --provider aws --format html
65+ # HTML report to a specific file
66+ python cms.py --provider aws --format html -o report.html
67+
68+ # Only show HIGH and CRITICAL findings
69+ python cms.py --provider aws --severity HIGH
70+
71+ # Scan only specific buckets
72+ python cms.py --provider aws --targets bucket-a,bucket-b
5873```
5974
60- #### Simulated Mode (no AWS credentials needed)
75+ #### Simulated Mode
6176
62- The scanner automatically detects when AWS credentials are not available ( ` ~/.aws/credentials ` missing) and runs in simulated mode. No extra flag is needed — just run:
77+ Simulated mode emits one finding per rule in ` cms/checks/aws_s3_rules.yaml ` against a fake bucket, so you can exercise the CLI/reporters without cloud credentials.
6378
64- python cms.py --provider aws
79+ ``` bash
80+ # Force simulated mode (useful for CI / sandbox testing)
81+ python cms.py --provider aws --simulated
82+ ```
83+
84+ If no AWS credentials are detected at all, the scanner auto-falls-back to simulated mode.
85+
86+ ### Exit Codes
87+
88+ | Code | Meaning |
89+ | ------| ------------------------------------|
90+ | 0 | No findings (posture looks clean) |
91+ | 1 | Findings detected |
92+ | 2 | CLI usage error |
93+ | 3 | Scanner runtime error |
6594
6695### Required AWS IAM Permissions
6796
@@ -76,69 +105,105 @@ Key permissions:
76105- ` s3:GetBucketPolicy `
77106- ` s3:GetBucketLogging `
78107- ` s3control:GetPublicAccessBlock `
108+ - ` sts:GetCallerIdentity `
79109
80110## Architecture
81111
82112```
83113Cloud-Misconfig-Scanner/
84- ├── cms.py # CLI entry point
114+ ├── cms.py # Legacy CLI entry point (delegates to cms.cli)
85115├── cms/
116+ │ ├── __init__.py
117+ │ ├── __main__.py # Allows `python -m cms`
118+ │ ├── cli.py # CLI implementation (argparse + exit codes)
86119│ ├── core/ # Core engine
87120│ │ ├── models.py # Resource, Finding, ScanResult dataclasses
88- │ │ ├── rules.py # YAML rule loader
89- │ │ ├── reporter.py # Text/JSON output
90- │ │ └── html_reporter.py # HTML report generator
91- │ ├── providers/ # Cloud providers
92- │ │ ├── base.py # ProviderScanner ABC
93- │ │ ├── aws_s3.py # AWS S3 scanner (real API)
121+ │ │ ├── rules.py # YAML rule loader + RuleRegistry
122+ │ │ ├── reporter.py # Text/JSON output + severity filtering
123+ │ │ └── html_reporter.py # HTML report (XSS-safe, CRITICAL supported)
124+ │ ├── providers/ # Cloud providers (all subclass ProviderScanner)
125+ │ │ ├── base.py # ProviderScanner ABC + shared helpers
126+ │ │ ├── aws_s3.py # AWS S3 scanner (real API + simulated fallback )
94127│ │ ├── azure_blob.py # Azure Blob (simulated, roadmap)
95128│ │ └── gcp_storage.py # GCP Storage (simulated, roadmap)
96129│ └── checks/ # YAML rule definitions
97130│ ├── aws_s3_rules.yaml
98131│ ├── azure_blob_rules.yaml
99132│ └── gcp_storage_rules.yaml
100- └── docs/
101- └── iam/
102- └── aws_least_privilege.json
133+ ├── tests/ # pytest + moto test suite
134+ │ ├── conftest.py
135+ │ ├── test_rules.py
136+ │ ├── test_reporter.py
137+ │ ├── test_html_reporter.py
138+ │ ├── test_aws_s3_scanner.py
139+ │ └── test_cli.py
140+ ├── docs/
141+ │ └── iam/
142+ │ ├── aws_least_privilege.json
143+ │ ├── azure_least_privilege.md
144+ │ └── gcp_least_privilege.md
145+ ├── .github/workflows/ci.yml # GitHub Actions: pytest + ruff on push/PR
146+ ├── pyproject.toml # pip install -e . support + tool config
147+ ├── requirements.txt # Runtime deps
148+ └── requirements-dev.txt # Test/lint deps
103149```
104150
105151## Output Formats
106152
107153### Text (default)
108154```
109- [CRITICAL] S3-BUCKET-PUBLIC-ACL
110- Resource: my-bucket
111- Description: Bucket ACL allows public read access
112- Remediation: Remove AllUsers grant from bucket ACL
113-
114- [HIGH] S3-NO-ENCRYPTION
115- Resource: another-bucket
116- Description: Server-side encryption is not enabled
117- Remediation: Enable SSE-S3 or SSE-KMS on the bucket
155+ Findings:
156+ - [CRITICAL] AWS-S3-PUBLIC-ACL | Bucket ACL allows public access -> aws:my-bucket
157+ - [HIGH] AWS-S3-ENCRYPTION | No default server-side encryption -> aws:another-bucket
118158```
119159
120160### JSON
121161``` json
122- {
123- "findings" : [
124- {
125- "rule_id" : " S3-BUCKET-PUBLIC-ACL" ,
126- "severity" : " CRITICAL" ,
127- "resource" : " my-bucket" ,
128- "description" : " Bucket ACL allows public read access" ,
129- "remediation" : " Remove AllUsers grant from bucket ACL"
130- }
131- ]
132- }
162+ [
163+ {
164+ "rule_id" : " AWS-S3-PUBLIC-ACL" ,
165+ "title" : " Bucket ACL allows public access" ,
166+ "severity" : " CRITICAL" ,
167+ "description" : " ..." ,
168+ "remediation" : " ..." ,
169+ "resource" : {
170+ "provider" : " aws" , "service" : " s3" , "account" : " 123456789012" ,
171+ "region" : " us-east-1" , "name" : " my-bucket" , "meta" : {}
172+ },
173+ "evidence" : { "public_grants" : [{"grantee" : " http://acs.amazonaws.com/groups/global/AllUsers" , "permission" : " READ" }] }
174+ }
175+ ]
133176```
134177
135178### HTML
136- Interactive HTML report with severity color-coding (CRITICAL=red, HIGH=orange, MEDIUM=yellow, LOW=blue).
179+ Self-contained HTML report with severity color-coding (CRITICAL=red, HIGH=pink, MEDIUM=yellow, LOW=blue). All fields are HTML-escaped to prevent XSS.
180+
181+ ## Development
182+
183+ ``` bash
184+ pip install -r requirements.txt
185+ pip install -r requirements-dev.txt
186+ pip install -e .
187+
188+ # Run tests with coverage (>=80% enforced)
189+ pytest -v
190+
191+ # Lint
192+ ruff check cms tests
193+ ```
137194
138195## Roadmap
139196
140197- [x] AWS S3 real API scanning
141- - [ ] AWS S3 Bucket Policy deep analysis
198+ - [x] AWS S3 Bucket Policy deep analysis (Principal: "* " detection)
199+ - [x] AWS S3 Bucket ACL analysis (AllUsers / AllAuthenticatedUsers)
200+ - [x] AWS S3 Access Logging verification
201+ - [x] AWS S3 MFA Delete verification
202+ - [x] YAML-driven AWS rules (consistency with Azure/GCP)
203+ - [x] Tests with moto + pytest (>=80% core coverage)
204+ - [x] GitHub Actions CI (pytest + ruff)
205+ - [x] CLI improvements: --output, --severity, exit codes
206+ - [x] HTML reporter: XSS fix, CRITICAL severity
142207- [ ] AWS IAM scanning (overly permissive policies)
143208- [ ] Azure Blob real API scanning
144209- [ ] GCP Storage real API scanning
@@ -155,8 +220,8 @@ Contributions welcome! See [CONTRIBUTING.md](CONTRIBUTING.md).
155220Areas needing help:
156221- Azure Blob real API implementation
157222- GCP Storage real API implementation
158- - Test coverage (pytest + moto)
159- - CI/CD pipeline
223+ - AWS IAM scanning module
224+ - SARIF output format
160225
161226## Security
162227
0 commit comments