Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
0824191
docs: add design doc for gates 9-18 (deps, api, privacy, resilience, …
sadayamuthu Feb 27, 2026
8ae9abd
docs: add implementation plan for gates 9-18 (10 new gates, TDD, one-…
sadayamuthu Feb 27, 2026
4c04200
feat: add Gate 9 — Dependency Vulnerability gate (deps, RA-5/SI-2/SA-12)
sadayamuthu Feb 27, 2026
4f6d9a2
fix: scope --no-verify pattern to package managers, add range specifi…
sadayamuthu Feb 27, 2026
1c938b0
feat: add Gate 10 — API Security gate (api, SC-8/AC-3/SC-5)
sadayamuthu Feb 27, 2026
23baf6d
fix: add missing GraphQL introspection test, remove dead SC-5/SI-10 d…
sadayamuthu Feb 27, 2026
768d64f
feat: add Gate 11 — Data Privacy gate (privacy, PT-2/PT-3/SC-28)
sadayamuthu Feb 27, 2026
f7e2b59
feat: add Gate 12 — Resilience & Backup gate (resilience, CP-9/CP-10/…
sadayamuthu Feb 27, 2026
e016fb7
feat: add Gate 13 — Incident Response gate (incident, IR-4/IR-6/AU-6)
sadayamuthu Feb 27, 2026
8965fae
feat: add Gate 14 — Observability gate (observability, SI-4/AU-12)
sadayamuthu Feb 27, 2026
227d2d0
feat: add Gate 15 — Memory Safety gate (memsafe, SI-16/CM-7)
sadayamuthu Feb 27, 2026
3c80867
feat: add Gate 16 — License Compliance gate (license, SA-4/SR-3)
sadayamuthu Feb 27, 2026
8554375
feat: add Gate 17 — AI/ML Security gate (aiml, SI-10/SC-28/SR-3)
sadayamuthu Feb 27, 2026
56a987a
feat: add Gate 18 — Container Security gate (container, CM-7/SC-7/SC-…
sadayamuthu Feb 27, 2026
54771a2
docs: add gate gap analysis — 3 bugs to fix, 4 items deferred as know…
sadayamuthu Feb 27, 2026
cad0ce5
docs: add implementation plan for gate gap fixes (3 tasks)
sadayamuthu Feb 27, 2026
154ea92
fix: add SC-5 and SI-10 to APIGate control map (align with design)
sadayamuthu Feb 27, 2026
00af207
feat: add cffi memory operation detection to MemSafeGate (SI-16)
sadayamuthu Feb 27, 2026
55206cd
fix: add word-boundary guard to cffi pattern; add false-positive test…
sadayamuthu Feb 27, 2026
d840dc1
feat: add plaintext model weights detection to AIMLGate (SC-28)
sadayamuthu Feb 27, 2026
1342bf2
test: add false-positive guard test for SC-28 plaintext weights (AIML…
sadayamuthu Feb 27, 2026
d8bc672
docs: mark gap analysis complete — all Approach A fixes applied
sadayamuthu Feb 27, 2026
0bd89ff
docs: add per-gate documentation design (18 gates × design.md + imple…
sadayamuthu Feb 27, 2026
392babc
docs: add per-gate documentation implementation plan (19 tasks, 36 fi…
sadayamuthu Feb 27, 2026
99c09e9
docs: add Gate 1 — Secrets design and implementation reference
sadayamuthu Feb 27, 2026
aebcffe
docs: fix Gate 1 test coverage table and entropy description
sadayamuthu Feb 27, 2026
591a453
docs: add Gate 2 — Cryptography & TLS design and implementation refer…
sadayamuthu Feb 27, 2026
97b580d
docs: add Gate 3 — IAM & Access Control design and implementation ref…
sadayamuthu Feb 27, 2026
c75cdae
docs: add Gate 4 — Supply Chain & SBOM design and implementation refe…
sadayamuthu Feb 27, 2026
e53bdcd
docs: add Gate 5 — Infrastructure-as-Code design and implementation r…
sadayamuthu Feb 27, 2026
6419e22
docs: add Gate 6 — Input Validation & Error Handling design and imple…
sadayamuthu Feb 27, 2026
08462ec
docs: add Gate 7 — Audit & Logging design and implementation reference
sadayamuthu Feb 27, 2026
54d6b52
docs: add Gate 8 — Change Control design and implementation reference
sadayamuthu Feb 27, 2026
c64fcdc
docs: add Gate 2 — Crypto design and implementation reference
sadayamuthu Feb 27, 2026
f9212d6
docs: fix regex pipe escaping in Gate 2 Crypto patterns table
sadayamuthu Feb 27, 2026
1668439
docs: add Gate 3 — IAM design and implementation reference
sadayamuthu Feb 27, 2026
be492dd
docs: fix pipe escaping in Gate 3 IAM patterns table
sadayamuthu Feb 27, 2026
c609e60
docs: update Gate 4 — SBOM design and implementation reference
sadayamuthu Feb 27, 2026
a8b4bd3
docs: update Gate 5 — IaC design and implementation reference
sadayamuthu Feb 27, 2026
4145472
docs: update Gate 6 — Input Validation design and implementation refe…
sadayamuthu Feb 27, 2026
46a27d4
docs: update Gate 7 — Audit design and implementation reference
sadayamuthu Feb 27, 2026
f292ec4
docs: update Gate 8 — Change Control design and implementation reference
sadayamuthu Feb 27, 2026
802c99b
docs: add Gate 9 — Dependency Vulnerability design and implementation…
sadayamuthu Feb 27, 2026
cdc832f
docs: add Gate 10 — API Security design and implementation reference
sadayamuthu Feb 27, 2026
0d3806c
docs: add Gate 11 — Data Privacy design and implementation reference
sadayamuthu Feb 27, 2026
e835af2
docs: add Gate 12 — Resilience & Backup design and implementation ref…
sadayamuthu Feb 27, 2026
85386ee
docs: add Gate 13 — Incident Response design and implementation refer…
sadayamuthu Feb 27, 2026
8755b39
docs: add Gate 14 — Observability design and implementation reference
sadayamuthu Feb 27, 2026
c25cc3d
docs: add Gate 15 — Memory Safety design and implementation reference
sadayamuthu Feb 27, 2026
b9cb0d1
docs: add Gate 16 — License Compliance design and implementation refe…
sadayamuthu Feb 27, 2026
ee2f389
docs: add Gate 18 — Container Security design and implementation refe…
sadayamuthu Feb 27, 2026
c759bb1
docs: add design for full scan mode and init command
sadayamuthu Feb 28, 2026
90edc1b
docs: add implementation plan for full scan mode and init command
sadayamuthu Feb 28, 2026
d3b5396
feat: add full_scan config fields (extensions, skip_dirs)
sadayamuthu Feb 28, 2026
0a2ece8
fix: sync full_scan_skip_dirs default_factory with _DEFAULT_CONFIG
sadayamuthu Feb 28, 2026
2102b85
test: add module docstring to test_config.py
sadayamuthu Feb 28, 2026
a4b4d54
feat: add _get_full_files() for full-repo scan mode
sadayamuthu Feb 28, 2026
9245126
fix: use fnmatch for skip_dirs in _get_full_files, add glob pattern test
sadayamuthu Feb 28, 2026
9acb058
feat: add controlgate scan --mode full with --path option
sadayamuthu Feb 28, 2026
9a4b0ee
feat: add init_command with templates for all generated files
sadayamuthu Feb 28, 2026
219f160
fix: add catalog comment to template, add GitLab/Bitbucket tests
sadayamuthu Feb 28, 2026
1da01fe
feat: wire controlgate init subcommand into CLI
sadayamuthu Feb 28, 2026
c0981a6
docs: update README for 18 gates, full scan mode, and init command
sadayamuthu Feb 28, 2026
1a4c0cf
chore: expand .controlgate.yml to all 18 gates and update CHANGELOG
sadayamuthu Feb 28, 2026
0086994
style: apply ruff format to deps_gate and 4 test files
sadayamuthu Feb 28, 2026
379f8e8
test: achieve 100% coverage for __main__ and init_command
sadayamuthu Feb 28, 2026
64532d2
docs: add auto version bump pre-commit hook design
sadayamuthu Feb 28, 2026
b67331e
docs: add auto version bump implementation plan
sadayamuthu Feb 28, 2026
6a5b85e
feat: add auto-bump minor version pre-commit hook
sadayamuthu Feb 28, 2026
054f07d
fix: address code review issues in bump_version hook
sadayamuthu Feb 28, 2026
000ae61
chore: register bump-version as a local pre-commit hook
sadayamuthu Feb 28, 2026
ce427ea
fix: scope bump-version hook to pre-commit stage only
sadayamuthu Feb 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions .controlgate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,24 @@ gov: false # If true, evaluates against FedRAMP baselines i
catalog: baseline/nist80053r5_full_catalog_enriched.json

gates:
secrets: { enabled: true, action: block }
crypto: { enabled: true, action: block }
iam: { enabled: true, action: warn }
sbom: { enabled: true, action: warn }
iac: { enabled: true, action: block }
input: { enabled: true, action: block }
audit: { enabled: true, action: warn }
change: { enabled: true, action: warn }
secrets: { enabled: true, action: block }
crypto: { enabled: true, action: block }
iam: { enabled: true, action: warn }
sbom: { enabled: true, action: warn }
iac: { enabled: true, action: block }
input_validation: { enabled: true, action: block }
audit: { enabled: true, action: warn }
change_control: { enabled: true, action: warn }
deps: { enabled: true, action: warn }
api: { enabled: true, action: warn }
privacy: { enabled: true, action: warn }
resilience: { enabled: true, action: warn }
incident: { enabled: true, action: warn }
observability: { enabled: true, action: warn }
memsafe: { enabled: true, action: warn }
license: { enabled: true, action: warn }
aiml: { enabled: true, action: warn }
container: { enabled: true, action: warn }

thresholds:
block_on: [CRITICAL, HIGH] # Block if finding severity matches
Expand Down
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,13 @@ repos:
- id: mypy
additional_dependencies: [ types-PyYAML, pytest ]
args: [ --config-file, pyproject.toml ]

- repo: local
hooks:
- id: bump-version
name: Auto-bump version if unchanged from main
entry: python hooks/bump_version.py
language: python
always_run: true
pass_filenames: false
stages: [pre-commit]
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- **10 New Security Gates**: Expanded scanning capabilities to a total of 18 gates, including API, Privacy, Resilience, Incident, Observability, MemSafe, License, AI/ML, Container, and Dependency vulnerabilities.
- **FedRAMP Support**: ControlGate can now evaluate code changes against FedRAMP baselines (LI-SaaS, Low, Moderate, High) via the `--gov` CLI flag or `gov: true` in `.controlgate.yml`. This integrates directly with the enriched `fedramp_membership` catalog data.

## [0.1.3] - 2026-02-20
Expand Down
73 changes: 54 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ ControlGate is an AI-powered agent skill that scans your code changes against th
# Install
pip install controlgate

# Bootstrap project (creates .controlgate.yml, pre-commit hook, CI workflows)
controlgate init

# Full repo audit (first-time scan)
controlgate scan --mode full --format markdown

# Scan staged changes (NIST baseline)
controlgate scan --mode pre-commit --format markdown

Expand All @@ -33,12 +39,12 @@ git commit / Pull Request
ControlGate intercepts the diff
8 Security Gates scan against 370 non-negotiable NIST controls
18 Security Gates scan against 370 non-negotiable NIST controls
Verdict: BLOCK 🚫 / WARN ⚠️ / PASS ✅
```

## The Eight Security Gates
## The 18 Security Gates

| # | Gate | NIST Families | What It Catches |
|---|------|---------------|-----------------|
Expand All @@ -47,9 +53,19 @@ Verdict: BLOCK 🚫 / WARN ⚠️ / PASS ✅
| 3 | 🛡️ IAM | AC-3, AC-5, AC-6 | Wildcard IAM, missing auth, overprivileged roles |
| 4 | 📦 Supply Chain | SR-3, SR-11, SA-10 | Unpinned deps, missing lockfiles, build tampering |
| 5 | 🏗️ IaC | CM-2, CM-6, SC-7 | Public buckets, `0.0.0.0/0` rules, root containers |
| 6 | ✅ Input | SI-10, SI-11 | SQL injection, `eval()`, exposed stack traces |
| 6 | ✅ Input Validation | SI-10, SI-11 | SQL injection, `eval()`, exposed stack traces |
| 7 | 📋 Audit | AU-2, AU-3, AU-12 | Missing security logging, PII in logs |
| 8 | 🔄 Change | CM-3, CM-4, CM-5 | Unauthorized config changes, missing CODEOWNERS |
| 8 | 🔄 Change Control | CM-3, CM-4, CM-5 | Unauthorized config changes, missing CODEOWNERS |
| 9 | 🧩 Dependencies | SA-12, RA-5, SI-2 | Vulnerable packages, missing lockfiles |
| 10 | 🌐 API Security | SC-8, AC-3, SI-10 | Unauthenticated endpoints, missing rate limiting |
| 11 | 🔐 Privacy | AR-2, DM-1, IP-1 | PII exposure, missing data classification |
| 12 | 🔁 Resilience | CP-2, CP-10, SC-5 | Missing retry logic, no circuit breakers |
| 13 | 🚨 Incident Response | IR-2, IR-4, IR-6 | Missing error handlers, no alerting integration |
| 14 | 👁️ Observability | AU-6, SI-4, CA-7 | Missing health checks, no structured logging |
| 15 | 🧠 Memory Safety | SI-16, SA-11, SA-15 | Buffer overflows, unsafe memory operations |
| 16 | ⚖️ License Compliance | SA-4, SR-3 | GPL contamination, unlicensed dependencies |
| 17 | 🤖 AI/ML Security | SA-11, SI-7, AC-3 | Untrusted model sources, prompt injection risk |
| 18 | 🐳 Container Security | CM-6, AC-6, SC-7 | Root containers, privileged mode, `latest` tags |

## Installation

Expand Down Expand Up @@ -87,17 +103,26 @@ Create a `.controlgate.yml` in your project root:
```yaml
baseline: moderate # low | moderate | high | privacy | li-saas
gov: false # set to true to evaluate against FedRAMP baselines
catalog: baseline/nist80053r5_full_catalog_enriched.json

gates:
secrets: { enabled: true, action: block }
crypto: { enabled: true, action: block }
iam: { enabled: true, action: warn }
sbom: { enabled: true, action: warn }
iac: { enabled: true, action: block }
input: { enabled: true, action: block }
audit: { enabled: true, action: warn }
change: { enabled: true, action: warn }
secrets: { enabled: true, action: block }
crypto: { enabled: true, action: block }
iam: { enabled: true, action: warn }
sbom: { enabled: true, action: warn }
iac: { enabled: true, action: block }
input_validation: { enabled: true, action: block }
audit: { enabled: true, action: warn }
change_control: { enabled: true, action: warn }
deps: { enabled: true, action: warn }
api: { enabled: true, action: warn }
privacy: { enabled: true, action: warn }
resilience: { enabled: true, action: warn }
incident: { enabled: true, action: warn }
observability: { enabled: true, action: warn }
memsafe: { enabled: true, action: warn }
license: { enabled: true, action: warn }
aiml: { enabled: true, action: warn }
container: { enabled: true, action: warn }

thresholds:
block_on: [CRITICAL, HIGH]
Expand All @@ -106,16 +131,25 @@ thresholds:

exclusions:
paths: ["tests/**", "docs/**", "*.md"]

full_scan:
extensions: [.py, .js, .ts, .go, .tf, .yaml, .yml, .json, .sh]
skip_dirs: [.git, node_modules, .venv, dist, build]
```

## CLI Usage

```bash
# Bootstrap project
controlgate init
controlgate init --baseline high --no-docs

# Scan staged changes (pre-commit mode)
controlgate scan --mode pre-commit --format markdown

# Scan explicitly against FedRAMP baselines (pre-commit mode)
controlgate scan --gov --baseline moderate --mode pre-commit --format markdown
# Full repository scan
controlgate scan --mode full --format markdown
controlgate scan --mode full --path ./src --format json

# Scan PR diff
controlgate scan --mode pr --target-branch main --format json markdown sarif
Expand All @@ -126,11 +160,12 @@ controlgate scan --gov --baseline high --mode pr --target-branch main --format j
# Scan a saved diff file
controlgate scan --diff-file path/to/diff --format json

# Scan a saved diff file against FedRAMP baselines
controlgate scan --gov --baseline li-saas --diff-file path/to/diff --format json

# Output reports to directory
controlgate scan --output-dir .controlgate/reports --format json markdown sarif

# Catalog management
controlgate update-catalog
controlgate catalog-info
```

## Output Formats
Expand Down Expand Up @@ -168,7 +203,7 @@ The agent prompts and workflows are located in the [`skills/`](skills/) director
## Test Suite

To validate the capabilities of ControlGate, we maintain a standalone test suite at [sadayamuthu/controlgate-test-suite](https://github.com/sadayamuthu/controlgate-test-suite).
This suite contains intentionally vulnerable projects spanning multiple languages and frameworks, specifically designed to trigger each of the 8 Security Gates. It is automatically executed in the CI pipeline to ensure zero regression in detection capabilities.
This suite contains intentionally vulnerable projects spanning multiple languages and frameworks, specifically designed to trigger each of the 18 Security Gates. It is automatically executed in the CI pipeline to ensure zero regression in detection capabilities.

## Data Source

Expand Down
58 changes: 58 additions & 0 deletions docs/gates/gate-01-secrets/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Gate 1 — Secrets & Credential Gate

**gate_id:** `secrets`
**NIST Controls:** IA-5, IA-6, SC-12, SC-28
**Priority:** 🔴 High

---

## Purpose

Prevents hardcoded secrets, API keys, tokens, and private keys from being committed to source control. Credentials committed to git are permanently exposed in history, even after removal, and are a leading cause of cloud account compromise. This gate provides an automated pre-commit tripwire for the most common credential formats used across AWS, GCP, GitHub, OpenAI, Stripe, and database connection strings.

---

## What This Gate Detects

| Detection | Why It Matters | NIST Control |
|---|---|---|
| AWS Access Key ID (AKIA/ASIA format) | Direct cloud account takeover | IA-5 |
| AWS Secret Access Key (40-char base64) | Paired with key ID enables full AWS API access | IA-5 |
| Google API Key (AIza prefix) | Unauthorized GCP service usage and billing fraud | IA-5 |
| Hardcoded credential assignment (`password =`, `token =`, etc.) | Generic pattern catches language-agnostic credential leaks | SC-28 |
| Private key files (RSA, EC, DSA, OpenSSH) | Key compromise enables impersonation and decryption of historical traffic | SC-12 |
| X.509 certificate files | Certificates in repos risk unauthorized service impersonation | SC-12 |
| GitHub Personal Access Tokens (ghp_ prefix) | Repo access, Actions secrets, and org data at risk | IA-5 |
| API secret keys (sk- prefix) | OpenAI/Stripe-style keys enabling fraudulent API usage | IA-5 |
| Bearer tokens in source code | Runtime tokens should not appear in code | IA-6 |
| Database connection strings with embedded credentials | Leaks DB host, port, username, and password | SC-28 |
| High-entropy quoted strings ≥20 chars | Catches randomized secrets not matching known formats | IA-5 |
| Sensitive file types committed (.env, .pem, .key, .p12, .pfx, .jks) | Entire file classes should never appear in source control | SC-28 |

---

## Scope

- **Scans:** all added lines in every file in the diff
- **File types targeted:** all files; additionally performs file-path checks for sensitive file extensions
- **Special detection:** Shannon entropy analysis — any quoted string ≥20 characters with entropy ≥4.5 bits/char is flagged even if it doesn't match a known pattern. Evidence is truncated to 120 characters.

---

## Known Limitations

- Does not scan deleted or unmodified lines
- Entropy detection produces false positives on long base64-encoded non-secret values (e.g., public keys, checksums)
- Known secret formats are a subset of real-world credential types; novel formats require new patterns
- Will not detect secrets stored in binary files

---

## NIST Control Mapping

| Control ID | Title | How This Gate Addresses It |
|---|---|---|
| IA-5 | Authenticator Management | Detects hardcoded passwords, tokens, and API keys that should be managed through a secrets manager |
| IA-6 | Authentication Feedback | Detects bearer tokens embedded in source code where they may be logged or exposed |
| SC-12 | Cryptographic Key Establishment and Management | Detects private keys and certificates committed to repositories |
| SC-28 | Protection of Information at Rest | Detects credentials and sensitive file types that expose data-at-rest protection keys |
73 changes: 73 additions & 0 deletions docs/gates/gate-01-secrets/implementation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Gate 1 — Secrets & Credential Gate: Implementation Reference

**Source file:** `src/controlgate/gates/secrets_gate.py`
**Test file:** `tests/test_gates/test_secrets_gate.py`
**Class:** `SecretsGate`
**gate_id:** `secrets`
**mapped_control_ids:** `["IA-5", "IA-6", "SC-12", "SC-28"]`

---

## Scan Method

`scan()` iterates every `diff_file` and calls two sub-methods:
1. `_check_sensitive_file()` — matches the file path against `_SENSITIVE_FILE_PATTERNS`; fires one SC-28 finding per file if the path matches (breaks after first match per file)
2. `_check_line()` — for each added line, runs all `_PATTERNS` regex matches, then runs Shannon entropy analysis on any quoted string ≥20 chars

---

## Patterns

| # | Regex | Description | Control | Remediation |
|---|---|---|---|---|
| 1 | `(?:AKIA\|ASIA)[0-9A-Z]{16}` | AWS Access Key ID detected | IA-5 | Use IAM roles or AWS Secrets Manager instead of hardcoded keys |
| 2 | `(?:"\|')(?:[A-Za-z0-9/+=]{40})(?:"\|')` | Possible AWS Secret Access Key detected | IA-5 | Use IAM roles or AWS Secrets Manager instead of hardcoded keys |
| 3 | `AIza[0-9A-Za-z\-_]{35}` | Google API Key detected | IA-5 | Use GCP Secret Manager or environment variables |
| 4 | `(?i)(?:password\|passwd\|pwd\|secret\|token\|api[_-]?key\|auth[_-]?token\|access[_-]?token)\s*[:=]\s*["'][^"']{4,}["']` | Hardcoded credential detected | SC-28 | Move to environment variable or secrets manager (AWS SSM, GCP Secret Manager, Azure Key Vault) |
| 5 | `(?i)(?:password\|passwd\|pwd\|secret\|token\|api[_-]?key)\s*=\s*(?!None\|null\|""\|''\|os\.environ\|env\(\|getenv)[^\s#]{4,}` | Hardcoded credential in assignment | SC-28 | Move to environment variable or secrets manager |
| 6 | `-----BEGIN (?:RSA \|EC \|DSA \|OPENSSH )?PRIVATE KEY-----` | Private key committed to repository | SC-12 | Never commit private keys. Use a secrets manager or secure key storage |
| 7 | `-----BEGIN CERTIFICATE-----` | Certificate file committed to repository | SC-12 | Manage certificates through a PKI or secrets manager, not source control |
| 8 | `ghp_[0-9a-zA-Z]{36}` | GitHub Personal Access Token detected | IA-5 | Use GitHub Apps or GITHUB_TOKEN instead of personal access tokens |
| 9 | `sk-[0-9a-zA-Z]{20,}` | API secret key detected (OpenAI/Stripe pattern) | IA-5 | Use environment variables or a secrets manager for API keys |
| 10 | `(?i)bearer\s+[a-z0-9\-._~+/]+=*` | Bearer token detected in source code | IA-6 | Tokens should be loaded from environment or config, not hardcoded |
| 11 | `(?i)(?:mongodb\|postgres(?:ql)?\|mysql\|redis\|amqp)://[^\s:]+:[^\s@]+@` | Database connection string with embedded credentials | SC-28 | Use environment variables for connection strings with credentials |

**Sensitive file path patterns** (checked against `diff_file.path`, fires SC-28):

| Pattern | Matches |
|---|---|
| `\.env(?:\..+)?$` | `.env`, `.env.prod`, `.env.local`, etc. |
| `(?i)credentials` | Any file with "credentials" in name |
| `(?i)\.pem$` | PEM certificate/key files |
| `(?i)\.key$` | Key files |
| `(?i)\.p12$` | PKCS#12 key stores |
| `(?i)\.pfx$` | Personal Information Exchange files |
| `(?i)\.jks$` | Java KeyStore files |

---

## Special Detection Logic

**Shannon entropy analysis** — runs after the pattern loop in `_check_line()`:

1. Scans the line for quoted strings matching `["']([A-Za-z0-9+/=\-_]{20,})["']`
2. For each candidate token of length ≥20: computes Shannon entropy (bits per character)
3. If entropy ≥ 4.5 AND no finding from this gate already exists for that line number, fires an IA-5 finding
4. The duplicate-check prevents double-firing when a pattern already matched the same line

Constants: `_ENTROPY_THRESHOLD = 4.5`, `_MIN_LENGTH_FOR_ENTROPY = 20`

---

## Test Coverage

| Test | What It Verifies |
|---|---|
| `test_detects_aws_key` | AKIA/ASIA format AWS access key triggers an IA-5 finding with "AWS" in the description |
| `test_detects_hardcoded_password` | `DB_PASSWORD = "super_secret_123"` assignment triggers a finding with "credential" or "password" in the description |
| `test_detects_private_key` | `-----BEGIN RSA PRIVATE KEY-----` header triggers a finding with "key" in the description |
| `test_clean_code_no_findings` | Code that reads credentials from `os.environ` produces zero findings |
| `test_detects_database_uri` | `postgres://user:pass@host/db` connection string triggers a finding with "connection string" or "credential" in the description |
| `test_detects_github_token` | `ghp_…` GitHub Personal Access Token pattern triggers at least one finding |
| `test_findings_have_gate_id` | Every finding from the AWS-key diff carries `gate == "secrets"` |
| `test_findings_have_control_ids` | Every finding from the AWS-key diff uses a control ID within `{IA-5, IA-6, SC-12, SC-28}` |
Loading