PYTHON · STATIC SECURITY ANALYSIS

CloudSentry

A local scanner for selected risky configuration patterns in Terraform, Dockerfiles, and Docker Compose—with more accurate finding locations, safer suppression behavior, and clearer scan failures.

View source on GitHub ↗

Loading the current project snapshot…

What it does

CloudSentry reads configuration files and reports findings with a rule ID, severity, confidence, source location, evidence, impact, remediation, and a stable fingerprint. It provides a command-line interface with text, JSON, and SARIF 2.1.0 reports, a local FastAPI API, and a React + TypeScript dashboard. It scans statically: it does not apply Terraform, build images, start containers, or execute the files it reads.

Implemented scope

  • Terraform: checks for public S3 ACLs, world-open AWS security-group ingress CIDRs, and EBS volumes with encryption explicitly disabled.
  • Dockerfiles: checks for an explicit root user, mutable latest base-image tags, and a missing USER instruction.
  • Docker Compose: checks privileged services, host networking, Docker socket mounts, and wildcard host-port bindings.

That is 10 documented rule IDs across three configuration formats. The project includes positive and negative fixtures and regression tests for line attribution, suppression behavior, and CLI exit codes.

Latest improvements: clearer reports and scan states

SARIF output for code-scanning workflows

The CLI now supports SARIF 2.1.0 alongside text and JSON. Invocation diagnostics preserve warnings and errors, and suppression justifications stay in machine-readable output. This makes it easier to pass results to compatible code-scanning tools without hiding the fact that part of a scan was incomplete.

The dashboard distinguishes complete, partial, and failed scans

The dashboard now exposes clear Complete, Partial, and Error states, with search and severity filtering for findings. Suppressed findings are hidden from the default active-risk view but can be inspected with their reasons. Unsupported inputs and unreadable files should not be mistaken for a clean scan.

Latest improvements: making findings more trustworthy

Finding locations point to the relevant code

Previously, source attribution could use the first matching text in a file, so a later insecure resource might be reported against an earlier resource. Terraform findings now locate the relevant resource or ingress block where possible; Compose uses parsed YAML node positions. This makes the finding easier to review and helps line-based suppressions target the intended code.

Suppressions are narrow and auditable

A cloudsentry:ignore comment now applies only to the next line of code (blank lines and comments may sit between them), or to the line containing a trailing directive. A reason is required. Unmatched directives and directives without reasons produce warnings. Suppressed findings remain in JSON and API results with suppressed: true and the reason, but are excluded from the risk score and exit status; the text report shows a suppression count.

Incomplete scans cannot look clean

The CLI exit codes now distinguish a clean scan (0), qualifying findings (1), and usage or scan errors (2). If any file cannot be scanned—for example, because it is malformed, unreadable, or oversized—exit code 2 takes precedence over findings. This avoids a CI check passing just because a broken file sat beside otherwise clean input.

Example: reviewing a Terraform fixture

The repository includes examples/terraform/storage.vulnerable.tf. It deliberately sets an S3 ACL to public-read and an EBS volume to encrypted = false. Those literal settings map to these implemented checks:

CS-TF-001 · Critical

aws_s3_bucket_acl.assets — S3 bucket ACL allows public access.

Evidence: acl = "public-read"

Remediation: Remove public ACL grants and enforce S3 Block Public Access and least-privilege bucket policies.

CS-TF-003 · High

aws_ebs_volume.data — EBS volume encryption explicitly disabled.

Evidence: encrypted = false

Remediation: Enable encryption and define an approved KMS key policy where required.

This is a walkthrough of the committed fixture and matching rule implementation, not a claim that these settings were found in a live cloud account. The sample is intentionally vulnerable test data.

Running it locally

The CLI can scan the included examples and produce either a readable report or JSON. Use the virtual-environment executables directly, so activating the environment is optional and the commands work in Fish as well as common POSIX shells. For the dashboard, start the API and frontend in separate terminals, then enter a configuration file or directory path on the machine running the API.

.venv/bin/cloudsentry scan examples --format text
.venv/bin/cloudsentry scan examples --format json --output report.json

For the dashboard, install frontend dependencies with npm install from frontend/ and start the dev server with npm run dev -- --host 127.0.0.1. Keep the API bound to 127.0.0.1: its scan endpoint accepts local filesystem paths and is intended for local development, not untrusted network clients. The README also documents a temporary demo scan and development checks.

Design trade-offs and limitations

Local static analysis is repeatable and does not need cloud credentials, but it cannot calculate the final effective permissions or network exposure of a deployed system. Terraform checks rely on literal parsed values and do not resolve variables, locals, modules, dynamic blocks, provider defaults, or effective policy. Source-line recovery is best-effort for unusual Terraform templates or heredocs; Compose services created through YAML anchors or merge keys may be attributed to the service-name line. Dockerfile checks are line-oriented and do not fully model multi-stage inheritance, build arguments, or orchestrator overrides. False positives and false negatives remain possible, and the risk score is a severity-weighted heuristic—not a probability or compliance score. A clean scan is not proof of security.

Tests and CI

Regression tests cover source-line attribution, narrow suppression scope, preservation of suppressed findings and their justifications in JSON/SARIF, CLI SARIF integration, warnings for ineffective directives, and error exit-code precedence. Frontend CI installs from the committed lockfile with npm ci. The project also has positive and negative rule tests, Python lint/test checks, and a frontend build in CI.

Read the code, rules, tests, changelog, and limitations ↗