proofctl 0.4.0__tar.gz → 0.4.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. {proofctl-0.4.0 → proofctl-0.4.2}/LICENSE +1 -1
  2. proofctl-0.4.2/MANIFEST.in +19 -0
  3. proofctl-0.4.2/PKG-INFO +352 -0
  4. proofctl-0.4.2/README.md +324 -0
  5. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/security.py +50 -0
  6. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/terraform.py +69 -2
  7. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/cli.py +21 -0
  8. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/config.py +31 -0
  9. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/engine.py +88 -0
  10. proofctl-0.4.2/proofctl.egg-info/PKG-INFO +352 -0
  11. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl.egg-info/SOURCES.txt +2 -33
  12. {proofctl-0.4.0 → proofctl-0.4.2}/pyproject.toml +1 -6
  13. proofctl-0.4.0/PKG-INFO +0 -527
  14. proofctl-0.4.0/README.md +0 -496
  15. proofctl-0.4.0/proofctl.egg-info/PKG-INFO +0 -527
  16. proofctl-0.4.0/tests/test_baseline.py +0 -133
  17. proofctl-0.4.0/tests/test_config_proofctl.py +0 -133
  18. proofctl-0.4.0/tests/test_dockerfile.py +0 -473
  19. proofctl-0.4.0/tests/test_engine.py +0 -156
  20. proofctl-0.4.0/tests/test_fixer.py +0 -163
  21. proofctl-0.4.0/tests/test_imports.py +0 -312
  22. proofctl-0.4.0/tests/test_leakage.py +0 -179
  23. proofctl-0.4.0/tests/test_llm.py +0 -279
  24. proofctl-0.4.0/tests/test_local_packages.py +0 -239
  25. proofctl-0.4.0/tests/test_phase1_audit_fixes.py +0 -176
  26. proofctl-0.4.0/tests/test_phase2_audit_fixes.py +0 -311
  27. proofctl-0.4.0/tests/test_phase3_audit_fixes.py +0 -305
  28. proofctl-0.4.0/tests/test_phase4_audit_fixes.py +0 -416
  29. proofctl-0.4.0/tests/test_phase5_llm_imports_fixes.py +0 -306
  30. proofctl-0.4.0/tests/test_phase5_p_l_v_fixes.py +0 -279
  31. proofctl-0.4.0/tests/test_phase5_quality_fixes.py +0 -240
  32. proofctl-0.4.0/tests/test_phase6_audit_fixes.py +0 -359
  33. proofctl-0.4.0/tests/test_phase8_audit_fixes.py +0 -328
  34. proofctl-0.4.0/tests/test_placeholders.py +0 -239
  35. proofctl-0.4.0/tests/test_quality.py +0 -595
  36. proofctl-0.4.0/tests/test_quality_ext.py +0 -286
  37. proofctl-0.4.0/tests/test_secrets.py +0 -512
  38. proofctl-0.4.0/tests/test_security.py +0 -509
  39. proofctl-0.4.0/tests/test_security_ext.py +0 -476
  40. proofctl-0.4.0/tests/test_security_external.py +0 -531
  41. proofctl-0.4.0/tests/test_suppression.py +0 -137
  42. proofctl-0.4.0/tests/test_terraform.py +0 -861
  43. proofctl-0.4.0/tests/test_terraform_ext.py +0 -2806
  44. proofctl-0.4.0/tests/test_terragrunt.py +0 -313
  45. proofctl-0.4.0/tests/test_variants.py +0 -136
  46. proofctl-0.4.0/tests/test_yaml.py +0 -469
  47. proofctl-0.4.0/tests/test_yaml_k8s_gha.py +0 -1387
  48. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/__init__.py +0 -0
  49. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/_globmatch.py +0 -0
  50. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/baseline.py +0 -0
  51. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/__init__.py +0 -0
  52. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/base.py +0 -0
  53. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/dockerfile.py +0 -0
  54. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/hcl_utils.py +0 -0
  55. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/imports.py +0 -0
  56. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/leakage.py +0 -0
  57. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/llm_integration.py +0 -0
  58. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/placeholders.py +0 -0
  59. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/quality.py +0 -0
  60. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/secrets.py +0 -0
  61. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/shell_checker.py +0 -0
  62. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/terragrunt.py +0 -0
  63. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/variants.py +0 -0
  64. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/checkers/yaml_checker.py +0 -0
  65. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/fixer.py +0 -0
  66. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/models.py +0 -0
  67. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/registry.py +0 -0
  68. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/reporters/__init__.py +0 -0
  69. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/reporters/html_reporter.py +0 -0
  70. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/reporters/json_reporter.py +0 -0
  71. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl/reporters/terminal.py +0 -0
  72. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl.egg-info/dependency_links.txt +0 -0
  73. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl.egg-info/entry_points.txt +0 -0
  74. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl.egg-info/requires.txt +0 -0
  75. {proofctl-0.4.0 → proofctl-0.4.2}/proofctl.egg-info/top_level.txt +0 -0
  76. {proofctl-0.4.0 → proofctl-0.4.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Kolawolu Odunola
3
+ Copyright (c) 2025-2026 Kolawolu Odunola
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,19 @@
1
+ graft proofctl
2
+ include README.md
3
+ include LICENSE
4
+ include pyproject.toml
5
+
6
+ # Internal-only — never ship to PyPI
7
+ prune tests
8
+ prune doc
9
+ prune docs
10
+ prune examples
11
+ prune build
12
+ prune dist
13
+ prune .github
14
+ exclude AUDIT_AND_ROADMAP.md
15
+ exclude AUDIT_VERIFICATION_v0.1.11.md
16
+
17
+ global-exclude __pycache__
18
+ global-exclude *.py[cod]
19
+ global-exclude .DS_Store
@@ -0,0 +1,352 @@
1
+ Metadata-Version: 2.4
2
+ Name: proofctl
3
+ Version: 0.4.2
4
+ Summary: Zero-dependency linter for Python, Terraform, Dockerfiles, Kubernetes, and GitHub Actions — catches AI slop and security misconfigurations pre-commit
5
+ Author-email: Kolawolu Odunola <kolawolu.o@gmail.com>
6
+ License: MIT
7
+ Keywords: linter,security,terraform,kubernetes,ai,static-analysis,pre-commit
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Environment :: Console
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Software Development :: Quality Assurance
17
+ Classifier: Topic :: Security
18
+ Requires-Python: >=3.11
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: typer[all]>=0.12
22
+ Requires-Dist: rich>=13
23
+ Requires-Dist: pyyaml>=6
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=8; extra == "dev"
26
+ Requires-Dist: pytest-mock>=3; extra == "dev"
27
+ Dynamic: license-file
28
+
29
+ # proofctl
30
+
31
+ A linter built for the DevOps stack — Python, Terraform, Kubernetes, Helm, Dockerfiles, GitHub Actions, Shell — that catches the specific kinds of mistakes AI coding tools introduce. **264 rules**, zero dependencies, runs in under a second.
32
+
33
+ ```
34
+ proofctl check .
35
+ ```
36
+
37
+ ```
38
+ PROOFCTL-S-001 module/auth.py:42 SQL injection via string format in .execute() ERROR
39
+ PROOFCTL-Q-001 module/models.py:17 Mutable default argument — list assigned at def time ERROR
40
+ PROOFCTL-S-AI-006 module/loaders.py:88 Empty `except Exception:` swallows all errors silently WARNING
41
+ PROOFCTL-TF-A024 infra/sg.tf:14 SG rule 0.0.0.0/0 ingress on port 22 ERROR
42
+ PROOFCTL-YAML-022 k8s/deployment.yaml:8 Workload uses default namespace WARNING
43
+ PROOFCTL-YAML-007 .github/workflows/release.yml:23 Action not pinned to SHA ERROR
44
+ PROOFCTL-SECRET-001 infra/lambda.tf:8 AWS access key (AKIA...) ERROR
45
+ ──────────────────────────────────────────────────────────────────
46
+ 7 findings (4 ERROR, 3 WARNING) — exit 2
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Why proofctl
52
+
53
+ LLM coding assistants ship code that compiles and looks correct but fails in predictable ways:
54
+
55
+ - **Insecure** — SQL/command injection, hardcoded credentials, weak crypto, JWT signature bypass, public S3 buckets, K8s default namespaces.
56
+ - **Broken** — hallucinated imports, phantom methods, type-hint vs implementation mismatch, `pass`-bodied functions shipped as real implementations.
57
+ - **Fragile** — broad `except Exception:`, no timeouts, mutable defaults, defensive guards for impossible states, unused configuration kwargs.
58
+ - **Wasteful** — single-method classes that should be functions, near-duplicate files, sprawling kwargs surface.
59
+
60
+ proofctl runs as a pre-commit linter and catches these patterns before they merge. The top-firing rules on real AI-authored code are **Q-002 broad except**, **Q-005 complexity**, **Q-006 long functions**, **YAML-007 / YAML-GHA-006 GitHub Actions hygiene**, and **YAML-GHA-003 missing permissions**.
61
+
62
+ ---
63
+
64
+ ## What proofctl scans
65
+
66
+ | Language | What it catches |
67
+ |---|---|
68
+ | Python | Security (SQLi, injection, eval, JWT bypass, weak crypto), quality (mutable defaults, broad except, complexity, long functions), AI-slop patterns (echo docstrings, single-method classes, stale kwargs), import hallucinations |
69
+ | Terraform / HCL | AWS / GCP / Azure resource hardening (200+ rules across IAM, encryption, public exposure, audit logs), AI-slop patterns (deprecated resources, AWS region in GCP, placeholder values), required_version, sensitive outputs |
70
+ | Kubernetes YAML | Pod Security Standards (runAsNonRoot, allowPrivilegeEscalation, readOnlyRootFilesystem, drop ALL caps, seccomp), data-exfiltration vectors (default namespace, hostPath, low UID, RBAC wildcards, automountServiceAccountToken), image hygiene (latest tag, digest pinning) |
71
+ | Helm / Mustache | Same K8s checks via Helm-templated YAML |
72
+ | Dockerfile | USER, base image pinning, secret leakage, root-running, OCI labels, HEALTHCHECK, AI-generated antipatterns |
73
+ | GitHub Actions | SHA-pinning, expression injection, missing permissions, missing timeouts, secret env-var leakage |
74
+ | Shell | Common mistake detection (set -euo, dangerous globbing) |
75
+ | Secrets (any text file) | AWS / GCP / GitHub / Slack / Stripe / private keys / JWTs / hardcoded passwords / K8s Secret YAML / HCL heredocs |
76
+
77
+ ---
78
+
79
+ ## Installation
80
+
81
+ ```bash
82
+ pip install proofctl
83
+ ```
84
+
85
+ **Requires:** Python 3.11+
86
+
87
+ No project dependencies are added — proofctl only scans, never imports your code.
88
+
89
+ ---
90
+
91
+ ## Quick start
92
+
93
+ ```bash
94
+ proofctl check . # scan current directory
95
+ proofctl check src/api/auth.py # scan a single file
96
+ proofctl check . --min-severity ERROR # only show ERROR
97
+ proofctl check . --fail-on ERROR # CI gate: exit non-zero only on ERROR
98
+ proofctl check . --changed-only # only files changed in this branch
99
+ proofctl check . --families S,Q,SECRET # restrict rule families
100
+ proofctl check . --format html --output report.html
101
+ proofctl rules # list all rules
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Pre-commit integration
107
+
108
+ Install proofctl from PyPI, then add a local hook in `.pre-commit-config.yaml`:
109
+
110
+ ```yaml
111
+ repos:
112
+ - repo: local
113
+ hooks:
114
+ - id: proofctl
115
+ name: proofctl
116
+ language: system
117
+ entry: proofctl check
118
+ args: [--no-pypi, --fail-on, ERROR]
119
+ pass_filenames: false
120
+ ```
121
+
122
+ ---
123
+
124
+ ## CI integration (GitHub Actions)
125
+
126
+ ```yaml
127
+ name: proofctl
128
+ on: [push, pull_request]
129
+
130
+ jobs:
131
+ proofctl:
132
+ runs-on: ubuntu-latest
133
+ steps:
134
+ - uses: actions/checkout@v4
135
+ - uses: actions/setup-python@v5
136
+ with:
137
+ python-version: "3.12"
138
+ - run: pip install proofctl
139
+
140
+ # --new-only compares against the committed baseline snapshot —
141
+ # CI fails only on regressions introduced in this PR.
142
+ - run: proofctl check . --no-pypi --fail-on ERROR --new-only
143
+
144
+ - name: Generate HTML report
145
+ if: failure()
146
+ run: proofctl check . --no-pypi --format html --output proofctl-report.html || true
147
+
148
+ - uses: actions/upload-artifact@v4
149
+ if: failure()
150
+ with:
151
+ name: proofctl-report
152
+ path: proofctl-report.html
153
+ retention-days: 14
154
+ ```
155
+
156
+ Create a baseline snapshot for an existing project so CI only flags regressions:
157
+
158
+ ```bash
159
+ proofctl baseline .
160
+ git add .proofctl-baseline.json
161
+ git commit -m "chore: add proofctl baseline"
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Rules
167
+
168
+ 264 rules across 14 families. Run `proofctl rules` after install to enumerate.
169
+
170
+ | Family | Count | What it covers |
171
+ |---|---|---|
172
+ | Python — Quality (`Q`) | 17 | Mutable defaults, broad `except`, complexity, long functions, AI-slop patterns (echo docstrings, single-method classes, stale kwargs, defensive guards) |
173
+ | Python — Security (`S`) | 24 | OWASP Top-10 + CWE coverage: SQLi, command injection, weak crypto, JWT bypass, path traversal, XSS, SSRF, file upload, CSRF, missing authz, XPath injection, open redirect, TLS bypass |
174
+ | Secrets (`SECRET`) | 13 | AWS / GCP / GitHub / Slack / Stripe / private keys / JWTs / hardcoded passwords / K8s Secret YAML / connection strings with embedded creds |
175
+ | Python — Other | 12 | Placeholders, leakage (cross-language idioms, PII), import hallucination, method complexity, variant detection, LLM guardrails (OWASP LLM Top-10) |
176
+ | Terraform — General + AI (`TF-T`, `TF-AI`) | 26 | required_version, sensitive outputs, IAM wildcards, mutable git refs, deprecated resources, AWS-region-in-GCP, placeholder values |
177
+ | Terraform — AWS (`TF-A`) | 40 | EC2 IMDSv2, S3 public-access-block, EBS encryption, VPC flow logs, KMS rotation, RDS hardening, SG / NACL / EKS / DynamoDB / ElastiCache / CloudTrail / IAM |
178
+ | Terraform — GCP (`TF-G`) | 50 | GKE hardening, GCS public-access prevention, IAM roles, KMS rotation, Cloud Function/Run public, BigQuery, Pub/Sub CMEK, Cloud SQL, firewall ingress |
179
+ | Terraform — Azure (`TF-AZ`) | 14 | Storage public blob, SQL public network, AKS RBAC, Key Vault purge protection, NSG SSH/RDP, managed disk CMK |
180
+ | Terraform — Mechanics + Lifecycle (`TF-M`, `TF-V`) | 12 | SG inline mixing, `force_destroy`, mutable module refs, lifecycle antipatterns |
181
+ | Terragrunt (`TG`) | 6 | HCL inputs, mock_outputs, remote state encryption |
182
+ | Dockerfile (`DF`) | 15 | Latest tag, root user, secret leakage, OCI labels, HEALTHCHECK, legacy ENV form |
183
+ | Kubernetes YAML (`YAML`) | 26 | Pod Security Standards, hostPath, default namespace, image digest pinning, RBAC wildcards |
184
+ | GitHub Actions (`YAML-GHA`) | — | SHA pinning, expression injection, missing permissions, secret env-var leakage, missing timeouts |
185
+ | Shell (`SH`) | 8 | Dangerous globbing, missing `set -euo pipefail` |
186
+
187
+ ```bash
188
+ proofctl rules # full list
189
+ proofctl rules --family S # filter by family
190
+ proofctl rules --severity ERROR
191
+ ```
192
+
193
+ ---
194
+
195
+ ## Suppressing findings
196
+
197
+ Inline (single line):
198
+
199
+ ```python
200
+ result = subprocess.run(cmd, shell=True) # proofctl: ignore[PROOFCTL-S-002]
201
+ ```
202
+
203
+ ```hcl
204
+ resource "aws_s3_bucket" "logs" {
205
+ acl = "public-read" # proofctl: ignore[PROOFCTL-TF-AI-003] // or # comment style
206
+ }
207
+ ```
208
+
209
+ Project-wide in `.proofctl.yaml`:
210
+
211
+ ```yaml
212
+ disable:
213
+ - PROOFCTL-Q-004
214
+ ```
215
+
216
+ ---
217
+
218
+ ## Configuration
219
+
220
+ Place `.proofctl.yaml` in the project root:
221
+
222
+ ```yaml
223
+ exclude_paths:
224
+ - "**/.venv/**"
225
+ - "**/migrations/**"
226
+ - "**/.terraform/**"
227
+
228
+ disable:
229
+ - PROOFCTL-Q-004
230
+ - PROOFCTL-DF-AI-002
231
+
232
+ severity_overrides:
233
+ PROOFCTL-P-002: ERROR # promote TODOs to ERROR
234
+
235
+ rules:
236
+ PROOFCTL-P-002:
237
+ allowed_formats:
238
+ - 'TODO\(#\d+\)' # allow TODO(#123) format
239
+ exclude_paths:
240
+ - tests/
241
+
242
+ PROOFCTL-Q-003:
243
+ any_threshold: 5
244
+
245
+ PROOFCTL-V-002:
246
+ similarity_threshold: 0.85
247
+ min_file_lines: 30
248
+
249
+ PROOFCTL-I-001:
250
+ local_namespaces:
251
+ - mycompany_
252
+ - internal_
253
+
254
+ PROOFCTL-TF-T013:
255
+ required_labels:
256
+ - environment
257
+ - team
258
+ - cost_center
259
+
260
+ # Substrings that mark a line as legitimate private infra. Findings from
261
+ # "name-shaped" rules (SECRET-*, TF-T005, TF-AI-001, DF-AI-*, Q-AI-*) on a
262
+ # line containing any of these tokens are silently dropped. Real
263
+ # code-shape security rules (S-001 SQLi, S-005 eval, etc.) keep firing.
264
+ internal_identifiers:
265
+ - mycompany-prod # internal hostname prefix
266
+ - mycompany.internal # internal DNS suffix
267
+ - INTERNAL_PROJECT_NAME # codename that sometimes looks like a placeholder
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Commands
273
+
274
+ ### `proofctl check`
275
+
276
+ ```
277
+ proofctl check [PATH] [OPTIONS]
278
+
279
+ Options:
280
+ --format / -f terminal | json | html (default: terminal)
281
+ --output / -o Write report to file
282
+ --changed-only Only scan git-changed files
283
+ --families P,Q,S,L,I,M,V,LLM,TF,TG,DF,YAML,SH,SECRET
284
+ --min-severity INFO | WARNING | ERROR
285
+ --fail-on Exit non-zero at this severity (default: WARNING)
286
+ --no-pypi Skip PyPI lookups (faster, works offline)
287
+ --new-only Suppress findings present in .proofctl-baseline.json
288
+ --fix Auto-fix fixable findings (Q-001 mutable defaults)
289
+ ```
290
+
291
+ ### `proofctl baseline`
292
+
293
+ Snapshot the current findings so future `--new-only` runs only surface regressions.
294
+
295
+ ```bash
296
+ proofctl baseline .
297
+ git add .proofctl-baseline.json && git commit -m "chore: proofctl baseline"
298
+ ```
299
+
300
+ ### `proofctl rules`
301
+
302
+ ```bash
303
+ proofctl rules # list all
304
+ proofctl rules --family S # filter by family
305
+ proofctl rules --severity ERROR
306
+ ```
307
+
308
+ ---
309
+
310
+ ## Exit codes
311
+
312
+ | Code | Meaning |
313
+ |------|---------|
314
+ | `0` | No findings |
315
+ | `1` | Findings present, none at or above `--fail-on` threshold |
316
+ | `2` | One or more findings at or above `--fail-on` threshold |
317
+
318
+ ---
319
+
320
+ ## Output formats
321
+
322
+ **Terminal** (default) — rich-coloured table with file:line, rule, severity, hint.
323
+
324
+ **JSON** — machine-readable for CI:
325
+
326
+ ```json
327
+ {
328
+ "schema_version": 1,
329
+ "summary": { "total": 4, "ERROR": 3, "WARNING": 1 },
330
+ "findings": [
331
+ {
332
+ "file": "module/auth.py",
333
+ "line": 42,
334
+ "col": 8,
335
+ "rule_id": "PROOFCTL-S-001",
336
+ "rule_name": "SQL injection",
337
+ "severity": "ERROR",
338
+ "message": "SQL injection via string format in .execute()",
339
+ "hint": "Use parameterised queries: cursor.execute(sql, params)",
340
+ "authority": "OWASP A03:2021, CWE-89"
341
+ }
342
+ ]
343
+ }
344
+ ```
345
+
346
+ **HTML** — self-contained single-file dashboard with severity summary cards and a filterable table.
347
+
348
+ ---
349
+
350
+ ## License
351
+
352
+ MIT
@@ -0,0 +1,324 @@
1
+ # proofctl
2
+
3
+ A linter built for the DevOps stack — Python, Terraform, Kubernetes, Helm, Dockerfiles, GitHub Actions, Shell — that catches the specific kinds of mistakes AI coding tools introduce. **264 rules**, zero dependencies, runs in under a second.
4
+
5
+ ```
6
+ proofctl check .
7
+ ```
8
+
9
+ ```
10
+ PROOFCTL-S-001 module/auth.py:42 SQL injection via string format in .execute() ERROR
11
+ PROOFCTL-Q-001 module/models.py:17 Mutable default argument — list assigned at def time ERROR
12
+ PROOFCTL-S-AI-006 module/loaders.py:88 Empty `except Exception:` swallows all errors silently WARNING
13
+ PROOFCTL-TF-A024 infra/sg.tf:14 SG rule 0.0.0.0/0 ingress on port 22 ERROR
14
+ PROOFCTL-YAML-022 k8s/deployment.yaml:8 Workload uses default namespace WARNING
15
+ PROOFCTL-YAML-007 .github/workflows/release.yml:23 Action not pinned to SHA ERROR
16
+ PROOFCTL-SECRET-001 infra/lambda.tf:8 AWS access key (AKIA...) ERROR
17
+ ──────────────────────────────────────────────────────────────────
18
+ 7 findings (4 ERROR, 3 WARNING) — exit 2
19
+ ```
20
+
21
+ ---
22
+
23
+ ## Why proofctl
24
+
25
+ LLM coding assistants ship code that compiles and looks correct but fails in predictable ways:
26
+
27
+ - **Insecure** — SQL/command injection, hardcoded credentials, weak crypto, JWT signature bypass, public S3 buckets, K8s default namespaces.
28
+ - **Broken** — hallucinated imports, phantom methods, type-hint vs implementation mismatch, `pass`-bodied functions shipped as real implementations.
29
+ - **Fragile** — broad `except Exception:`, no timeouts, mutable defaults, defensive guards for impossible states, unused configuration kwargs.
30
+ - **Wasteful** — single-method classes that should be functions, near-duplicate files, sprawling kwargs surface.
31
+
32
+ proofctl runs as a pre-commit linter and catches these patterns before they merge. The top-firing rules on real AI-authored code are **Q-002 broad except**, **Q-005 complexity**, **Q-006 long functions**, **YAML-007 / YAML-GHA-006 GitHub Actions hygiene**, and **YAML-GHA-003 missing permissions**.
33
+
34
+ ---
35
+
36
+ ## What proofctl scans
37
+
38
+ | Language | What it catches |
39
+ |---|---|
40
+ | Python | Security (SQLi, injection, eval, JWT bypass, weak crypto), quality (mutable defaults, broad except, complexity, long functions), AI-slop patterns (echo docstrings, single-method classes, stale kwargs), import hallucinations |
41
+ | Terraform / HCL | AWS / GCP / Azure resource hardening (200+ rules across IAM, encryption, public exposure, audit logs), AI-slop patterns (deprecated resources, AWS region in GCP, placeholder values), required_version, sensitive outputs |
42
+ | Kubernetes YAML | Pod Security Standards (runAsNonRoot, allowPrivilegeEscalation, readOnlyRootFilesystem, drop ALL caps, seccomp), data-exfiltration vectors (default namespace, hostPath, low UID, RBAC wildcards, automountServiceAccountToken), image hygiene (latest tag, digest pinning) |
43
+ | Helm / Mustache | Same K8s checks via Helm-templated YAML |
44
+ | Dockerfile | USER, base image pinning, secret leakage, root-running, OCI labels, HEALTHCHECK, AI-generated antipatterns |
45
+ | GitHub Actions | SHA-pinning, expression injection, missing permissions, missing timeouts, secret env-var leakage |
46
+ | Shell | Common mistake detection (set -euo, dangerous globbing) |
47
+ | Secrets (any text file) | AWS / GCP / GitHub / Slack / Stripe / private keys / JWTs / hardcoded passwords / K8s Secret YAML / HCL heredocs |
48
+
49
+ ---
50
+
51
+ ## Installation
52
+
53
+ ```bash
54
+ pip install proofctl
55
+ ```
56
+
57
+ **Requires:** Python 3.11+
58
+
59
+ No project dependencies are added — proofctl only scans, never imports your code.
60
+
61
+ ---
62
+
63
+ ## Quick start
64
+
65
+ ```bash
66
+ proofctl check . # scan current directory
67
+ proofctl check src/api/auth.py # scan a single file
68
+ proofctl check . --min-severity ERROR # only show ERROR
69
+ proofctl check . --fail-on ERROR # CI gate: exit non-zero only on ERROR
70
+ proofctl check . --changed-only # only files changed in this branch
71
+ proofctl check . --families S,Q,SECRET # restrict rule families
72
+ proofctl check . --format html --output report.html
73
+ proofctl rules # list all rules
74
+ ```
75
+
76
+ ---
77
+
78
+ ## Pre-commit integration
79
+
80
+ Install proofctl from PyPI, then add a local hook in `.pre-commit-config.yaml`:
81
+
82
+ ```yaml
83
+ repos:
84
+ - repo: local
85
+ hooks:
86
+ - id: proofctl
87
+ name: proofctl
88
+ language: system
89
+ entry: proofctl check
90
+ args: [--no-pypi, --fail-on, ERROR]
91
+ pass_filenames: false
92
+ ```
93
+
94
+ ---
95
+
96
+ ## CI integration (GitHub Actions)
97
+
98
+ ```yaml
99
+ name: proofctl
100
+ on: [push, pull_request]
101
+
102
+ jobs:
103
+ proofctl:
104
+ runs-on: ubuntu-latest
105
+ steps:
106
+ - uses: actions/checkout@v4
107
+ - uses: actions/setup-python@v5
108
+ with:
109
+ python-version: "3.12"
110
+ - run: pip install proofctl
111
+
112
+ # --new-only compares against the committed baseline snapshot —
113
+ # CI fails only on regressions introduced in this PR.
114
+ - run: proofctl check . --no-pypi --fail-on ERROR --new-only
115
+
116
+ - name: Generate HTML report
117
+ if: failure()
118
+ run: proofctl check . --no-pypi --format html --output proofctl-report.html || true
119
+
120
+ - uses: actions/upload-artifact@v4
121
+ if: failure()
122
+ with:
123
+ name: proofctl-report
124
+ path: proofctl-report.html
125
+ retention-days: 14
126
+ ```
127
+
128
+ Create a baseline snapshot for an existing project so CI only flags regressions:
129
+
130
+ ```bash
131
+ proofctl baseline .
132
+ git add .proofctl-baseline.json
133
+ git commit -m "chore: add proofctl baseline"
134
+ ```
135
+
136
+ ---
137
+
138
+ ## Rules
139
+
140
+ 264 rules across 14 families. Run `proofctl rules` after install to enumerate.
141
+
142
+ | Family | Count | What it covers |
143
+ |---|---|---|
144
+ | Python — Quality (`Q`) | 17 | Mutable defaults, broad `except`, complexity, long functions, AI-slop patterns (echo docstrings, single-method classes, stale kwargs, defensive guards) |
145
+ | Python — Security (`S`) | 24 | OWASP Top-10 + CWE coverage: SQLi, command injection, weak crypto, JWT bypass, path traversal, XSS, SSRF, file upload, CSRF, missing authz, XPath injection, open redirect, TLS bypass |
146
+ | Secrets (`SECRET`) | 13 | AWS / GCP / GitHub / Slack / Stripe / private keys / JWTs / hardcoded passwords / K8s Secret YAML / connection strings with embedded creds |
147
+ | Python — Other | 12 | Placeholders, leakage (cross-language idioms, PII), import hallucination, method complexity, variant detection, LLM guardrails (OWASP LLM Top-10) |
148
+ | Terraform — General + AI (`TF-T`, `TF-AI`) | 26 | required_version, sensitive outputs, IAM wildcards, mutable git refs, deprecated resources, AWS-region-in-GCP, placeholder values |
149
+ | Terraform — AWS (`TF-A`) | 40 | EC2 IMDSv2, S3 public-access-block, EBS encryption, VPC flow logs, KMS rotation, RDS hardening, SG / NACL / EKS / DynamoDB / ElastiCache / CloudTrail / IAM |
150
+ | Terraform — GCP (`TF-G`) | 50 | GKE hardening, GCS public-access prevention, IAM roles, KMS rotation, Cloud Function/Run public, BigQuery, Pub/Sub CMEK, Cloud SQL, firewall ingress |
151
+ | Terraform — Azure (`TF-AZ`) | 14 | Storage public blob, SQL public network, AKS RBAC, Key Vault purge protection, NSG SSH/RDP, managed disk CMK |
152
+ | Terraform — Mechanics + Lifecycle (`TF-M`, `TF-V`) | 12 | SG inline mixing, `force_destroy`, mutable module refs, lifecycle antipatterns |
153
+ | Terragrunt (`TG`) | 6 | HCL inputs, mock_outputs, remote state encryption |
154
+ | Dockerfile (`DF`) | 15 | Latest tag, root user, secret leakage, OCI labels, HEALTHCHECK, legacy ENV form |
155
+ | Kubernetes YAML (`YAML`) | 26 | Pod Security Standards, hostPath, default namespace, image digest pinning, RBAC wildcards |
156
+ | GitHub Actions (`YAML-GHA`) | — | SHA pinning, expression injection, missing permissions, secret env-var leakage, missing timeouts |
157
+ | Shell (`SH`) | 8 | Dangerous globbing, missing `set -euo pipefail` |
158
+
159
+ ```bash
160
+ proofctl rules # full list
161
+ proofctl rules --family S # filter by family
162
+ proofctl rules --severity ERROR
163
+ ```
164
+
165
+ ---
166
+
167
+ ## Suppressing findings
168
+
169
+ Inline (single line):
170
+
171
+ ```python
172
+ result = subprocess.run(cmd, shell=True) # proofctl: ignore[PROOFCTL-S-002]
173
+ ```
174
+
175
+ ```hcl
176
+ resource "aws_s3_bucket" "logs" {
177
+ acl = "public-read" # proofctl: ignore[PROOFCTL-TF-AI-003] // or # comment style
178
+ }
179
+ ```
180
+
181
+ Project-wide in `.proofctl.yaml`:
182
+
183
+ ```yaml
184
+ disable:
185
+ - PROOFCTL-Q-004
186
+ ```
187
+
188
+ ---
189
+
190
+ ## Configuration
191
+
192
+ Place `.proofctl.yaml` in the project root:
193
+
194
+ ```yaml
195
+ exclude_paths:
196
+ - "**/.venv/**"
197
+ - "**/migrations/**"
198
+ - "**/.terraform/**"
199
+
200
+ disable:
201
+ - PROOFCTL-Q-004
202
+ - PROOFCTL-DF-AI-002
203
+
204
+ severity_overrides:
205
+ PROOFCTL-P-002: ERROR # promote TODOs to ERROR
206
+
207
+ rules:
208
+ PROOFCTL-P-002:
209
+ allowed_formats:
210
+ - 'TODO\(#\d+\)' # allow TODO(#123) format
211
+ exclude_paths:
212
+ - tests/
213
+
214
+ PROOFCTL-Q-003:
215
+ any_threshold: 5
216
+
217
+ PROOFCTL-V-002:
218
+ similarity_threshold: 0.85
219
+ min_file_lines: 30
220
+
221
+ PROOFCTL-I-001:
222
+ local_namespaces:
223
+ - mycompany_
224
+ - internal_
225
+
226
+ PROOFCTL-TF-T013:
227
+ required_labels:
228
+ - environment
229
+ - team
230
+ - cost_center
231
+
232
+ # Substrings that mark a line as legitimate private infra. Findings from
233
+ # "name-shaped" rules (SECRET-*, TF-T005, TF-AI-001, DF-AI-*, Q-AI-*) on a
234
+ # line containing any of these tokens are silently dropped. Real
235
+ # code-shape security rules (S-001 SQLi, S-005 eval, etc.) keep firing.
236
+ internal_identifiers:
237
+ - mycompany-prod # internal hostname prefix
238
+ - mycompany.internal # internal DNS suffix
239
+ - INTERNAL_PROJECT_NAME # codename that sometimes looks like a placeholder
240
+ ```
241
+
242
+ ---
243
+
244
+ ## Commands
245
+
246
+ ### `proofctl check`
247
+
248
+ ```
249
+ proofctl check [PATH] [OPTIONS]
250
+
251
+ Options:
252
+ --format / -f terminal | json | html (default: terminal)
253
+ --output / -o Write report to file
254
+ --changed-only Only scan git-changed files
255
+ --families P,Q,S,L,I,M,V,LLM,TF,TG,DF,YAML,SH,SECRET
256
+ --min-severity INFO | WARNING | ERROR
257
+ --fail-on Exit non-zero at this severity (default: WARNING)
258
+ --no-pypi Skip PyPI lookups (faster, works offline)
259
+ --new-only Suppress findings present in .proofctl-baseline.json
260
+ --fix Auto-fix fixable findings (Q-001 mutable defaults)
261
+ ```
262
+
263
+ ### `proofctl baseline`
264
+
265
+ Snapshot the current findings so future `--new-only` runs only surface regressions.
266
+
267
+ ```bash
268
+ proofctl baseline .
269
+ git add .proofctl-baseline.json && git commit -m "chore: proofctl baseline"
270
+ ```
271
+
272
+ ### `proofctl rules`
273
+
274
+ ```bash
275
+ proofctl rules # list all
276
+ proofctl rules --family S # filter by family
277
+ proofctl rules --severity ERROR
278
+ ```
279
+
280
+ ---
281
+
282
+ ## Exit codes
283
+
284
+ | Code | Meaning |
285
+ |------|---------|
286
+ | `0` | No findings |
287
+ | `1` | Findings present, none at or above `--fail-on` threshold |
288
+ | `2` | One or more findings at or above `--fail-on` threshold |
289
+
290
+ ---
291
+
292
+ ## Output formats
293
+
294
+ **Terminal** (default) — rich-coloured table with file:line, rule, severity, hint.
295
+
296
+ **JSON** — machine-readable for CI:
297
+
298
+ ```json
299
+ {
300
+ "schema_version": 1,
301
+ "summary": { "total": 4, "ERROR": 3, "WARNING": 1 },
302
+ "findings": [
303
+ {
304
+ "file": "module/auth.py",
305
+ "line": 42,
306
+ "col": 8,
307
+ "rule_id": "PROOFCTL-S-001",
308
+ "rule_name": "SQL injection",
309
+ "severity": "ERROR",
310
+ "message": "SQL injection via string format in .execute()",
311
+ "hint": "Use parameterised queries: cursor.execute(sql, params)",
312
+ "authority": "OWASP A03:2021, CWE-89"
313
+ }
314
+ ]
315
+ }
316
+ ```
317
+
318
+ **HTML** — self-contained single-file dashboard with severity summary cards and a filterable table.
319
+
320
+ ---
321
+
322
+ ## License
323
+
324
+ MIT