cra-scan
SBOM + exploited-vulnerability check for Swift / Apple-platform projects, built for the EU Cyber Resilience Act (CRA). The open-source core of Pinwatch.
- Reads Swift Package Manager
Package.resolved(formats v1–v3) and CocoaPodsPodfile.lock - Writes a CycloneDX 1.6 SBOM
- Checks every pinned Swift package against OSV and flags vulnerabilities that CISA KEV or ENISA's EUVD list as exploited, plus EPSS exploit probability
- Pure Python 3.9+, no dependencies, no account, no telemetry
Install & run
pipx install cra-scan # or: pip install cra-scan
cra-scan scan path/to/MyApp --product "My App" --product-version 1.4 --supplier "My Studio"
cra-scan check sbom.cdx.json --format markdown # re-check an existing SBOM
Exit codes: 0 ok · 1 findings at/above --fail-on (default exploited) · 2 input error · 3 feed unreachable.
Levels: exploited (CISA KEV or ENISA EUVD lists it as exploited — if your product is affected, CRA Art. 14 reporting applies: 24 h early warning, 72 h notification, final report within 14 days of a fix) · high (EPSS ≥ 0.10 or CVSS ≥ 9.0) · known (any published advisory for the pinned version).
Coverage: Swift packages are matched through OSV's SwiftURL ecosystem (GitHub advisory database). CocoaPods pods are
listed in the SBOM but not yet matched — there is no public advisory feed for them; v0.2 will map pods to their source repos.
Feeds are cached in ~/.cache/cra-scan for 12 h (CRA_SCAN_CACHE overrides).
GitHub Action
- uses: actions/checkout@v4
- uses: stavrop/cra-scan@v0
with: {product: "My App", version: "1.4", fail-on: exploited}
The report is added to the job summary; output worst = none | known | high | exploited.
Development
python3 -m unittest discover -s tests
Licence: Apache-2.0. Not legal advice — you remain the manufacturer responsible for your product's conformity.
Metadata
Release files for cra-scan 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cra_scan-0.1.0.tar.gz | 13.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cra_scan-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.1 kB
Release files / cra_scan-0.1.0.tar.gz
| Download URL | cra_scan-0.1.0.tar.gz |
|---|---|
| Size | 13.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8e53a7c398945c6aedacd938b79f18d5ff5d47258d56d45ef589b67e45934592
|
|
BLAKE2b-256 checksum How to use checksums |
a9e1ceaedfea9a7a00ae52070a8f9927b616101ff9c18235fd304d75a4f8f8f6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.
Transparency logRelease files / cra_scan-0.1.0-py3-none-any.whl
| Download URL | cra_scan-0.1.0-py3-none-any.whl |
|---|---|
| Size | 13.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ffcb40a93a7bfda23294d35f5c46201fb90c261913341d6f0ae6e2a20056f749
|
|
BLAKE2b-256 checksum How to use checksums |
babde7fd5f36cd29a8f280ec4d237d072539b7b5e08ea790b2dee48896580a24
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.
Transparency log