proofctl 0.1.0__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 (56) hide show
  1. proofctl-0.1.0/LICENSE +21 -0
  2. proofctl-0.1.0/PKG-INFO +563 -0
  3. proofctl-0.1.0/README.md +532 -0
  4. proofctl-0.1.0/proofctl/__init__.py +0 -0
  5. proofctl-0.1.0/proofctl/baseline.py +63 -0
  6. proofctl-0.1.0/proofctl/checkers/__init__.py +0 -0
  7. proofctl-0.1.0/proofctl/checkers/base.py +61 -0
  8. proofctl-0.1.0/proofctl/checkers/dockerfile.py +452 -0
  9. proofctl-0.1.0/proofctl/checkers/hcl_utils.py +180 -0
  10. proofctl-0.1.0/proofctl/checkers/imports.py +486 -0
  11. proofctl-0.1.0/proofctl/checkers/leakage.py +228 -0
  12. proofctl-0.1.0/proofctl/checkers/llm_integration.py +370 -0
  13. proofctl-0.1.0/proofctl/checkers/placeholders.py +261 -0
  14. proofctl-0.1.0/proofctl/checkers/quality.py +539 -0
  15. proofctl-0.1.0/proofctl/checkers/security.py +831 -0
  16. proofctl-0.1.0/proofctl/checkers/terraform.py +1979 -0
  17. proofctl-0.1.0/proofctl/checkers/terragrunt.py +206 -0
  18. proofctl-0.1.0/proofctl/checkers/variants.py +166 -0
  19. proofctl-0.1.0/proofctl/checkers/yaml_checker.py +1220 -0
  20. proofctl-0.1.0/proofctl/cli.py +246 -0
  21. proofctl-0.1.0/proofctl/config.py +92 -0
  22. proofctl-0.1.0/proofctl/engine.py +403 -0
  23. proofctl-0.1.0/proofctl/fixer.py +138 -0
  24. proofctl-0.1.0/proofctl/models.py +44 -0
  25. proofctl-0.1.0/proofctl/reporters/__init__.py +0 -0
  26. proofctl-0.1.0/proofctl/reporters/html_reporter.py +191 -0
  27. proofctl-0.1.0/proofctl/reporters/json_reporter.py +22 -0
  28. proofctl-0.1.0/proofctl/reporters/terminal.py +110 -0
  29. proofctl-0.1.0/proofctl.egg-info/PKG-INFO +563 -0
  30. proofctl-0.1.0/proofctl.egg-info/SOURCES.txt +54 -0
  31. proofctl-0.1.0/proofctl.egg-info/dependency_links.txt +1 -0
  32. proofctl-0.1.0/proofctl.egg-info/entry_points.txt +2 -0
  33. proofctl-0.1.0/proofctl.egg-info/requires.txt +7 -0
  34. proofctl-0.1.0/proofctl.egg-info/top_level.txt +1 -0
  35. proofctl-0.1.0/pyproject.toml +53 -0
  36. proofctl-0.1.0/setup.cfg +4 -0
  37. proofctl-0.1.0/tests/test_baseline.py +130 -0
  38. proofctl-0.1.0/tests/test_config_proofctl.py +101 -0
  39. proofctl-0.1.0/tests/test_dockerfile.py +470 -0
  40. proofctl-0.1.0/tests/test_engine.py +88 -0
  41. proofctl-0.1.0/tests/test_fixer.py +162 -0
  42. proofctl-0.1.0/tests/test_imports.py +312 -0
  43. proofctl-0.1.0/tests/test_leakage.py +179 -0
  44. proofctl-0.1.0/tests/test_llm.py +279 -0
  45. proofctl-0.1.0/tests/test_placeholders.py +239 -0
  46. proofctl-0.1.0/tests/test_quality.py +135 -0
  47. proofctl-0.1.0/tests/test_quality_ext.py +286 -0
  48. proofctl-0.1.0/tests/test_security.py +322 -0
  49. proofctl-0.1.0/tests/test_security_ext.py +470 -0
  50. proofctl-0.1.0/tests/test_suppression.py +137 -0
  51. proofctl-0.1.0/tests/test_terraform.py +861 -0
  52. proofctl-0.1.0/tests/test_terraform_ext.py +1121 -0
  53. proofctl-0.1.0/tests/test_terragrunt.py +259 -0
  54. proofctl-0.1.0/tests/test_variants.py +136 -0
  55. proofctl-0.1.0/tests/test_yaml.py +401 -0
  56. proofctl-0.1.0/tests/test_yaml_k8s_gha.py +1105 -0
proofctl-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Tameed Engineering
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,563 @@
1
+ Metadata-Version: 2.4
2
+ Name: proofctl
3
+ Version: 0.1.0
4
+ Summary: Zero-dependency linter for Python, Terraform, Dockerfiles, Kubernetes, and GitHub Actions — catches AI slop and security misconfigurations pre-commit
5
+ Author-email: Tameed Engineering <eng@tameed.io>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/kolawoluu/proofctl
8
+ Project-URL: Repository, https://github.com/kolawoluu/proofctl
9
+ Project-URL: Bug Tracker, https://github.com/kolawoluu/proofctl/issues
10
+ Keywords: linter,security,terraform,kubernetes,ai,static-analysis,pre-commit
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Quality Assurance
20
+ Classifier: Topic :: Security
21
+ Requires-Python: >=3.11
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: typer[all]>=0.12
25
+ Requires-Dist: rich>=13
26
+ Requires-Dist: pyyaml>=6
27
+ Provides-Extra: dev
28
+ Requires-Dist: pytest>=8; extra == "dev"
29
+ Requires-Dist: pytest-mock>=3; extra == "dev"
30
+ Dynamic: license-file
31
+
32
+ # proofctl
33
+
34
+ Zero-dependency Python linter and infrastructure policy checker for pre-commit hooks. Detects AI-generated slop, security misconfigurations, and quality regressions across Python, Terraform (AWS/GCP/Azure), Dockerfiles, Kubernetes manifests, and GitHub Actions workflows.
35
+
36
+ ```
37
+ proofctl check .
38
+ ```
39
+
40
+ ```
41
+ PROOFCTL-S-001 module/auth.py:42 SQL injection via string format in .execute() ERROR
42
+ PROOFCTL-Q-001 module/models.py:17 Mutable default argument — list assigned at def time ERROR
43
+ PROOFCTL-P-001 module/tasks.py:89 Unimplemented function body (pass / ...) ERROR
44
+ PROOFCTL-TF-G004 infra/main.tf:14 GKE node pool has auto-repair disabled WARNING
45
+ ──────────────────────────────────────────────────────────────────
46
+ 4 findings (3 ERROR, 1 WARNING) exit 2
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Why proofctl
52
+
53
+ AI coding assistants generate plausible-looking code that is frequently:
54
+ - **Insecure** — SQL/command injection, hardcoded secrets, weak crypto, JWT bypass
55
+ - **Broken** — hallucinated imports, phantom methods, `pass` bodies shipped as real functions
56
+ - **Fragile** — mutable defaults, broad `except:`, no timeouts, untested paths
57
+ - **Wasteful** — near-duplicate files, single-implementation abstractions, TODO bombs
58
+
59
+ proofctl is a pre-commit linter purpose-built to catch all of this *before* it merges. It runs in under a second on a typical repo, requires no internet access, and adds zero runtime dependencies to your project.
60
+
61
+ ---
62
+
63
+ ## Installation
64
+
65
+ ```bash
66
+ pip install proofctl
67
+ ```
68
+
69
+ Or for development:
70
+
71
+ ```bash
72
+ git clone https://github.com/kolawoluu/proofctl
73
+ cd proofctl
74
+ pip install -e ".[dev]"
75
+ ```
76
+
77
+ **Requires:** Python 3.11+
78
+
79
+ ---
80
+
81
+ ## Quick start
82
+
83
+ ```bash
84
+ # Scan the current directory
85
+ proofctl check .
86
+
87
+ # Scan a single file
88
+ proofctl check src/api/auth.py
89
+
90
+ # Only report ERROR findings
91
+ proofctl check . --min-severity ERROR
92
+
93
+ # Exit non-zero only on ERROR (useful for CI gate)
94
+ proofctl check . --fail-on ERROR
95
+
96
+ # Scan only files changed in this branch
97
+ proofctl check . --changed-only
98
+
99
+ # Run only security and quality families
100
+ proofctl check . --families S,Q
101
+
102
+ # Generate an HTML report
103
+ proofctl check . --format html --output report.html
104
+
105
+ # List all rules
106
+ proofctl rules
107
+ ```
108
+
109
+ ---
110
+
111
+ ## Pre-commit integration
112
+
113
+ Add to `.pre-commit-config.yaml`:
114
+
115
+ ```yaml
116
+ repos:
117
+ - repo: local
118
+ hooks:
119
+ - id: proofctl
120
+ name: proofctl
121
+ language: system
122
+ entry: proofctl check
123
+ args: [--no-pypi, --fail-on, ERROR]
124
+ types: [python]
125
+ pass_filenames: false
126
+ ```
127
+
128
+ Or pin from the published GitHub repo:
129
+
130
+ ```yaml
131
+ repos:
132
+ - repo: https://github.com/kolawoluu/proofctl
133
+ rev: v0.1.0
134
+ hooks:
135
+ - id: proofctl
136
+ ```
137
+
138
+ ---
139
+
140
+ ## CI integration (GitHub Actions)
141
+
142
+ ```yaml
143
+ name: proofctl
144
+
145
+ on: [push, pull_request]
146
+
147
+ jobs:
148
+ proofctl:
149
+ runs-on: ubuntu-latest
150
+ steps:
151
+ - uses: actions/checkout@v4
152
+ - uses: actions/setup-python@v5
153
+ with:
154
+ python-version: "3.12"
155
+ - run: pip install proofctl
156
+
157
+ # --new-only compares against the committed baseline snapshot —
158
+ # CI fails only on regressions introduced in this PR.
159
+ - run: proofctl check . --no-pypi --fail-on ERROR --new-only
160
+
161
+ - name: Generate HTML report
162
+ if: failure()
163
+ run: proofctl check . --no-pypi --format html --output proofctl-report.html || true
164
+
165
+ - uses: actions/upload-artifact@v4
166
+ if: failure()
167
+ with:
168
+ name: proofctl-report
169
+ path: proofctl-report.html
170
+ retention-days: 14
171
+ ```
172
+
173
+ Create a baseline snapshot to suppress pre-existing findings:
174
+
175
+ ```bash
176
+ proofctl baseline .
177
+ git add .proofctl-baseline.json
178
+ git commit -m "chore: add proofctl baseline"
179
+ ```
180
+
181
+ ---
182
+
183
+ ## Rules
184
+
185
+ ### Python — Placeholder (P)
186
+
187
+ | Rule | Severity | Description |
188
+ |------|----------|-------------|
189
+ | PROOFCTL-P-001 | ERROR | Unimplemented function body (`pass`, `...`, `raise NotImplementedError`) |
190
+ | PROOFCTL-P-002 | WARNING | TODO / FIXME / HACK / XXX comment present |
191
+ | PROOFCTL-P-003 | INFO | Commented-out code block |
192
+
193
+ ### Python — Quality (Q)
194
+
195
+ | Rule | Severity | Description |
196
+ |------|----------|-------------|
197
+ | PROOFCTL-Q-001 | ERROR | Mutable default argument (`list`, `dict`, `set` at def time) |
198
+ | PROOFCTL-Q-002 | ERROR | Bare `except:` or broad `except Exception` with no re-raise |
199
+ | PROOFCTL-Q-003 | WARNING | Excessive `Any` usage or unexplained `# type: ignore` |
200
+ | PROOFCTL-Q-004 | INFO | Single-implementation abstraction (YAGNI violation) |
201
+ | PROOFCTL-Q-005 | WARNING/ERROR | High cyclomatic complexity (warn >10, error >20) |
202
+ | PROOFCTL-Q-006 | WARNING/ERROR | Function body too long (warn >50 lines, error >100 lines) |
203
+ | PROOFCTL-Q-007 | WARNING/ERROR | Too many parameters (warn >5, error >7) |
204
+ | PROOFCTL-Q-008 | WARNING | Boolean literal as positional argument (flag argument) |
205
+ | PROOFCTL-Q-009 | INFO | `print()` in non-test code instead of `logging` |
206
+
207
+ ### Python — Security (S)
208
+
209
+ | Rule | Severity | Description | Authority |
210
+ |------|----------|-------------|-----------|
211
+ | PROOFCTL-S-001 | ERROR | SQL injection via string formatting in `.execute()` | OWASP A03, CWE-89 |
212
+ | PROOFCTL-S-002 | ERROR | Command injection via `shell=True` or `os.system()` | OWASP A03, CWE-78 |
213
+ | PROOFCTL-S-003 | ERROR | Unsafe deserialization (`pickle.loads`, `yaml.load` without SafeLoader) | OWASP A08, CWE-502 |
214
+ | PROOFCTL-S-004 | ERROR | Weak cryptographic primitive (`md5`/`sha1` for auth, `random` for secrets) | OWASP A02, CWE-327 |
215
+ | PROOFCTL-S-005 | ERROR | `eval()` / `exec()` on non-literal input | CWE-95 |
216
+ | PROOFCTL-S-006 | WARNING | Missing `timeout=` on HTTP calls (`requests`, `httpx`) | CWE-400 |
217
+ | PROOFCTL-S-007 | ERROR | JWT signature bypass (`verify_signature: False`, `algorithms: ["none"]`) | OWASP A07 |
218
+ | PROOFCTL-S-008 | ERROR | Path traversal — `open()` with user-supplied path | CWE-22 |
219
+ | PROOFCTL-S-009 | ERROR | Insecure UUID for security token (`uuid1`/`uuid3` for token/secret/key) | CWE-338 |
220
+ | PROOFCTL-S-010 | WARNING | Secret value leaked into logs (password/token in `logging.*` call) | OWASP A09 |
221
+ | PROOFCTL-S-011 | ERROR/WARNING | Insecure cipher mode (`ECB`, `ARC4`, `TripleDES`) | OWASP A02 |
222
+ | PROOFCTL-S-012 | WARNING | Regex injection — non-literal pattern passed to `re.compile`/`re.search` | CWE-625 |
223
+ | PROOFCTL-S-013 | WARNING | Open redirect — `redirect()` with user-supplied URL | CWE-601 |
224
+
225
+ ### Python — Leakage (L)
226
+
227
+ | Rule | Severity | Description |
228
+ |------|----------|-------------|
229
+ | PROOFCTL-L-001 | ERROR | Hardcoded secret or credential in source |
230
+ | PROOFCTL-L-002 | WARNING | PII pattern in source (email, SSN, phone number) |
231
+ | PROOFCTL-L-003 | WARNING | Cross-language idiom (JS/Java/Go pattern in Python) |
232
+
233
+ ### Python — Imports (I)
234
+
235
+ | Rule | Severity | Description |
236
+ |------|----------|-------------|
237
+ | PROOFCTL-I-001 | WARNING | Import from unknown or unresolvable package (hallucination) |
238
+ | PROOFCTL-I-002 | ERROR | High-risk or deprecated package (`telnetlib`, `pickle`, etc.) |
239
+
240
+ ### Python — Methods (M)
241
+
242
+ | Rule | Severity | Description |
243
+ |------|----------|-------------|
244
+ | PROOFCTL-M-001 | WARNING | Method too complex — abstraction opportunity |
245
+
246
+ ### Python — Variants (V)
247
+
248
+ | Rule | Severity | Description |
249
+ |------|----------|-------------|
250
+ | PROOFCTL-V-001 | WARNING | Near-duplicate function bodies (DRY violation) |
251
+ | PROOFCTL-V-002 | INFO | Near-duplicate file (Jaccard similarity above threshold) |
252
+
253
+ ### Python — LLM Guardrails (LLM)
254
+
255
+ | Rule | Severity | Description | Authority |
256
+ |------|----------|-------------|-----------|
257
+ | PROOFCTL-LLM-001 | ERROR | Unsanitised user input in LLM prompt (f-string in `content=`) | OWASP LLM01 |
258
+ | PROOFCTL-LLM-002 | WARNING | Missing `max_tokens` on LLM API call | OWASP LLM10 |
259
+ | PROOFCTL-LLM-003 | WARNING | LLM API call inside a loop (unbounded cost) | OWASP LLM10 |
260
+ | PROOFCTL-LLM-004 | WARNING | PII variable name in LLM prompt | OWASP LLM02 |
261
+ | PROOFCTL-LLM-005 | ERROR | `while True:` agentic loop with LLM call and no iteration guard | OWASP LLM06 |
262
+
263
+ ### Terraform — General (TF-T)
264
+
265
+ | Rule | Severity | Description |
266
+ |------|----------|-------------|
267
+ | PROOFCTL-TF-T001 | ERROR | Empty or null resource block |
268
+ | PROOFCTL-TF-T002 | WARNING | `count = 0` resource |
269
+ | PROOFCTL-TF-T003 | ERROR | Hardcoded secret in resource attribute |
270
+ | PROOFCTL-TF-T004 | WARNING | Wildcard IAM permission (`*`) |
271
+ | PROOFCTL-TF-T005 | WARNING | `lifecycle { ignore_changes = all }` |
272
+ | PROOFCTL-TF-T006 | WARNING | Local-only module source (no registry or git ref) |
273
+ | PROOFCTL-TF-T007 | ERROR | Mutable git ref in module source (branch / HEAD) |
274
+ | PROOFCTL-TF-T008 | WARNING | Missing `description` on variable |
275
+ | PROOFCTL-TF-T009 | WARNING | Missing `description` on output |
276
+ | PROOFCTL-TF-T010 | WARNING | Null-default variable without validation block |
277
+ | PROOFCTL-TF-T011 | ERROR | Remote state without encryption |
278
+ | PROOFCTL-TF-T012 | WARNING | Provisioner block (prefer cloud-init or user_data) |
279
+ | PROOFCTL-TF-T013 | ERROR | Missing required resource labels |
280
+ | PROOFCTL-TF-T014 | WARNING | No `terraform { required_version }` constraint |
281
+ | PROOFCTL-TF-T015 | WARNING | Sensitive-named output without `sensitive = true` |
282
+
283
+ ### Terraform — GCP (TF-G)
284
+
285
+ 25 rules covering GCP compute, Cloud SQL, GKE, Cloud Storage, IAM, KMS, VPC, Cloud Run, BigQuery, Pub/Sub, and Cloud Functions. Highlights:
286
+
287
+ - `PROOFCTL-TF-G001` — GKE node pool with auto-repair disabled
288
+ - `PROOFCTL-TF-G004` — Cloud SQL with public IP
289
+ - `PROOFCTL-TF-G008` — Storage bucket with `allUsers` ACL
290
+ - `PROOFCTL-TF-G015` — GCS bucket without versioning
291
+ - `PROOFCTL-TF-G026` — IAM binding with `allUsers` / `allAuthenticatedUsers`
292
+ - `PROOFCTL-TF-G030` — BigQuery dataset accessible to `allAuthenticatedUsers`
293
+
294
+ ### Terraform — AWS (TF-A)
295
+
296
+ 14 rules covering EC2 IMDSv2, RDS, EKS, EBS, Lambda, ElastiCache, S3, ECR, CloudTrail, and VPC flow logs. Highlights:
297
+
298
+ - `PROOFCTL-TF-A001` — EC2 without IMDSv2 enforced
299
+ - `PROOFCTL-TF-A003` — RDS with public access
300
+ - `PROOFCTL-TF-A011` — No CloudTrail resource in file
301
+ - `PROOFCTL-TF-A014` — Lambda function with hardcoded secret in env vars
302
+
303
+ ### Terraform — Azure (TF-AZ)
304
+
305
+ 12 rules covering Azure storage, SQL/Postgres/MySQL, AKS, Key Vault, Monitor, RBAC, App Service, and VMs. Highlights:
306
+
307
+ - `PROOFCTL-TF-AZ001` — Storage account with `allow_blob_public_access = true`
308
+ - `PROOFCTL-TF-AZ003` — SQL server with `public_network_access_enabled = true`
309
+ - `PROOFCTL-TF-AZ005` — AKS cluster with unrestricted API server access
310
+ - `PROOFCTL-TF-AZ007` — Key Vault without purge protection
311
+ - `PROOFCTL-TF-AZ011` — App Service without `https_only = true`
312
+
313
+ ### Terraform — Mechanics (TF-M) and Lifecycle (TF-V)
314
+
315
+ 7 + 4 rules covering security group mixing, `ignore_changes = all`, external provisioners, `force_destroy`, `prevent_destroy`, and mutable module refs.
316
+
317
+ ### Terragrunt (TG)
318
+
319
+ 6 rules covering `var.*` in HCL inputs, missing `mock_outputs`, invalid `if_exists` values, and unencrypted remote state.
320
+
321
+ ### Dockerfile (DF)
322
+
323
+ | Rule | Severity | Description |
324
+ |------|----------|-------------|
325
+ | PROOFCTL-DF-001 | WARNING | `FROM` uses `latest` tag |
326
+ | PROOFCTL-DF-002 | ERROR | Running as root (`USER root` or no `USER` directive) |
327
+ | PROOFCTL-DF-003 | WARNING | `apt-get install` without `--no-install-recommends` |
328
+ | PROOFCTL-DF-004 | ERROR | Secret in `ARG` or `ENV` (password/token/key name) |
329
+ | PROOFCTL-DF-005 | WARNING | `ADD` used where `COPY` is sufficient |
330
+ | PROOFCTL-DF-006 | INFO | Multiple `RUN` commands that could be merged |
331
+ | PROOFCTL-DF-007 | ERROR | `curl`/`wget` output piped directly to shell |
332
+ | PROOFCTL-DF-008 | WARNING | `ADD` from URL without checksum verification |
333
+ | PROOFCTL-DF-009 | WARNING | `COPY` of dependency manifest without pinned install |
334
+ | PROOFCTL-DF-010 | INFO | Missing OCI image labels (`org.opencontainers.image.*`) |
335
+
336
+ ### YAML / Kubernetes (YAML-K8S)
337
+
338
+ 13 rules based on Kubernetes Pod Security Standards. Highlights:
339
+
340
+ | Rule | Severity | Description |
341
+ |------|----------|-------------|
342
+ | PROOFCTL-YAML-009 | ERROR | Container missing `runAsNonRoot: true` |
343
+ | PROOFCTL-YAML-010 | ERROR | Container missing `allowPrivilegeEscalation: false` |
344
+ | PROOFCTL-YAML-011 | WARNING | Container missing `readOnlyRootFilesystem: true` |
345
+ | PROOFCTL-YAML-012 | WARNING | Container missing `drop: [ALL]` capabilities |
346
+ | PROOFCTL-YAML-013 | WARNING | Pod missing `seccompProfile` annotation |
347
+ | PROOFCTL-YAML-014 | WARNING | `automountServiceAccountToken: true` on pod or service account |
348
+ | PROOFCTL-YAML-015 | ERROR | ClusterRoleBinding to `cluster-admin` |
349
+ | PROOFCTL-YAML-016 | WARNING | RBAC rule with wildcard verb or resource (`*`) |
350
+ | PROOFCTL-YAML-017 | ERROR | RBAC rule with `escalate`/`impersonate`/`bind` verb |
351
+ | PROOFCTL-YAML-018 | WARNING | Deployment/DaemonSet container missing liveness or readiness probe |
352
+ | PROOFCTL-YAML-019 | WARNING | Ingress without TLS configuration |
353
+ | PROOFCTL-YAML-020 | ERROR | Plaintext secret in environment variable (`value:` on secret-named var) |
354
+ | PROOFCTL-YAML-021 | WARNING | Namespace-scoped RoleBinding using `cluster-admin` |
355
+
356
+ ### YAML / GitHub Actions (YAML-GHA)
357
+
358
+ | Rule | Severity | Description |
359
+ |------|----------|-------------|
360
+ | PROOFCTL-YAML-007 | ERROR | Expression injection — `${{ github.event.* }}` in `run:` step |
361
+ | PROOFCTL-YAML-GHA-001 | ERROR | `pull_request_target` with `actions/checkout` of PR head ref |
362
+ | PROOFCTL-YAML-GHA-002 | WARNING | Workflow missing top-level `permissions:` block |
363
+ | PROOFCTL-YAML-GHA-003 | WARNING | Secret passed directly to environment variable in workflow |
364
+ | PROOFCTL-YAML-GHA-004 | ERROR | `ACTIONS_ALLOW_UNSECURE_COMMANDS: true` in workflow |
365
+ | PROOFCTL-YAML-GHA-005 | WARNING | Job missing `timeout-minutes` |
366
+
367
+ ---
368
+
369
+ ## Suppressing findings
370
+
371
+ Inline suppression for a single line:
372
+
373
+ ```python
374
+ result = subprocess.run(cmd, shell=True) # proofctl: ignore[PROOFCTL-S-002]
375
+ ```
376
+
377
+ Project-wide suppression in `.proofctl.yaml`:
378
+
379
+ ```yaml
380
+ disable:
381
+ - PROOFCTL-Q-004 # YAGNI check too noisy for this repo
382
+ ```
383
+
384
+ ---
385
+
386
+ ## Configuration
387
+
388
+ Place `.proofctl.yaml` in the project root:
389
+
390
+ ```yaml
391
+ exclude_paths:
392
+ - "**/.venv/**"
393
+ - "**/migrations/**"
394
+ - "**/.terraform/**"
395
+
396
+ disable:
397
+ - PROOFCTL-Q-004
398
+
399
+ severity_overrides:
400
+ PROOFCTL-P-002: ERROR # promote TODOs to ERROR
401
+
402
+ rules:
403
+ PROOFCTL-P-002:
404
+ allowed_formats:
405
+ - 'TODO\(#\d+\)' # allow TODO(#123) format
406
+ exclude_paths:
407
+ - tests/
408
+
409
+ PROOFCTL-Q-003:
410
+ any_threshold: 5
411
+
412
+ PROOFCTL-V-002:
413
+ similarity_threshold: 0.85
414
+ min_file_lines: 30
415
+
416
+ PROOFCTL-I-001:
417
+ local_namespaces:
418
+ - mycompany_
419
+ - internal_
420
+
421
+ PROOFCTL-TF-T013:
422
+ required_labels:
423
+ - environment
424
+ - team
425
+ - cost_center
426
+ ```
427
+
428
+ ---
429
+
430
+ ## Commands
431
+
432
+ ### `proofctl check`
433
+
434
+ ```
435
+ proofctl check [PATH] [OPTIONS]
436
+
437
+ Options:
438
+ --format / -f terminal | json | html (default: terminal)
439
+ --output / -o Write report to file
440
+ --changed-only Only scan git-changed files
441
+ --families Comma-separated families: P,Q,S,L,I,M,V,LLM,TF,TG,DF,YAML
442
+ --min-severity INFO | WARNING | ERROR
443
+ --fail-on Exit non-zero at this severity (default: WARNING)
444
+ --no-pypi Skip PyPI lookups (faster, works offline)
445
+ --new-only Suppress findings present in .proofctl-baseline.json
446
+ --fix Auto-fix fixable findings (Q-001 mutable defaults)
447
+ ```
448
+
449
+ ### `proofctl baseline`
450
+
451
+ Snapshot the current findings so future `--new-only` runs only surface regressions.
452
+
453
+ ```bash
454
+ proofctl baseline .
455
+ git add .proofctl-baseline.json && git commit -m "chore: proofctl baseline"
456
+ ```
457
+
458
+ ### `proofctl rules`
459
+
460
+ Print all rule IDs, names, and severities.
461
+
462
+ ---
463
+
464
+ ## Exit codes
465
+
466
+ | Code | Meaning |
467
+ |------|---------|
468
+ | `0` | No findings |
469
+ | `1` | Findings present, none at or above `--fail-on` threshold |
470
+ | `2` | One or more findings at or above `--fail-on` threshold |
471
+
472
+ ---
473
+
474
+ ## Output formats
475
+
476
+ **Terminal** (default) — rich-coloured table with file:line, rule, severity, and hint.
477
+
478
+ **JSON** — machine-readable array for CI integrations:
479
+
480
+ ```json
481
+ {
482
+ "summary": { "total": 4, "ERROR": 3, "WARNING": 1 },
483
+ "findings": [
484
+ {
485
+ "file": "module/auth.py",
486
+ "line": 42,
487
+ "col": 8,
488
+ "rule_id": "PROOFCTL-S-001",
489
+ "severity": "ERROR",
490
+ "message": "SQL injection via string format in .execute()",
491
+ "hint": "Use parameterised queries: cursor.execute(sql, params)",
492
+ "authority": "OWASP A03:2021, CWE-89"
493
+ }
494
+ ]
495
+ }
496
+ ```
497
+
498
+ **HTML** — self-contained single-file dashboard with severity summary cards and a filterable table.
499
+
500
+ ---
501
+
502
+ ## Architecture
503
+
504
+ proofctl is a pure Python AST linter with zero subprocess dependencies. It walks the repository with Python's `pathlib`, runs AST visitors for Python files, and custom regex/text parsers for Terraform HCL, Dockerfiles, and YAML. This makes it:
505
+
506
+ - **Fast** — typically < 1s for a 10k-line Python repo
507
+ - **Offline** — no network calls needed with `--no-pypi`
508
+ - **Dependency-free** — only `typer`, `rich`, `pyyaml` are required at runtime
509
+
510
+ ```
511
+ proofctl/
512
+ ├── cli.py # typer commands: check, baseline, rules
513
+ ├── engine.py # orchestrator: walks files, dispatches checkers
514
+ ├── config.py # .proofctl.yaml loader
515
+ ├── models.py # Finding dataclass + Severity enum
516
+ ├── baseline.py # snapshot save/load/filter
517
+ ├── fixer.py # auto-fix for Q-001
518
+ ├── checkers/
519
+ │ ├── placeholders.py # P family
520
+ │ ├── quality.py # Q family
521
+ │ ├── security.py # S family (S-001 to S-013)
522
+ │ ├── leakage.py # L family
523
+ │ ├── imports.py # I family
524
+ │ ├── methods.py # M family
525
+ │ ├── variants.py # V family
526
+ │ ├── llm.py # LLM family
527
+ │ ├── terraform.py # TF/TG families (T, G, A, AZ, M, V, TG)
528
+ │ ├── dockerfile.py # DF family
529
+ │ └── yaml_checker.py # YAML/K8s/GHA families
530
+ └── reporters/
531
+ ├── terminal.py
532
+ ├── json_reporter.py
533
+ └── html_reporter.py
534
+ ```
535
+
536
+ ---
537
+
538
+ ## Development
539
+
540
+ ```bash
541
+ pip install -e ".[dev]"
542
+ pytest tests/ -v
543
+ ```
544
+
545
+ 635 tests across all rule families. To run a specific family:
546
+
547
+ ```bash
548
+ pytest tests/test_security*.py -v
549
+ pytest tests/test_terraform*.py -v
550
+ pytest tests/test_yaml*.py -v
551
+ ```
552
+
553
+ ---
554
+
555
+ ## Companion tool
556
+
557
+ [**shieldctl**](https://github.com/kolawoluu/shieldctl) — CI-stage scanner that wraps best-of-breed external tools (checkov, tfsec, gitleaks, shellcheck, hadolint, actionlint, pip-audit) for deeper infrastructure security scanning. Run proofctl pre-commit; run shieldctl in CI.
558
+
559
+ ---
560
+
561
+ ## License
562
+
563
+ MIT