proofctl 0.5.4__tar.gz → 0.5.6__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 (41) hide show
  1. {proofctl-0.5.4/proofctl.egg-info → proofctl-0.5.6}/PKG-INFO +1 -1
  2. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/terraform.py +66 -3
  3. {proofctl-0.5.4 → proofctl-0.5.6/proofctl.egg-info}/PKG-INFO +1 -1
  4. {proofctl-0.5.4 → proofctl-0.5.6}/pyproject.toml +1 -1
  5. {proofctl-0.5.4 → proofctl-0.5.6}/LICENSE +0 -0
  6. {proofctl-0.5.4 → proofctl-0.5.6}/MANIFEST.in +0 -0
  7. {proofctl-0.5.4 → proofctl-0.5.6}/README.md +0 -0
  8. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/__init__.py +0 -0
  9. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/_globmatch.py +0 -0
  10. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/baseline.py +0 -0
  11. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/__init__.py +0 -0
  12. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/base.py +0 -0
  13. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/dockerfile.py +0 -0
  14. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/hcl_utils.py +0 -0
  15. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/imports.py +0 -0
  16. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/leakage.py +0 -0
  17. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/llm_integration.py +0 -0
  18. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/placeholders.py +0 -0
  19. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/quality.py +0 -0
  20. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/secrets.py +0 -0
  21. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/security.py +0 -0
  22. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/shell_checker.py +0 -0
  23. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/terragrunt.py +0 -0
  24. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/variants.py +0 -0
  25. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/checkers/yaml_checker.py +0 -0
  26. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/cli.py +0 -0
  27. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/config.py +0 -0
  28. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/engine.py +0 -0
  29. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/fixer.py +0 -0
  30. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/models.py +0 -0
  31. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/registry.py +0 -0
  32. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/reporters/__init__.py +0 -0
  33. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/reporters/html_reporter.py +0 -0
  34. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/reporters/json_reporter.py +0 -0
  35. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl/reporters/terminal.py +0 -0
  36. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl.egg-info/SOURCES.txt +0 -0
  37. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl.egg-info/dependency_links.txt +0 -0
  38. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl.egg-info/entry_points.txt +0 -0
  39. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl.egg-info/requires.txt +0 -0
  40. {proofctl-0.5.4 → proofctl-0.5.6}/proofctl.egg-info/top_level.txt +0 -0
  41. {proofctl-0.5.4 → proofctl-0.5.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: proofctl
3
- Version: 0.5.4
3
+ Version: 0.5.6
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
@@ -1632,12 +1632,41 @@ class TerraformChecker(HclFileChecker):
1632
1632
  ))
1633
1633
  return out
1634
1634
 
1635
+ # ── GKE Autopilot detection (0.5.6) ──────────────────────────────────
1636
+ #
1637
+ # GKE Autopilot is a managed-node mode where Google forces hardened
1638
+ # defaults that cannot be overridden. Many rules in this family target
1639
+ # `node_config` attributes that are illegal to set on Autopilot
1640
+ # clusters — flagging them produces false positives whose suggested
1641
+ # fix wouldn't even apply.
1642
+ #
1643
+ # The two helpers below let downstream rules skip themselves (or
1644
+ # demote severity) when scanning an Autopilot cluster. The detection
1645
+ # is whole-block string-match — adequate because the attribute name
1646
+ # is unambiguous.
1647
+
1648
+ @staticmethod
1649
+ def _is_gke_autopilot(b: HclBlock) -> bool:
1650
+ """True iff the cluster has `enable_autopilot = true`."""
1651
+ if b.label1 != "google_container_cluster":
1652
+ return False
1653
+ val = (b.attr_value("enable_autopilot") or "").strip().lower()
1654
+ return val == "true"
1655
+
1656
+ @staticmethod
1657
+ def _has_workload_identity(b: HclBlock) -> bool:
1658
+ """True iff `workload_identity_config { … }` block is nested."""
1659
+ return b.has_nested("workload_identity_config")
1660
+
1635
1661
  def _g034(self, path: Path, blocks: list[HclBlock]) -> list[Finding]:
1636
1662
  """G-034 — GKE cluster missing explicit enable_legacy_abac = false."""
1637
1663
  out = []
1638
1664
  for b in blocks:
1639
1665
  if b.kind != "resource" or b.label1 != "google_container_cluster":
1640
1666
  continue
1667
+ # Autopilot: legacy ABAC is forced false and unchangeable.
1668
+ if self._is_gke_autopilot(b):
1669
+ continue
1641
1670
  val = b.attr_value("enable_legacy_abac")
1642
1671
  if val is None:
1643
1672
  # Absent — provider default is false now, but old default was true.
@@ -1680,6 +1709,10 @@ class TerraformChecker(HclFileChecker):
1680
1709
  for b in blocks:
1681
1710
  if b.kind != "resource" or b.label1 not in ("google_container_cluster", "google_container_node_pool"):
1682
1711
  continue
1712
+ # Autopilot: node_config is not settable and Autopilot forces
1713
+ # disable-legacy-endpoints = "true" by default. Skip.
1714
+ if b.label1 == "google_container_cluster" and self._is_gke_autopilot(b):
1715
+ continue
1683
1716
  # Heuristic: require disable-legacy-endpoints = "true" anywhere in the block.
1684
1717
  if not b.contains(r'disable-legacy-endpoints\s*=\s*"true"'):
1685
1718
  out.append(self._f(
@@ -1699,6 +1732,10 @@ class TerraformChecker(HclFileChecker):
1699
1732
  for b in blocks:
1700
1733
  if b.kind != "resource" or b.label1 not in ("google_container_cluster", "google_container_node_pool"):
1701
1734
  continue
1735
+ # Autopilot: shielded VM is forced on and node_config is not
1736
+ # settable. The suggested fix would even fail provider validation.
1737
+ if b.label1 == "google_container_cluster" and self._is_gke_autopilot(b):
1738
+ continue
1702
1739
  has_block = b.contains(r'shielded_instance_config\s*\{')
1703
1740
  has_secure = b.contains(r'enable_secure_boot\s*=\s*true')
1704
1741
  has_integrity = b.contains(r'enable_integrity_monitoring\s*=\s*true')
@@ -1716,14 +1753,23 @@ class TerraformChecker(HclFileChecker):
1716
1753
 
1717
1754
  def _g038(self, path: Path, blocks: list[HclBlock]) -> list[Finding]:
1718
1755
  """G-038 — GKE cluster without release_channel pinned to STABLE/REGULAR/RAPID."""
1719
- _channel_re = re.compile(r'channel\s*=\s*"(STABLE|REGULAR|RAPID)"')
1756
+ _channel_literal_re = re.compile(r'channel\s*=\s*"(STABLE|REGULAR|RAPID)"')
1757
+ # `channel = var.something` is also a valid pin — the value comes
1758
+ # from a typed variable, not a hardcoded mistake. Recognise it.
1759
+ _channel_var_re = re.compile(r'channel\s*=\s*var\.[a-zA-Z_][a-zA-Z0-9_]*')
1760
+ # `channel = local.something` similarly.
1761
+ _channel_local_re = re.compile(r'channel\s*=\s*local\.[a-zA-Z_][a-zA-Z0-9_]*')
1720
1762
  out = []
1721
1763
  for b in blocks:
1722
1764
  if b.kind != "resource" or b.label1 != "google_container_cluster":
1723
1765
  continue
1724
1766
  body = "\n".join(b.raw_lines)
1725
1767
  has_block = bool(re.search(r'release_channel\s*\{', body))
1726
- has_channel = bool(_channel_re.search(body))
1768
+ has_channel = (
1769
+ bool(_channel_literal_re.search(body))
1770
+ or bool(_channel_var_re.search(body))
1771
+ or bool(_channel_local_re.search(body))
1772
+ )
1727
1773
  if not has_block or not has_channel:
1728
1774
  out.append(self._f(
1729
1775
  path, b.start_line,
@@ -1747,10 +1793,16 @@ class TerraformChecker(HclFileChecker):
1747
1793
  continue
1748
1794
  val = (b.attr_value("enable_shielded_nodes") or "").strip().lower()
1749
1795
  if val != "true":
1796
+ # Autopilot: shielded nodes are forced on regardless. The
1797
+ # explicit attribute remains useful as documentation — demote
1798
+ # severity to INFO so the gate doesn't fail prod CI on it.
1799
+ severity = (
1800
+ Severity.INFO if self._is_gke_autopilot(b) else Severity.WARNING
1801
+ )
1750
1802
  out.append(self._f(
1751
1803
  path, b.attr_line("enable_shielded_nodes") or b.start_line,
1752
1804
  "PROOFCTL-TF-G040", "GKE shielded nodes not enabled",
1753
- Severity.WARNING,
1805
+ severity,
1754
1806
  f'Cluster "{b.label2}" has enable_shielded_nodes not set to true',
1755
1807
  hint="Set enable_shielded_nodes = true on the cluster.",
1756
1808
  authority="CIS GKE Benchmark 6.5.5",
@@ -1765,6 +1817,17 @@ class TerraformChecker(HclFileChecker):
1765
1817
  for b in blocks:
1766
1818
  if b.kind != "resource" or b.label1 not in ("google_container_cluster", "google_container_node_pool"):
1767
1819
  continue
1820
+ # Autopilot + Workload Identity: workloads get GCP API access via
1821
+ # Workload Identity bindings to GSAs, not via the node SA. The
1822
+ # node SA is mostly inert. Skip the warning when the cluster is
1823
+ # Autopilot AND has workload_identity_config — that's the
1824
+ # recommended Autopilot security model.
1825
+ if (
1826
+ b.label1 == "google_container_cluster"
1827
+ and self._is_gke_autopilot(b)
1828
+ and self._has_workload_identity(b)
1829
+ ):
1830
+ continue
1768
1831
  body = "\n".join(b.raw_lines)
1769
1832
  uses_default = bool(_default_sa_re.search(body))
1770
1833
  # Absence of any service_account inside node_config also implies default SA.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: proofctl
3
- Version: 0.5.4
3
+ Version: 0.5.6
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.4"
7
+ version = "0.5.6"
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