- SPDX 3.0 detection and field validation against BSI TR-03183-2 v2.1.0 in
sbom-generation. Detects viaCreationInfo.specVersion, validatesSbomrootElement chain, per-Package required fields (name, version, supplier, license, checksums) with first-match-wins alias resolution and Relationship traversal (hasConcludedLicense,hasSuppliedBy,hasOriginatedBy,hasDeclaredLicense). Synthetic fixtures and the pilot 0006 real-Yocto fixture exercise the full validator; pilot 0006 scores 20/50 because Yocto Scarthgap'screate-spdx-3.0emission omitshasSuppliedByRelationships and per-PackageverifiedUsing(the gap is documented inaudits/0003-spdx3-mapping/upstream-poky-spdx3.mdwith a drafted dual-emit patch series for openembedded-core). - Audit document
audits/0003-spdx3-mapping/upstream-poky-spdx3.mdcoveringgit logwalks against poky scarthgap, walnascar, and master since the Scarthgap pin, the smallest upstream patch that would close the SPDX 3.0 emission gap to reach 50/50 against the BSI v2.1.0 mapping, and submission guidance for the openembedded-core list.
Pilot: pilots/0006-poky-scarthgap-spdx3/REPORT.md
image-featurescheck detecting insecureIMAGE_FEATURESentries (debug-tweaksand similar).hardening-flagscheck detecting global compile-time hardening evidence (security_flags.incinclusion +TUNE_CCARGSparsing).pyproject.tomlnow declares[build-system]withuv_buildbackend and asource-includeglob forsrc/shipcheck/**/*.yaml, fixing the v0.0.4 wheel that shipped withoutlicense_categories.yamlorcra/requirements.yaml. (#2 by @threexc)
- Merged
secure-bootandimage-signingchecks into a singlecode-integritycheck covering UEFI Secure Boot, signed FIT, dm-verity, and IMA/EVM. Migration:sed -i -e 's/^secure_boot:/code_integrity:/' -e '/^image_signing:/d' .shipcheck.yaml(and merge any per-key overrides manually).
secure_boot:andimage_signing:configuration sections in.shipcheck.yamlno longer accepted.
vuln-reportingnow emits findings for placeholder tokens (VENDOR,TODO,FIXME,[TO BE FILLED],[VENDOR]) in any required field, and for malformed values inproduct.yamlfields previously accepted on presence alone:cvd.policy_urlmust parse ashttp://,https://, ormailto:;cvd.contactmust be email-shaped (local@domain.tld) or URL-shaped;support_period.end_datemust parse as ISO 8601YYYY-MM-DD. Placeholder matching is case-insensitive against the trimmed value. Findings cite Annex I Part II §5 (CVD policy), Annex II §2 (SPoC), Annex II §7 (support period), and Annex I Part II §7 (update distribution).
- Unparseable
support_period.end_dateinproduct.yamlnow emits ahigh-severity finding citing Annex II §7 rather than silently skipping the expired-date branch.
- Secure Boot audit check: detects signing class configuration, flags test/development keys, catches EFI artifacts without signing enabled
- Image Signing check: detects FIT image signatures (U-Boot) and dm-verity configuration
secure_bootandimage_signingconfiguration sections in.shipcheck.yaml- Readiness score now includes Secure Boot (50pts) and Image Signing (50pts), total max 200
- CRA requirement mapping metadata on every
FindingandCheckResultvia newcra_mapping: list[str]field, with static CRA catalog transcribed verbatim from Regulation (EU) 2024/2847 (Annex I Part I items a-m, Part II items 1-8, Annex II items 1-9, Annex VII items 1-8) --format evidencerenderer that pivots findings by CRA requirement instead of by check, with explicit "Gaps" section enumerating unmapped requirements--out DIRoption oncheckthat emits a multi-file compliance dossier (evidence report, license audit, CVE report, Annex VII technical documentation, Declaration of Conformity,scan.json)license-auditcheck parsing Yocto's human-readabletmp/deploy/licenses/*/license.manifest(complements the machine-readable SPDX SBOM check)yocto-cve-checkcheck integrating with Yocto'scve-check.bbclassoutput attmp/log/cve/cve-summary.json, version-tolerant across Kirkstone and Scarthgap schemas- CVE finding reconciliation:
shipcheck checkmerges duplicate findings fromcve-trackingandyocto-cve-checkinto a single finding whosesourceslists every scanner that flagged it - SQLite scan history store at
.shipcheck/history.dbpersisting every scan record shipcheck dossiersubcommand producing a multi-scan trend report (scan cadence, score trend, CVE velocity, licence drift)shipcheck docssubcommand generating an Annex VII technical documentation draft from scan evidence plusproduct.yamlshipcheck doc declarationsubcommand generating Annex V (full) and Annex VI (simplified) Declaration of Conformity templatesvuln-reportingcheck validating Article 14 / Annex I Part II §§4-8 documentation obligations (CVD policy, SPoC, support period, update distribution)shipcheck initscaffold now lists all 7 v0.3 checks and templates thelicense_audit,yocto_cve,history,vuln_reporting, andproduct_config_pathsections with v0.3 usage examples- README rewritten with install, quickstart, check catalog, subcommand summary, and a pointer to the OpenSSF CRA Yocto rules catalog (was a 5-line stub)
- Pilot testing methodology (
docs/pilot.md) documenting when pilots are required, kas-container bootstrap with cache reuse (DL_DIR,SSTATE_DIR,KAS_REPO_REF_DIR), NVD API key passthrough, the per-pilot artefact layout, and the gating rules that tie pilot completion to release tags. - First pilot report (
pilots/0001-poky-scarthgap-min/REPORT.md) validating the v0.1 check set against a real poky Scarthgapcore-image-minimalbuild withINHERIT += "create-spdx cve-check". All seven registered check IDs executed without raising. - Pilots directory convention at repo root (
pilots/NNNN-<short-name>/) containingkas.yml,log.txt,scan.json,REPORT.md, and adossier/subdirectory with the full--outevidence bundle.
CheckStatusenum extended withERRORmember for checks whose input is structurally unreadable (previously had PASS/WARN/FAIL/SKIP only)BaseCheck.produces_cve_findings: ClassVar[bool] = Falsetrait declares which checks emit CVE findings; the dossier CVE filter and CVE-velocity counter now derive their producer set from this flag instead of a hardcoded ID list- README Roadmap now links to
pilots/0001-poky-scarthgap-min/REPORT.mdinstead of the "pending - first pilot run is in progress" placeholder. - Added a "Known limitations" subsection to README under "What it checks" enumerating documented scope boundaries surfaced by pilot 0001 (
vuln-reportingrequiresproduct.yaml,secure-bootis config-level only,image-signingis config-level only,sbom-generationaccepts SPDX 2.x,cve-tracking/yocto-cve-checkfile-lookup divergence). - BREAKING:
shipcheck check --format jsonnow writes the JSON payload to stdout instead of silently creating./shipcheck-report.jsonin the current working directory; callers that relied on the file side-effect must switch to shell redirection (--format json > report.json) or pass--out DIRfor the dossier bundle. (Pilot: pilots/0001-poky-scarthgap-min/REPORT.md#re-run-2026-04-20) - README now explicitly distinguishes readiness score from CRA compliance and enumerates what shipcheck is NOT - see "What shipcheck is not" and "Readiness is not compliance" sections.
- Dossier CVE-velocity counter now matches the registered
cve-trackingcheck ID (previously matched the never-registeredcve-scanand silently undercounted) shipcheck check --format jsonrouted the JSON payload to a silent./shipcheck-report.jsonside-effect instead of stdout, so shell redirection (> scan.json) captured an empty stream and CI pipelines lost the result. JSON now prints to stdout and suppresses the Rich terminal report when--outis not set. (PF-01; Pilot: pilots/0001-poky-scarthgap-min/REPORT.md#re-run-2026-04-20)cve-trackingandyocto-cve-checkdiverged on the same build because each check implemented its own discovery logic and onlyyocto-cve-checklooked attmp/log/cve/cve-summary.json. Both checks now shareshipcheck.checks._cve_discovery.discover_cve_output()and agree on evidence presence. (PF-02; Pilot: pilots/0001-poky-scarthgap-min/REPORT.md#re-run-2026-04-20)license-auditreturned SKIP on real Yocto builds because_discover_image_dir()only searched the top level oftmp/deploy/licenses/and missed the per-architecture layout (tmp/deploy/licenses/<arch>/<pkg-or-image>/license.manifest). Discovery now walks the tree recursively viaPath.rglob("license.manifest")and selects the newest-mtime manifest. (PF-03; Pilot: pilots/0001-poky-scarthgap-min/REPORT.md#re-run-2026-04-20)
- SBOM generation check: validates SPDX 2.3 documents against BSI TR-03183-2 field requirements
- SPDX 3.0 and CycloneDX format detection (detection-only, no field validation)
- CVE tracking check: consumes Yocto cve-check, vex.bbclass, and sbom-cve-check JSON output
- CVE severity classification with CVSS bands (critical/high/medium/low)
- CVE suppression via
.shipcheck.yamlconfiguration - Compliance report with readiness score (0-100)
- Terminal output (Rich), markdown, JSON, and HTML report formats
--fail-onseverity-gated exit codes for CI pipeline integrationshipcheck checkcommand with--build-dir,--format,--checks,--fail-onoptionsshipcheck initcommand to generate.shipcheck.yamlscaffold.shipcheck.yamlconfiguration file with per-check overrides- BaseCheck plugin architecture with check registry
- Migrated from hatchling to uv-native packaging
- Added ty type checking to CI pipeline
- Fixed CI
uv syncto include dev dependency group