secure-code-agent 0.7.0__tar.gz → 0.8.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 (50) hide show
  1. {secure_code_agent-0.7.0/src/secure_code_agent.egg-info → secure_code_agent-0.8.0}/PKG-INFO +1 -1
  2. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0/src/secure_code_agent.egg-info}/PKG-INFO +1 -1
  3. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/__init__.py +1 -1
  4. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/cli.py +18 -1
  5. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/renderers.py +6 -0
  6. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scoring.py +21 -0
  7. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/LICENSE +0 -0
  8. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/README.md +0 -0
  9. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/pyproject.toml +0 -0
  10. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/setup.cfg +0 -0
  11. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_agent.egg-info/SOURCES.txt +0 -0
  12. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_agent.egg-info/dependency_links.txt +0 -0
  13. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_agent.egg-info/entry_points.txt +0 -0
  14. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_agent.egg-info/requires.txt +0 -0
  15. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_agent.egg-info/top_level.txt +0 -0
  16. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/baseline.py +0 -0
  17. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/config.py +0 -0
  18. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/data/semgrep-offline.yaml +0 -0
  19. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/findings.py +0 -0
  20. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/git_tools.py +0 -0
  21. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/history.py +0 -0
  22. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/instructions.py +0 -0
  23. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/pillar.py +0 -0
  24. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/practice.py +0 -0
  25. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/remediation.py +0 -0
  26. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/ruleset.py +0 -0
  27. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/sarif.py +0 -0
  28. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanner_status.py +0 -0
  29. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/__init__.py +0 -0
  30. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/bandit_scanner.py +0 -0
  31. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/base.py +0 -0
  32. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/builtin_rules.py +0 -0
  33. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/checkov_scanner.py +0 -0
  34. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/floor.py +0 -0
  35. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/gitleaks_scanner.py +0 -0
  36. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/gosec_scanner.py +0 -0
  37. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/hadolint_scanner.py +0 -0
  38. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/njsscan_scanner.py +0 -0
  39. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/npm_audit_scanner.py +0 -0
  40. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/osv_scanner.py +0 -0
  41. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/pip_audit_scanner.py +0 -0
  42. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/rubocop_scanner.py +0 -0
  43. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/scorecard_scanner.py +0 -0
  44. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/semgrep_scanner.py +0 -0
  45. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/trivy_scanner.py +0 -0
  46. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/scanners/trufflehog_scanner.py +0 -0
  47. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/standards.py +0 -0
  48. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/suppressions.py +0 -0
  49. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/triage.py +0 -0
  50. {secure_code_agent-0.7.0 → secure_code_agent-0.8.0}/src/secure_code_audit/verify.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: secure-code-agent
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: Deterministic security gate + bounded AI remediation prompt generator. NIST SSDF / OWASP ASVS / CWE Top 25 anchored.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: secure-code-agent
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: Deterministic security gate + bounded AI remediation prompt generator. NIST SSDF / OWASP ASVS / CWE Top 25 anchored.
5
5
  Author: Marshall Guillory
6
6
  License: MIT
@@ -12,4 +12,4 @@
12
12
  #:
13
13
  #: PyPI is immutable, so 0.4.0 stays wrong. 0.5.0 is the first build whose
14
14
  #: artifacts name their own producer correctly.
15
- __version__ = "0.7.0"
15
+ __version__ = "0.8.0"
@@ -897,7 +897,15 @@ def _under_root(root: Path, value: str) -> Path:
897
897
  def _print_summary(
898
898
  verdict, score, gate, ran, unavailable, coverage, paths, axes=(), trend=None
899
899
  ) -> None:
900
- status = "PASS" if gate.passed else "FAIL"
900
+ # "PASS" is a claim that something was checked. With no gate configured
901
+ # nothing was, and saying so is the difference between a report and a
902
+ # false assurance.
903
+ if not gate.passed:
904
+ status = "FAIL"
905
+ elif gate.enforced:
906
+ status = "PASS"
907
+ else:
908
+ status = "NOT CONFIGURED"
901
909
  print(f"secure-code-agent · score {verdict.headline()} · gate {status}")
902
910
  for reason in verdict.reasons:
903
911
  print(f" ! grade withheld: {reason}")
@@ -921,6 +929,15 @@ def _print_summary(
921
929
  if not gate.passed:
922
930
  for reason in gate.reasons:
923
931
  print(f" ✗ {reason}")
932
+ elif not gate.enforced:
933
+ print(
934
+ " ! no gate is configured, so nothing here could have failed. "
935
+ "This audit is a report, not a check."
936
+ )
937
+ print(
938
+ " Set gates.fail_on_severity in secure-code-agent.json to make "
939
+ "findings block a build; read the work order either way."
940
+ )
924
941
  written = [
925
942
  str(p)
926
943
  for p in (
@@ -51,6 +51,12 @@ def to_json(
51
51
  },
52
52
  "gate": {
53
53
  "passed": gate.passed,
54
+ # Which gates could actually have failed. Empty means no policy
55
+ # was configured, and `passed: true` then says only that nothing
56
+ # tripped — not that anything was checked. A consumer treating
57
+ # `passed` as a security signal needs to see this.
58
+ "configured": list(gate.configured),
59
+ "enforced": gate.enforced,
54
60
  "reasons": list(gate.reasons),
55
61
  "tripped": list(gate.tripped),
56
62
  },
@@ -551,6 +551,26 @@ class GateResult:
551
551
  passed: bool
552
552
  reasons: tuple[str, ...] # human-readable trip reasons
553
553
  tripped: tuple[str, ...] = field(default_factory=tuple)
554
+ #: Gates that could actually have failed this run. Empty means no
555
+ #: policy was configured, which is **not** the same as passing one.
556
+ #:
557
+ #: `passed` stays True in that case — no gate tripped, which is
558
+ #: accurate — but reporting it as PASS is a claim nothing checked. A
559
+ #: 200,000-line repository carrying SQL injection, `shell=True`,
560
+ #: `pickle.loads` and `eval` printed "gate PASS" out of the box, with
561
+ #: no configuration, because an absent gate cannot trip. The work
562
+ #: order listed all seven findings correctly at the same time.
563
+ #:
564
+ #: `_require_configured_gates` already refuses `--fail-on-gate` in this
565
+ #: situation, calling it "a green build with no security floor". This
566
+ #: is the same fact, carried far enough to reach the summary line a
567
+ #: person actually reads.
568
+ configured: tuple[str, ...] = field(default_factory=tuple)
569
+
570
+ @property
571
+ def enforced(self) -> bool:
572
+ """Did any gate actually stand between these findings and a pass?"""
573
+ return bool(self.configured)
554
574
 
555
575
 
556
576
  # Every gate, with the predicate that decides whether it can actually trip.
@@ -611,6 +631,7 @@ def evaluate_gates(
611
631
  passed=not tripped,
612
632
  reasons=tuple(reasons),
613
633
  tripped=tuple(tripped),
634
+ configured=active_gates(gate_config),
614
635
  )
615
636
 
616
637