secure-code-agent 0.12.9__tar.gz → 0.12.11__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 (60) hide show
  1. {secure_code_agent-0.12.9/src/secure_code_agent.egg-info → secure_code_agent-0.12.11}/PKG-INFO +44 -5
  2. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/README.md +39 -1
  3. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/pyproject.toml +37 -5
  4. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11/src/secure_code_agent.egg-info}/PKG-INFO +44 -5
  5. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_agent.egg-info/SOURCES.txt +4 -0
  6. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_agent.egg-info/requires.txt +4 -3
  7. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/__init__.py +1 -1
  8. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/cli.py +234 -79
  9. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/config.py +84 -27
  10. secure_code_agent-0.12.11/src/secure_code_audit/data/standards.yaml +424 -0
  11. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/findings.py +11 -30
  12. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/git_tools.py +34 -0
  13. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/renderers.py +4 -2
  14. secure_code_agent-0.12.11/src/secure_code_audit/scanners/_execution.py +112 -0
  15. secure_code_agent-0.12.11/src/secure_code_audit/scanners/_finding_builder.py +233 -0
  16. secure_code_agent-0.12.11/src/secure_code_audit/scanners/_resolution.py +157 -0
  17. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/bandit_scanner.py +15 -4
  18. secure_code_agent-0.12.11/src/secure_code_audit/scanners/base.py +140 -0
  19. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/checkov_scanner.py +1 -3
  20. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/gitleaks_scanner.py +1 -3
  21. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/gosec_scanner.py +1 -3
  22. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/hadolint_scanner.py +1 -1
  23. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/njsscan_scanner.py +1 -3
  24. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/npm_audit_scanner.py +1 -3
  25. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/osv_scanner.py +1 -3
  26. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/pip_audit_scanner.py +0 -1
  27. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/rubocop_scanner.py +1 -3
  28. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/scorecard_scanner.py +1 -3
  29. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/semgrep_scanner.py +1 -3
  30. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/trivy_scanner.py +1 -3
  31. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/trufflehog_scanner.py +1 -1
  32. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scoring.py +13 -2
  33. secure_code_agent-0.12.11/src/secure_code_audit/standards.py +550 -0
  34. secure_code_agent-0.12.11/src/secure_code_audit/suppressions.py +442 -0
  35. secure_code_agent-0.12.9/src/secure_code_audit/scanners/base.py +0 -444
  36. secure_code_agent-0.12.9/src/secure_code_audit/standards.py +0 -705
  37. secure_code_agent-0.12.9/src/secure_code_audit/suppressions.py +0 -284
  38. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/LICENSE +0 -0
  39. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/setup.cfg +0 -0
  40. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_agent.egg-info/dependency_links.txt +0 -0
  41. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_agent.egg-info/entry_points.txt +0 -0
  42. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_agent.egg-info/top_level.txt +0 -0
  43. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/baseline.py +0 -0
  44. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/capabilities.py +0 -0
  45. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/data/semgrep-offline.yaml +0 -0
  46. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/demo.py +0 -0
  47. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/history.py +0 -0
  48. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/instructions.py +0 -0
  49. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/mcp_server.py +0 -0
  50. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/pillar.py +0 -0
  51. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/practice.py +0 -0
  52. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/remediation.py +0 -0
  53. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/ruleset.py +0 -0
  54. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/sarif.py +0 -0
  55. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanner_status.py +0 -0
  56. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/__init__.py +0 -0
  57. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/builtin_rules.py +0 -0
  58. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/scanners/floor.py +0 -0
  59. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/src/secure_code_audit/triage.py +0 -0
  60. {secure_code_agent-0.12.9 → secure_code_agent-0.12.11}/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.12.9
3
+ Version: 0.12.11
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
@@ -30,11 +30,11 @@ Description-Content-Type: text/markdown
30
30
  License-File: LICENSE
31
31
  Requires-Dist: PyYAML<7,>=6.0.2
32
32
  Provides-Extra: mcp
33
- Requires-Dist: mcp<2,>=1.0; extra == "mcp"
33
+ Requires-Dist: mcp<3,>=1.0; extra == "mcp"
34
34
  Provides-Extra: required-scanners
35
35
  Requires-Dist: bandit==1.9.4; extra == "required-scanners"
36
36
  Requires-Dist: pip-audit==2.10.1; extra == "required-scanners"
37
- Requires-Dist: njsscan==1.0.0; extra == "required-scanners"
37
+ Requires-Dist: njsscan==1.0.1; extra == "required-scanners"
38
38
  Provides-Extra: python-scanners
39
39
  Requires-Dist: secure-code-agent[required-scanners]; extra == "python-scanners"
40
40
  Requires-Dist: semgrep<2,>=1.172; extra == "python-scanners"
@@ -43,7 +43,8 @@ Provides-Extra: dev
43
43
  Requires-Dist: secure-code-agent[required-scanners]; extra == "dev"
44
44
  Requires-Dist: pytest>=8.0; extra == "dev"
45
45
  Requires-Dist: pytest-cov>=4.0; extra == "dev"
46
- Requires-Dist: ruff==0.16.2; extra == "dev"
46
+ Requires-Dist: ruff==0.16.9; extra == "dev"
47
+ Requires-Dist: markdown>=3.5; extra == "dev"
47
48
  Dynamic: license-file
48
49
 
49
50
  # secure-code-agent
@@ -454,6 +455,44 @@ for repositories whose `pyproject.toml` is their authoritative audit input.
454
455
 
455
456
  Wildcard rule (`rule_id: "*"`) requires a `file` or `paths` scope — you cannot disable a rule globally.
456
457
 
458
+ ## Extending the standards mapping
459
+
460
+ The shipped mapping table lives in `data/standards.yaml` and covers the rules
461
+ this project curates. Semgrep alone publishes thousands, so point
462
+ `standards_overlay` at your own file to map or correct a rule without waiting
463
+ for a release:
464
+
465
+ ```json
466
+ { "standards_overlay": "security/standards-overlay.yaml" }
467
+ ```
468
+
469
+ ```yaml
470
+ version: 1
471
+ entries:
472
+ - scanner: semgrep
473
+ rule_id: python.lang.security.audit.my-rule
474
+ canonical_cwe: CWE-22
475
+ owasp_top10: A01
476
+ asvs_section: V12.3.1
477
+ nist_ssdf: PW.5.1
478
+ short_desc: Path traversal in our request handler.
479
+ fix_hint: Resolve the path and contain it under the upload root.
480
+ ```
481
+
482
+ An overlay entry wins over the shipped table for the fields it sets, and an
483
+ adapter asserting its own CWE still wins over both.
484
+
485
+ **An overlay cannot set `severity`, `confidence` or `category`**, and a file
486
+ that tries is refused with the reason rather than ignored. Those three are the
487
+ scoring inputs: an overlay that set them could move the grade, which is the
488
+ hole [D32](docs/decisions.md) closed on the configuration side. An overlay says
489
+ *what weakness a rule describes*; it does not say *how much it counts*. Set
490
+ severity policy with `severity_overrides` in a config kept outside the audited
491
+ tree.
492
+
493
+ A declared overlay that cannot be read fails the run rather than being skipped,
494
+ for the same reason a malformed `.scignore.yaml` does.
495
+
457
496
  ## Baseline + incremental adoption
458
497
 
459
498
  `secure-code-baseline.json` fingerprints every current finding. On the next run:
@@ -515,7 +554,7 @@ For agents that support invokable skills, this repo ships a portable skill under
515
554
  ## GitHub Action
516
555
 
517
556
  ```yaml
518
- - uses: marshallguillory86/secure-code-agent@v0.12.9
557
+ - uses: marshallguillory86/secure-code-agent@v0.12.11
519
558
  with:
520
559
  config: secure-code-agent.json
521
560
  fail-on-gate: true
@@ -406,6 +406,44 @@ for repositories whose `pyproject.toml` is their authoritative audit input.
406
406
 
407
407
  Wildcard rule (`rule_id: "*"`) requires a `file` or `paths` scope — you cannot disable a rule globally.
408
408
 
409
+ ## Extending the standards mapping
410
+
411
+ The shipped mapping table lives in `data/standards.yaml` and covers the rules
412
+ this project curates. Semgrep alone publishes thousands, so point
413
+ `standards_overlay` at your own file to map or correct a rule without waiting
414
+ for a release:
415
+
416
+ ```json
417
+ { "standards_overlay": "security/standards-overlay.yaml" }
418
+ ```
419
+
420
+ ```yaml
421
+ version: 1
422
+ entries:
423
+ - scanner: semgrep
424
+ rule_id: python.lang.security.audit.my-rule
425
+ canonical_cwe: CWE-22
426
+ owasp_top10: A01
427
+ asvs_section: V12.3.1
428
+ nist_ssdf: PW.5.1
429
+ short_desc: Path traversal in our request handler.
430
+ fix_hint: Resolve the path and contain it under the upload root.
431
+ ```
432
+
433
+ An overlay entry wins over the shipped table for the fields it sets, and an
434
+ adapter asserting its own CWE still wins over both.
435
+
436
+ **An overlay cannot set `severity`, `confidence` or `category`**, and a file
437
+ that tries is refused with the reason rather than ignored. Those three are the
438
+ scoring inputs: an overlay that set them could move the grade, which is the
439
+ hole [D32](docs/decisions.md) closed on the configuration side. An overlay says
440
+ *what weakness a rule describes*; it does not say *how much it counts*. Set
441
+ severity policy with `severity_overrides` in a config kept outside the audited
442
+ tree.
443
+
444
+ A declared overlay that cannot be read fails the run rather than being skipped,
445
+ for the same reason a malformed `.scignore.yaml` does.
446
+
409
447
  ## Baseline + incremental adoption
410
448
 
411
449
  `secure-code-baseline.json` fingerprints every current finding. On the next run:
@@ -467,7 +505,7 @@ For agents that support invokable skills, this repo ships a portable skill under
467
505
  ## GitHub Action
468
506
 
469
507
  ```yaml
470
- - uses: marshallguillory86/secure-code-agent@v0.12.9
508
+ - uses: marshallguillory86/secure-code-agent@v0.12.11
471
509
  with:
472
510
  config: secure-code-agent.json
473
511
  fail-on-gate: true
@@ -53,7 +53,7 @@ dependencies = [
53
53
  # server drives it by subprocess rather than reimplementing it — so nobody
54
54
  # who only wants the gate pays for an MCP dependency.
55
55
  mcp = [
56
- "mcp>=1.0,<2",
56
+ "mcp>=1.0,<3",
57
57
  ]
58
58
 
59
59
  # Scanners the default configuration lists in gates.require_scanners. Pinned
@@ -66,7 +66,7 @@ required-scanners = [
66
66
  # rules, so a JavaScript repository can be scanned on a host with no Node.
67
67
  # Pinned for the same reason as the rest: the floor is a claim about what
68
68
  # ran, and an unpinned ruleset makes that claim unreproducible.
69
- "njsscan==1.0.0",
69
+ "njsscan==1.0.1",
70
70
  ]
71
71
  # The remaining Python-packaged scanners. Bounded rather than pinned because
72
72
  # they are optional; the coverage gate does not require them by default.
@@ -87,7 +87,12 @@ dev = [
87
87
  "secure-code-agent[required-scanners]",
88
88
  "pytest>=8.0",
89
89
  "pytest-cov>=4.0",
90
- "ruff==0.16.2",
90
+ "ruff==0.16.9",
91
+ # Renders docs/html, the reading copy of every document in the repository.
92
+ # A dev dependency, not a runtime one: the audit never renders documentation,
93
+ # and tests/unit/test_rendered_docs.py is what keeps the committed copy
94
+ # current. See tools/render_docs.py.
95
+ "markdown>=3.5",
91
96
  ]
92
97
 
93
98
  [project.scripts]
@@ -133,14 +138,41 @@ ignore = ["E501"] # let line-length be a soft guide; long log strings are fine
133
138
 
134
139
  [tool.pytest.ini_options]
135
140
  testpaths = ["tests"]
136
- addopts = "-q --strict-markers"
141
+ # Coverage is on by default, so the declared test command — plain `pytest`,
142
+ # which is what maintainability-agent runs — reports it and the
143
+ # `fail_under` below actually applies. Without this the suite was
144
+ # measurable only by whoever remembered the flags, and MA scored
145
+ # test_effectiveness as "not measurable" on every run.
146
+ #
147
+ # `xml` is not decoration: a consumer reads the *artifact*, never stdout.
148
+ # MA looks for `coverage.xml`, `coverage/lcov.info` or `lcov.info` and
149
+ # requires it to be newer than the moment before it ran the suite, so a
150
+ # repository cannot hand it a committed report and set its own
151
+ # test_effectiveness. With `term` alone the number was printed for humans
152
+ # and invisible to every tool, which is the same defect one layer down.
153
+ # `coverage.xml` is gitignored.
154
+ #
155
+ # A step that is not the one measuring passes `--no-cov`;
156
+ # tests/unit/test_one_coverage_floor.py requires every CI invocation to say
157
+ # which it is.
158
+ addopts = "-q --strict-markers --cov=secure_code_audit --cov-branch --cov-report=term --cov-report=xml"
159
+ # The suite tests this checkout, never an installed copy. Without it, bare
160
+ # `pytest` imports whichever secure_code_audit the interpreter can find, and
161
+ # an environment holding a plain install grades code nobody is editing —
162
+ # which is how maintainability-agent came to report a bug fixed in #59.
163
+ pythonpath = ["src"]
137
164
 
138
165
  [tool.coverage.run]
139
166
  source = ["secure_code_audit"]
140
167
  branch = true
141
168
 
142
169
  [tool.coverage.report]
143
- fail_under = 85
170
+ # The house floor. Raised 85 -> 92 once the suite could actually clear it:
171
+ # measured 93.79% branch coverage after the test seat covered --verify-against
172
+ # (which had no test through main() at all), the four live-config keys, and the
173
+ # loader's fail-closed paths. Raising it while the suite sat at 90.42% would
174
+ # have bought a red build and no tests.
175
+ fail_under = 92
144
176
  exclude_lines = [
145
177
  "pragma: no cover",
146
178
  "if __name__ == .__main__.:",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: secure-code-agent
3
- Version: 0.12.9
3
+ Version: 0.12.11
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
@@ -30,11 +30,11 @@ Description-Content-Type: text/markdown
30
30
  License-File: LICENSE
31
31
  Requires-Dist: PyYAML<7,>=6.0.2
32
32
  Provides-Extra: mcp
33
- Requires-Dist: mcp<2,>=1.0; extra == "mcp"
33
+ Requires-Dist: mcp<3,>=1.0; extra == "mcp"
34
34
  Provides-Extra: required-scanners
35
35
  Requires-Dist: bandit==1.9.4; extra == "required-scanners"
36
36
  Requires-Dist: pip-audit==2.10.1; extra == "required-scanners"
37
- Requires-Dist: njsscan==1.0.0; extra == "required-scanners"
37
+ Requires-Dist: njsscan==1.0.1; extra == "required-scanners"
38
38
  Provides-Extra: python-scanners
39
39
  Requires-Dist: secure-code-agent[required-scanners]; extra == "python-scanners"
40
40
  Requires-Dist: semgrep<2,>=1.172; extra == "python-scanners"
@@ -43,7 +43,8 @@ Provides-Extra: dev
43
43
  Requires-Dist: secure-code-agent[required-scanners]; extra == "dev"
44
44
  Requires-Dist: pytest>=8.0; extra == "dev"
45
45
  Requires-Dist: pytest-cov>=4.0; extra == "dev"
46
- Requires-Dist: ruff==0.16.2; extra == "dev"
46
+ Requires-Dist: ruff==0.16.9; extra == "dev"
47
+ Requires-Dist: markdown>=3.5; extra == "dev"
47
48
  Dynamic: license-file
48
49
 
49
50
  # secure-code-agent
@@ -454,6 +455,44 @@ for repositories whose `pyproject.toml` is their authoritative audit input.
454
455
 
455
456
  Wildcard rule (`rule_id: "*"`) requires a `file` or `paths` scope — you cannot disable a rule globally.
456
457
 
458
+ ## Extending the standards mapping
459
+
460
+ The shipped mapping table lives in `data/standards.yaml` and covers the rules
461
+ this project curates. Semgrep alone publishes thousands, so point
462
+ `standards_overlay` at your own file to map or correct a rule without waiting
463
+ for a release:
464
+
465
+ ```json
466
+ { "standards_overlay": "security/standards-overlay.yaml" }
467
+ ```
468
+
469
+ ```yaml
470
+ version: 1
471
+ entries:
472
+ - scanner: semgrep
473
+ rule_id: python.lang.security.audit.my-rule
474
+ canonical_cwe: CWE-22
475
+ owasp_top10: A01
476
+ asvs_section: V12.3.1
477
+ nist_ssdf: PW.5.1
478
+ short_desc: Path traversal in our request handler.
479
+ fix_hint: Resolve the path and contain it under the upload root.
480
+ ```
481
+
482
+ An overlay entry wins over the shipped table for the fields it sets, and an
483
+ adapter asserting its own CWE still wins over both.
484
+
485
+ **An overlay cannot set `severity`, `confidence` or `category`**, and a file
486
+ that tries is refused with the reason rather than ignored. Those three are the
487
+ scoring inputs: an overlay that set them could move the grade, which is the
488
+ hole [D32](docs/decisions.md) closed on the configuration side. An overlay says
489
+ *what weakness a rule describes*; it does not say *how much it counts*. Set
490
+ severity policy with `severity_overrides` in a config kept outside the audited
491
+ tree.
492
+
493
+ A declared overlay that cannot be read fails the run rather than being skipped,
494
+ for the same reason a malformed `.scignore.yaml` does.
495
+
457
496
  ## Baseline + incremental adoption
458
497
 
459
498
  `secure-code-baseline.json` fingerprints every current finding. On the next run:
@@ -515,7 +554,7 @@ For agents that support invokable skills, this repo ships a portable skill under
515
554
  ## GitHub Action
516
555
 
517
556
  ```yaml
518
- - uses: marshallguillory86/secure-code-agent@v0.12.9
557
+ - uses: marshallguillory86/secure-code-agent@v0.12.11
519
558
  with:
520
559
  config: secure-code-agent.json
521
560
  fail-on-gate: true
@@ -31,7 +31,11 @@ src/secure_code_audit/suppressions.py
31
31
  src/secure_code_audit/triage.py
32
32
  src/secure_code_audit/verify.py
33
33
  src/secure_code_audit/data/semgrep-offline.yaml
34
+ src/secure_code_audit/data/standards.yaml
34
35
  src/secure_code_audit/scanners/__init__.py
36
+ src/secure_code_audit/scanners/_execution.py
37
+ src/secure_code_audit/scanners/_finding_builder.py
38
+ src/secure_code_audit/scanners/_resolution.py
35
39
  src/secure_code_audit/scanners/bandit_scanner.py
36
40
  src/secure_code_audit/scanners/base.py
37
41
  src/secure_code_audit/scanners/builtin_rules.py
@@ -4,10 +4,11 @@ PyYAML<7,>=6.0.2
4
4
  secure-code-agent[required-scanners]
5
5
  pytest>=8.0
6
6
  pytest-cov>=4.0
7
- ruff==0.16.2
7
+ ruff==0.16.9
8
+ markdown>=3.5
8
9
 
9
10
  [mcp]
10
- mcp<2,>=1.0
11
+ mcp<3,>=1.0
11
12
 
12
13
  [python-scanners]
13
14
  secure-code-agent[required-scanners]
@@ -17,4 +18,4 @@ checkov<4,>=3.3
17
18
  [required-scanners]
18
19
  bandit==1.9.4
19
20
  pip-audit==2.10.1
20
- njsscan==1.0.0
21
+ njsscan==1.0.1
@@ -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.12.9"
15
+ __version__ = "0.12.11"