proofctl 0.5.0__tar.gz → 0.5.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.
- {proofctl-0.5.0/proofctl.egg-info → proofctl-0.5.2}/PKG-INFO +1 -1
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/terraform.py +39 -4
- {proofctl-0.5.0 → proofctl-0.5.2/proofctl.egg-info}/PKG-INFO +1 -1
- {proofctl-0.5.0 → proofctl-0.5.2}/pyproject.toml +1 -1
- {proofctl-0.5.0 → proofctl-0.5.2}/LICENSE +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/MANIFEST.in +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/README.md +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/__init__.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/_globmatch.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/baseline.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/__init__.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/base.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/dockerfile.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/hcl_utils.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/imports.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/leakage.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/llm_integration.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/placeholders.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/quality.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/secrets.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/security.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/shell_checker.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/terragrunt.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/variants.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/checkers/yaml_checker.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/cli.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/config.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/engine.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/fixer.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/models.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/registry.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/reporters/__init__.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/reporters/html_reporter.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/reporters/json_reporter.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl/reporters/terminal.py +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl.egg-info/SOURCES.txt +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl.egg-info/dependency_links.txt +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl.egg-info/entry_points.txt +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl.egg-info/requires.txt +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/proofctl.egg-info/top_level.txt +0 -0
- {proofctl-0.5.0 → proofctl-0.5.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: proofctl
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Summary: Zero-dependency linter for Python, Terraform, Dockerfiles, Kubernetes, and GitHub Actions — catches AI slop and security misconfigurations pre-commit
|
|
5
5
|
Author-email: Kolawolu Odunola <kolawolu.o@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -143,7 +143,12 @@ _AI_PLACEHOLDER_VALUE_RE = re.compile(
|
|
|
143
143
|
r'<[A-Z][A-Z0-9_\-]+>|placeholder|todo)"',
|
|
144
144
|
re.IGNORECASE,
|
|
145
145
|
)
|
|
146
|
-
|
|
146
|
+
# Single-line anchored: [^"\n]* (not [^"]*) so the match can't span
|
|
147
|
+
# across a closing+opening quote pair on different lines. Without the
|
|
148
|
+
# \n exclusion, a line like `attr = "TRUE"` followed several lines
|
|
149
|
+
# down by `image = "..."` produces a spurious match that picks up any
|
|
150
|
+
# `<placeholder>` in a comment in between.
|
|
151
|
+
_AI_ANGLE_BRACKET_RE = re.compile(r'"[^"\n]*<[A-Za-z][A-Za-z0-9_\-]+>[^"\n]*"')
|
|
147
152
|
|
|
148
153
|
# AWS region format: us-east-1 (with trailing -digit). GCP uses us-east1, us-central1.
|
|
149
154
|
_AWS_REGION_RE = re.compile(
|
|
@@ -3477,6 +3482,36 @@ class TerraformChecker(HclFileChecker):
|
|
|
3477
3482
|
re.IGNORECASE,
|
|
3478
3483
|
)
|
|
3479
3484
|
|
|
3485
|
+
# Suffixes that mark a variable name as a reference identifier rather
|
|
3486
|
+
# than the secret value itself. ``var.db_password_secret_id`` is the
|
|
3487
|
+
# *name* of a Secret Manager secret (fetched at runtime via gcloud)
|
|
3488
|
+
# — not the password value — so embedding it in metadata is safe.
|
|
3489
|
+
# AI-013 must NOT fire on names matching these suffixes.
|
|
3490
|
+
_ID_SUFFIX_RE = re.compile(
|
|
3491
|
+
r"_(?:id|name|arn|uri|url|email|self_link|version|"
|
|
3492
|
+
r"key_id|key_name|secret_id|secret_name)$",
|
|
3493
|
+
re.IGNORECASE,
|
|
3494
|
+
)
|
|
3495
|
+
|
|
3496
|
+
@classmethod
|
|
3497
|
+
def _sensitive_var_match(cls, line_text: str) -> "re.Match[str] | None":
|
|
3498
|
+
"""Return a match on a secret-shaped var name, or None.
|
|
3499
|
+
|
|
3500
|
+
Wraps ``_SENSITIVE_VAR_NAME_RE.search`` with a suffix filter:
|
|
3501
|
+
names ending in ``_id``, ``_name``, ``_arn``, ``_uri``, ``_email``,
|
|
3502
|
+
``_self_link``, ``_version``, ``_secret_id``, ``_secret_name``,
|
|
3503
|
+
``_key_id``, ``_key_name``, ``_url`` are reference identifiers
|
|
3504
|
+
(pointers to other resources) rather than secret values themselves.
|
|
3505
|
+
They are safe to embed in metadata because the actual secret is
|
|
3506
|
+
fetched at runtime by the consumer.
|
|
3507
|
+
"""
|
|
3508
|
+
for m in cls._SENSITIVE_VAR_NAME_RE.finditer(line_text):
|
|
3509
|
+
name = m.group(1)
|
|
3510
|
+
if cls._ID_SUFFIX_RE.search(name):
|
|
3511
|
+
continue
|
|
3512
|
+
return m
|
|
3513
|
+
return None
|
|
3514
|
+
|
|
3480
3515
|
@staticmethod
|
|
3481
3516
|
def _line_range_of_attr(
|
|
3482
3517
|
block: HclBlock, attr_name: str
|
|
@@ -3552,14 +3587,14 @@ class TerraformChecker(HclFileChecker):
|
|
|
3552
3587
|
lo, hi = rng
|
|
3553
3588
|
for offset in range(lo, hi + 1):
|
|
3554
3589
|
line_text = b.raw_lines[offset]
|
|
3555
|
-
m = self.
|
|
3590
|
+
m = self._sensitive_var_match(line_text)
|
|
3556
3591
|
if m:
|
|
3557
3592
|
_emit(b, b.start_line + offset, m.group(1),
|
|
3558
3593
|
"metadata_startup_script")
|
|
3559
3594
|
# 2. Scan nested metadata { ... } blocks (HCL block form).
|
|
3560
3595
|
for md in b.nested("metadata"):
|
|
3561
3596
|
for offset, line_text in enumerate(md.raw_lines):
|
|
3562
|
-
m = self.
|
|
3597
|
+
m = self._sensitive_var_match(line_text)
|
|
3563
3598
|
if m:
|
|
3564
3599
|
_emit(b, md.start_line + offset, m.group(1),
|
|
3565
3600
|
"metadata block")
|
|
@@ -3569,7 +3604,7 @@ class TerraformChecker(HclFileChecker):
|
|
|
3569
3604
|
lo, hi = rng
|
|
3570
3605
|
for offset in range(lo, hi + 1):
|
|
3571
3606
|
line_text = b.raw_lines[offset]
|
|
3572
|
-
m = self.
|
|
3607
|
+
m = self._sensitive_var_match(line_text)
|
|
3573
3608
|
if m:
|
|
3574
3609
|
_emit(b, b.start_line + offset, m.group(1),
|
|
3575
3610
|
"metadata block")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: proofctl
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Summary: Zero-dependency linter for Python, Terraform, Dockerfiles, Kubernetes, and GitHub Actions — catches AI slop and security misconfigurations pre-commit
|
|
5
5
|
Author-email: Kolawolu Odunola <kolawolu.o@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "proofctl"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.2"
|
|
8
8
|
description = "Zero-dependency linter for Python, Terraform, Dockerfiles, Kubernetes, and GitHub Actions — catches AI slop and security misconfigurations pre-commit"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|