cra-sentinel 1.0.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 (42) hide show
  1. cra_sentinel-1.0.0/LICENSE +21 -0
  2. cra_sentinel-1.0.0/PKG-INFO +196 -0
  3. cra_sentinel-1.0.0/README.md +174 -0
  4. cra_sentinel-1.0.0/cra_sentinel/__init__.py +9 -0
  5. cra_sentinel-1.0.0/cra_sentinel/assess/__init__.py +0 -0
  6. cra_sentinel-1.0.0/cra_sentinel/assess/article14.py +314 -0
  7. cra_sentinel-1.0.0/cra_sentinel/cli.py +597 -0
  8. cra_sentinel-1.0.0/cra_sentinel/evidence/__init__.py +0 -0
  9. cra_sentinel-1.0.0/cra_sentinel/evidence/ledger.py +120 -0
  10. cra_sentinel-1.0.0/cra_sentinel/exporters/__init__.py +0 -0
  11. cra_sentinel-1.0.0/cra_sentinel/exporters/csaf.py +185 -0
  12. cra_sentinel-1.0.0/cra_sentinel/exporters/cyclonedx.py +166 -0
  13. cra_sentinel-1.0.0/cra_sentinel/exporters/notification.py +86 -0
  14. cra_sentinel-1.0.0/cra_sentinel/exporters/spdx.py +72 -0
  15. cra_sentinel-1.0.0/cra_sentinel/model.py +196 -0
  16. cra_sentinel-1.0.0/cra_sentinel/report/__init__.py +0 -0
  17. cra_sentinel-1.0.0/cra_sentinel/report/html.py +506 -0
  18. cra_sentinel-1.0.0/cra_sentinel/scanner/__init__.py +0 -0
  19. cra_sentinel-1.0.0/cra_sentinel/scanner/core.py +117 -0
  20. cra_sentinel-1.0.0/cra_sentinel/scanner/cvss.py +93 -0
  21. cra_sentinel-1.0.0/cra_sentinel/scanner/detectors.py +404 -0
  22. cra_sentinel-1.0.0/cra_sentinel/scanner/intel.py +281 -0
  23. cra_sentinel-1.0.0/cra_sentinel/server/__init__.py +0 -0
  24. cra_sentinel-1.0.0/cra_sentinel/server/app.py +167 -0
  25. cra_sentinel-1.0.0/cra_sentinel/templates.py +203 -0
  26. cra_sentinel-1.0.0/cra_sentinel/term.py +67 -0
  27. cra_sentinel-1.0.0/cra_sentinel/watchtower/__init__.py +6 -0
  28. cra_sentinel-1.0.0/cra_sentinel/watchtower/commands.py +345 -0
  29. cra_sentinel-1.0.0/cra_sentinel/watchtower/config.py +106 -0
  30. cra_sentinel-1.0.0/cra_sentinel/watchtower/dashboard.py +171 -0
  31. cra_sentinel-1.0.0/cra_sentinel/watchtower/notify.py +242 -0
  32. cra_sentinel-1.0.0/cra_sentinel/watchtower/runner.py +263 -0
  33. cra_sentinel-1.0.0/cra_sentinel/watchtower/store.py +395 -0
  34. cra_sentinel-1.0.0/cra_sentinel.egg-info/PKG-INFO +196 -0
  35. cra_sentinel-1.0.0/cra_sentinel.egg-info/SOURCES.txt +40 -0
  36. cra_sentinel-1.0.0/cra_sentinel.egg-info/dependency_links.txt +1 -0
  37. cra_sentinel-1.0.0/cra_sentinel.egg-info/entry_points.txt +3 -0
  38. cra_sentinel-1.0.0/cra_sentinel.egg-info/top_level.txt +1 -0
  39. cra_sentinel-1.0.0/pyproject.toml +35 -0
  40. cra_sentinel-1.0.0/setup.cfg +4 -0
  41. cra_sentinel-1.0.0/tests/test_suite.py +439 -0
  42. cra_sentinel-1.0.0/tests/test_watchtower.py +246 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CRA Sentinel
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,196 @@
1
+ Metadata-Version: 2.4
2
+ Name: cra-sentinel
3
+ Version: 1.0.0
4
+ Summary: EU Cyber Resilience Act compliance scanner: SBOM, actively-exploited detection, Article 14 evidence
5
+ License: MIT
6
+ Project-URL: Homepage, https://tomvallat.github.io/cra-sentinel/
7
+ Project-URL: Repository, https://github.com/tomvallat/cra-sentinel
8
+ Project-URL: Issues, https://github.com/tomvallat/cra-sentinel/issues
9
+ Keywords: cra,cyber-resilience-act,sbom,cyclonedx,spdx,csaf,vex,compliance,eu
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Legal Industry
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Security
17
+ Classifier: Topic :: Software Development :: Quality Assurance
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Dynamic: license-file
22
+
23
+ # CRA Sentinel
24
+
25
+ **Cyber Resilience Act compliance for products with digital elements.**
26
+ Zero dependencies. One command. Evidence an auditor will accept.
27
+
28
+ ```
29
+ pip install cra-sentinel
30
+ cra scan . --report cra-report.html --sbom sbom.cdx.json
31
+ ```
32
+
33
+ ---
34
+
35
+ ## Why this exists
36
+
37
+ Regulation (EU) 2024/2847 applies to every manufacturer placing a product with
38
+ digital elements on the EU market — including manufacturers established outside
39
+ the EU, and including products already on the market.
40
+
41
+ | Date | Obligation |
42
+ |------|------------|
43
+ | **11 September 2026** | Article 14: report actively exploited vulnerabilities within **24 hours** to ENISA and the national CSIRT, full notification within 72 hours, final report within 14 days of a corrective measure |
44
+ | 11 June 2027 | Conformity assessment provisions |
45
+ | **11 December 2027** | Full application: Annex I essential requirements, CE marking |
46
+
47
+ Most manufacturers cannot comply, for a mundane reason: they have no SBOM, no
48
+ vulnerability-monitoring process, and no record of the decisions they have made.
49
+ The regulation does not require you to be free of vulnerabilities. It requires
50
+ you to **know what is in your product, watch it, decide, and be able to show the
51
+ decision.**
52
+
53
+ That last part is what tools usually skip. A vulnerability scan is not evidence.
54
+ A documented triage decision is.
55
+
56
+ ## What it does
57
+
58
+ **Builds the inventory.** Resolves components from npm, PyPI, Go, Cargo, Maven,
59
+ Composer, RubyGems, NuGet — lockfiles preferred over manifests, because the SBOM
60
+ must describe what ships, not what was requested.
61
+
62
+ **Separates "vulnerable" from "actively exploited".** Every finding is enriched
63
+ from OSV.dev, then intersected with the CISA Known Exploited Vulnerabilities
64
+ catalogue. Only that intersection starts an Article 14 clock, and the tool says
65
+ so explicitly rather than drowning you in 200 undifferentiated CVEs.
66
+
67
+ **Computes its own severity.** CVSS v3.1 base scores are calculated locally from
68
+ the vector, validated against the published reference values, because under
69
+ Annex I you must be able to justify your own severity assessment.
70
+
71
+ **Assesses 14 controls against the actual text.** Each one names its article —
72
+ Article 14(1)(a), Annex I Part II(2), Article 13(8) — and reports Pass, Partial,
73
+ Fail, or *Attest* for what no tool can verify. Manual checks are excluded from
74
+ the score rather than silently counted as failures.
75
+
76
+ **Keeps an append-only evidence ledger.** Every triage decision is recorded with
77
+ its rationale, author and timestamp. A `not_affected` verdict is refused without
78
+ a CSAF justification, because an auditor will ask for one.
79
+
80
+ **Exports the four formats that matter.** CycloneDX 1.6 (with VEX analysis
81
+ inline), SPDX 2.3, CSAF 2.0 advisories, and a pre-filled Article 14 notification
82
+ draft so the 24-hour window is spent deciding, not formatting.
83
+
84
+ ## Commands
85
+
86
+ ```bash
87
+ cra scan . # scan and assess
88
+ cra scan . --report r.html --sbom sbom.cdx.json --csaf advisory.json
89
+ cra scan . --fail-on exploited # CI gate: non-zero if a KEV component ships
90
+ cra scan . --fail-on score --min-score 75
91
+
92
+ cra init --contact security@acme.eu --ci
93
+ # scaffold SECURITY.md, the Article 14 runbook,
94
+ # security.txt and a CI workflow
95
+
96
+ cra triage CVE-2021-44228 --status affected \
97
+ -r "log4j-core is bundled in the firmware; JNDI reachable from the syslog parser" \
98
+ --plan "Upgrade to 2.17.1 in 3.2.2" --target-date 2026-09-24
99
+
100
+ cra triage CVE-2021-45046 --status not_affected \
101
+ --justification vulnerable_code_not_in_execute_path \
102
+ -r "Lookups disabled at build time via log4j2.formatMsgNoLookups"
103
+
104
+ cra ledger --history # the audit trail
105
+ cra notify CVE-2021-44228 # Article 14 early-warning draft
106
+ cra advisory --only-exploited # CSAF 2.0 advisory to publish
107
+ cra watch --fail-on-new # diff against baseline; alert on new exploitation
108
+ cra serve # local dashboard for non-terminal colleagues
109
+ cra deadlines # where you are in the timeline
110
+ ```
111
+
112
+ ## Exit codes
113
+
114
+ `0` clean · `1` threshold breached · `2` error. Use `--fail-on` to turn a scan
115
+ into a release gate.
116
+
117
+ ## Design decisions worth knowing
118
+
119
+ **Zero dependencies.** Standard library only. It installs inside an air-gapped
120
+ build environment and it will still run in 2031, which matters when the support
121
+ period you declared is five years.
122
+
123
+ **`--offline` is real.** Advisory data is cached to `.cra-sentinel/cache/`. On a
124
+ network failure the scan degrades to the cache and says so in the report rather
125
+ than silently reporting zero findings.
126
+
127
+ **A malformed manifest never aborts a scan.** A compliance scan that crashes on
128
+ one bad `pom.xml` is worse than useless in CI.
129
+
130
+ **The HTML report is one self-contained file.** No CDN, no fonts, no tracking.
131
+ It survives being emailed to a notified body and printed to PDF. Dark and light
132
+ themes, readable at 400px.
133
+
134
+ **Nothing leaves your machine except package coordinates.** Component names and
135
+ versions are sent to OSV.dev to query advisories. No source code, no telemetry,
136
+ no account.
137
+
138
+ ## Continuous monitoring
139
+
140
+ A scan you run by hand is not monitoring. `cra watchtower` sweeps a portfolio
141
+ of products on a schedule, records the **moment of awareness** when a component
142
+ becomes actively exploited — the fact from which every Article 14 deadline runs
143
+ — and alerts by email or webhook, escalating until someone acknowledges.
144
+
145
+ ```bash
146
+ cra watchtower init
147
+ cra watchtower add "Acme — Gateway 3.2.1" --source https://github.com/acme/gw.git
148
+ cra watchtower run # put this on a timer
149
+ cra watchtower status # what is on the clock right now
150
+ cra watchtower ack acme-gateway-321 CVE-2021-44228 --by tom --note "not affected"
151
+ cra watchtower dashboard # portfolio view
152
+ ```
153
+
154
+ The awareness timestamp is written **before** delivery is attempted: if SMTP is
155
+ down the alert does not arrive, but the evidence still exists. Deployment units
156
+ for systemd and cron are in `deploy/`.
157
+
158
+ ## Troubleshooting
159
+
160
+ **`TLS certificate verification failed` on macOS.** Python installed from
161
+ python.org ships without a populated system trust store. CRA Sentinel falls back
162
+ to `certifi` automatically when it is importable; otherwise run the installer's
163
+ one-time fix:
164
+
165
+ ```bash
166
+ /Applications/Python\ 3.x/Install\ Certificates.command
167
+ # or
168
+ pip install certifi
169
+ ```
170
+
171
+ The scanner never reports a clean result it could not verify — a scan with no
172
+ reachable advisory source is marked **Unverified** in both the terminal and the
173
+ report, and the affected controls report *Attest* rather than *Pass*.
174
+
175
+ **Python version.** Requires 3.10 or later. Tested on 3.10 and 3.14.
176
+
177
+ ## Scope and limitations
178
+
179
+ This covers third-party component risk — the part of Annex I that is mechanically
180
+ checkable. It does **not** assess first-party source code, hardware, cryptographic
181
+ implementation, or the organisational measures in Annex I Part I. Checks marked
182
+ *Attest* remain the manufacturer's responsibility, and the tool says so in the
183
+ report rather than implying coverage it does not have.
184
+
185
+ Automated output supports, and does not replace, the technical documentation
186
+ required under Annex VII. It is not legal advice.
187
+
188
+ ## Development
189
+
190
+ ```bash
191
+ python3 tests/test_suite.py # 33 tests, offline, no network required
192
+ ```
193
+
194
+ ## Licence
195
+
196
+ MIT.
@@ -0,0 +1,174 @@
1
+ # CRA Sentinel
2
+
3
+ **Cyber Resilience Act compliance for products with digital elements.**
4
+ Zero dependencies. One command. Evidence an auditor will accept.
5
+
6
+ ```
7
+ pip install cra-sentinel
8
+ cra scan . --report cra-report.html --sbom sbom.cdx.json
9
+ ```
10
+
11
+ ---
12
+
13
+ ## Why this exists
14
+
15
+ Regulation (EU) 2024/2847 applies to every manufacturer placing a product with
16
+ digital elements on the EU market — including manufacturers established outside
17
+ the EU, and including products already on the market.
18
+
19
+ | Date | Obligation |
20
+ |------|------------|
21
+ | **11 September 2026** | Article 14: report actively exploited vulnerabilities within **24 hours** to ENISA and the national CSIRT, full notification within 72 hours, final report within 14 days of a corrective measure |
22
+ | 11 June 2027 | Conformity assessment provisions |
23
+ | **11 December 2027** | Full application: Annex I essential requirements, CE marking |
24
+
25
+ Most manufacturers cannot comply, for a mundane reason: they have no SBOM, no
26
+ vulnerability-monitoring process, and no record of the decisions they have made.
27
+ The regulation does not require you to be free of vulnerabilities. It requires
28
+ you to **know what is in your product, watch it, decide, and be able to show the
29
+ decision.**
30
+
31
+ That last part is what tools usually skip. A vulnerability scan is not evidence.
32
+ A documented triage decision is.
33
+
34
+ ## What it does
35
+
36
+ **Builds the inventory.** Resolves components from npm, PyPI, Go, Cargo, Maven,
37
+ Composer, RubyGems, NuGet — lockfiles preferred over manifests, because the SBOM
38
+ must describe what ships, not what was requested.
39
+
40
+ **Separates "vulnerable" from "actively exploited".** Every finding is enriched
41
+ from OSV.dev, then intersected with the CISA Known Exploited Vulnerabilities
42
+ catalogue. Only that intersection starts an Article 14 clock, and the tool says
43
+ so explicitly rather than drowning you in 200 undifferentiated CVEs.
44
+
45
+ **Computes its own severity.** CVSS v3.1 base scores are calculated locally from
46
+ the vector, validated against the published reference values, because under
47
+ Annex I you must be able to justify your own severity assessment.
48
+
49
+ **Assesses 14 controls against the actual text.** Each one names its article —
50
+ Article 14(1)(a), Annex I Part II(2), Article 13(8) — and reports Pass, Partial,
51
+ Fail, or *Attest* for what no tool can verify. Manual checks are excluded from
52
+ the score rather than silently counted as failures.
53
+
54
+ **Keeps an append-only evidence ledger.** Every triage decision is recorded with
55
+ its rationale, author and timestamp. A `not_affected` verdict is refused without
56
+ a CSAF justification, because an auditor will ask for one.
57
+
58
+ **Exports the four formats that matter.** CycloneDX 1.6 (with VEX analysis
59
+ inline), SPDX 2.3, CSAF 2.0 advisories, and a pre-filled Article 14 notification
60
+ draft so the 24-hour window is spent deciding, not formatting.
61
+
62
+ ## Commands
63
+
64
+ ```bash
65
+ cra scan . # scan and assess
66
+ cra scan . --report r.html --sbom sbom.cdx.json --csaf advisory.json
67
+ cra scan . --fail-on exploited # CI gate: non-zero if a KEV component ships
68
+ cra scan . --fail-on score --min-score 75
69
+
70
+ cra init --contact security@acme.eu --ci
71
+ # scaffold SECURITY.md, the Article 14 runbook,
72
+ # security.txt and a CI workflow
73
+
74
+ cra triage CVE-2021-44228 --status affected \
75
+ -r "log4j-core is bundled in the firmware; JNDI reachable from the syslog parser" \
76
+ --plan "Upgrade to 2.17.1 in 3.2.2" --target-date 2026-09-24
77
+
78
+ cra triage CVE-2021-45046 --status not_affected \
79
+ --justification vulnerable_code_not_in_execute_path \
80
+ -r "Lookups disabled at build time via log4j2.formatMsgNoLookups"
81
+
82
+ cra ledger --history # the audit trail
83
+ cra notify CVE-2021-44228 # Article 14 early-warning draft
84
+ cra advisory --only-exploited # CSAF 2.0 advisory to publish
85
+ cra watch --fail-on-new # diff against baseline; alert on new exploitation
86
+ cra serve # local dashboard for non-terminal colleagues
87
+ cra deadlines # where you are in the timeline
88
+ ```
89
+
90
+ ## Exit codes
91
+
92
+ `0` clean · `1` threshold breached · `2` error. Use `--fail-on` to turn a scan
93
+ into a release gate.
94
+
95
+ ## Design decisions worth knowing
96
+
97
+ **Zero dependencies.** Standard library only. It installs inside an air-gapped
98
+ build environment and it will still run in 2031, which matters when the support
99
+ period you declared is five years.
100
+
101
+ **`--offline` is real.** Advisory data is cached to `.cra-sentinel/cache/`. On a
102
+ network failure the scan degrades to the cache and says so in the report rather
103
+ than silently reporting zero findings.
104
+
105
+ **A malformed manifest never aborts a scan.** A compliance scan that crashes on
106
+ one bad `pom.xml` is worse than useless in CI.
107
+
108
+ **The HTML report is one self-contained file.** No CDN, no fonts, no tracking.
109
+ It survives being emailed to a notified body and printed to PDF. Dark and light
110
+ themes, readable at 400px.
111
+
112
+ **Nothing leaves your machine except package coordinates.** Component names and
113
+ versions are sent to OSV.dev to query advisories. No source code, no telemetry,
114
+ no account.
115
+
116
+ ## Continuous monitoring
117
+
118
+ A scan you run by hand is not monitoring. `cra watchtower` sweeps a portfolio
119
+ of products on a schedule, records the **moment of awareness** when a component
120
+ becomes actively exploited — the fact from which every Article 14 deadline runs
121
+ — and alerts by email or webhook, escalating until someone acknowledges.
122
+
123
+ ```bash
124
+ cra watchtower init
125
+ cra watchtower add "Acme — Gateway 3.2.1" --source https://github.com/acme/gw.git
126
+ cra watchtower run # put this on a timer
127
+ cra watchtower status # what is on the clock right now
128
+ cra watchtower ack acme-gateway-321 CVE-2021-44228 --by tom --note "not affected"
129
+ cra watchtower dashboard # portfolio view
130
+ ```
131
+
132
+ The awareness timestamp is written **before** delivery is attempted: if SMTP is
133
+ down the alert does not arrive, but the evidence still exists. Deployment units
134
+ for systemd and cron are in `deploy/`.
135
+
136
+ ## Troubleshooting
137
+
138
+ **`TLS certificate verification failed` on macOS.** Python installed from
139
+ python.org ships without a populated system trust store. CRA Sentinel falls back
140
+ to `certifi` automatically when it is importable; otherwise run the installer's
141
+ one-time fix:
142
+
143
+ ```bash
144
+ /Applications/Python\ 3.x/Install\ Certificates.command
145
+ # or
146
+ pip install certifi
147
+ ```
148
+
149
+ The scanner never reports a clean result it could not verify — a scan with no
150
+ reachable advisory source is marked **Unverified** in both the terminal and the
151
+ report, and the affected controls report *Attest* rather than *Pass*.
152
+
153
+ **Python version.** Requires 3.10 or later. Tested on 3.10 and 3.14.
154
+
155
+ ## Scope and limitations
156
+
157
+ This covers third-party component risk — the part of Annex I that is mechanically
158
+ checkable. It does **not** assess first-party source code, hardware, cryptographic
159
+ implementation, or the organisational measures in Annex I Part I. Checks marked
160
+ *Attest* remain the manufacturer's responsibility, and the tool says so in the
161
+ report rather than implying coverage it does not have.
162
+
163
+ Automated output supports, and does not replace, the technical documentation
164
+ required under Annex VII. It is not legal advice.
165
+
166
+ ## Development
167
+
168
+ ```bash
169
+ python3 tests/test_suite.py # 33 tests, offline, no network required
170
+ ```
171
+
172
+ ## Licence
173
+
174
+ MIT.
@@ -0,0 +1,9 @@
1
+ """CRA Sentinel — EU Cyber Resilience Act compliance scanner.
2
+
3
+ Regulation (EU) 2024/2847 obliges manufacturers of products with digital
4
+ elements to inventory their components, handle vulnerabilities, and report
5
+ actively exploited ones within 24 hours. This tool produces the evidence.
6
+ """
7
+
8
+ __version__ = "1.0.0"
9
+ __all__ = ["__version__"]
File without changes