Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 0 additions & 68 deletions .cfusa-hara.json

This file was deleted.

132 changes: 132 additions & 0 deletions .fusa-hara.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
{
"project": "c-FuSa",
"standard": "iso26262",
"createdAt": "2026-06-09T18:34:23Z",
"operationalSituations": [
{
"id": "OS-001",
"description": "Developer runs cfusa check/lint in CI or as a pre-commit gate as the sole safety-relevant static analysis step for a change"
},
{
"id": "OS-002",
"description": "Developer runs cfusa impact locally against a git repository, passing --from/--to ref arguments that may originate from an untrusted source (e.g. a CI job templated from a pull request)"
},
{
"id": "OS-003",
"description": "cfusa release/qualify artifacts (SBOM, provenance, qualification record) are generated and submitted as evidence into an external safety case or certification package"
},
{
"id": "OS-004",
"description": "Developer manually computes an ASIL rating via cfusa hara asil from S/E/C parameters during hazard analysis"
}
],
"hazards": [
{
"id": "H-001",
"description": "Tool reports no violations on a file that contains real safety violations (false-negative), leading the developer to believe code is safe when it is not",
"source": "c-FuSa self-analysis",
"situations": ["OS-001"],
"risk": {
"severity": "S3",
"exposure": "E4",
"controllability": "C2",
"asil": "ASIL-D"
},
"safetyGoals": ["SG-001"]
},
{
"id": "H-002",
"description": "Tool reports excessive false-positives, causing the developer to disable checks or ignore findings, masking real violations",
"source": "c-FuSa self-analysis",
"situations": ["OS-001"],
"risk": {
"severity": "S2",
"exposure": "E4",
"controllability": "C3",
"asil": "ASIL-D"
},
"safetyGoals": ["SG-002"]
},
{
"id": "H-003",
"description": "Command injection via unsanitised --from/--to git refs passed to popen(), allowing arbitrary shell execution on the developer's machine",
"source": "c-FuSa self-analysis / cyber review",
"situations": ["OS-002"],
"risk": {
"severity": "S3",
"exposure": "E2",
"controllability": "C1",
"asil": "ASIL-B"
},
"safetyGoals": ["SG-003"]
},
{
"id": "H-004",
"description": "SBOM or qualification record is generated with incorrect checksums or version info, leading to incorrect evidence being submitted to a safety case",
"source": "c-FuSa self-analysis",
"situations": ["OS-003"],
"risk": {
"severity": "S2",
"exposure": "E3",
"controllability": "C2",
"asil": "ASIL-B"
},
"safetyGoals": ["SG-004"]
},
{
"id": "H-005",
"description": "Incorrect ASIL determination output (wrong table lookup) causes the developer to under-design safety measures for a hazardous item",
"source": "c-FuSa self-analysis",
"situations": ["OS-004"],
"risk": {
"severity": "S3",
"exposure": "E3",
"controllability": "C2",
"asil": "ASIL-D"
},
"safetyGoals": ["SG-005"]
}
],
"safetyGoals": [
{
"id": "SG-001",
"description": "cfusa shall not suppress or omit any finding for which the rule engine is configured to detect",
"hazards": ["H-001"],
"asil": "ASIL-D",
"safeState": "Developer independently reviews code and uses additional static analysis tools",
"fssrRefs": ["REQ-FSR-CHECK001"]
},
{
"id": "SG-002",
"description": "cfusa shall limit its false-positive rate to a level that does not cause systematic check-disabling",
"hazards": ["H-002"],
"asil": "ASIL-D",
"safeState": "Developer uses the disposition system to explicitly accept findings with rationale",
"fssrRefs": ["REQ-FSR-CHECK002"]
},
{
"id": "SG-003",
"description": "cfusa impact shall validate all git ref arguments before constructing shell commands",
"hazards": ["H-003"],
"asil": "ASIL-B",
"safeState": "validate_git_ref() whitelist prevents injection; the tool exits 1 with an error message",
"fssrRefs": ["REQ-IMP001"]
},
{
"id": "SG-004",
"description": "cfusa release/qualify shall compute SHA-256 checksums deterministically and embed the correct project/version from .fusa.json",
"hazards": ["H-004"],
"asil": "ASIL-B",
"safeState": "Reviewer independently verifies SBOM checksums against source",
"fssrRefs": ["REQ-REL002", "REQ-UTIL015"]
},
{
"id": "SG-005",
"description": "cfusa hara asil shall implement ISO 26262-3:2018 Table 4 correctly for all S/E/C combinations",
"hazards": ["H-005"],
"asil": "ASIL-D",
"safeState": "Developer cross-checks the ASIL result with ISO 26262-3:2018 Table 4 directly",
"fssrRefs": ["REQ-HARA009"]
}
]
}
32 changes: 31 additions & 1 deletion .fusa-reqs.json
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,36 @@
{"id":"REQ-VULN005","title":"cfusa vuln --format json output contains the detected findings","standard":"c-FuSa CLI","level":"ASIL-A"},
{"id":"REQ-VULN006","title":"cfusa vuln --output-dir writes the vulnerability report to the given directory","standard":"c-FuSa CLI","level":"ASIL-A"},
{"id":"REQ-VULN007","title":"cfusa vuln --format text writes findings to an output file","standard":"c-FuSa CLI","level":"ASIL-A"},
{"id":"REQ-VULN008","title":"cfusa vuln word-boundary matching avoids false positives on substrings of vulnerable function names","standard":"c-FuSa CLI","level":"ASIL-A"}
{"id":"REQ-VULN008","title":"cfusa vuln word-boundary matching avoids false positives on substrings of vulnerable function names","standard":"c-FuSa CLI","level":"ASIL-A"},

{"id":"REQ-QB001","title":"qualitybar FUSA-STUB001 deny-list scan detects bracket placeholders and instructional substrings","standard":"x-FuSa spec §1.6.1","level":"ASIL-D"},
{"id":"REQ-QB002","title":"qualitybar FUSA-STUB002 distinct-value-ratio check flags <0.1 ratio across >=10 entries","standard":"x-FuSa spec §1.6.1","level":"ASIL-B"},
{"id":"REQ-QB003","title":"qualitybar content hash is deterministic and sha256:-prefixed","standard":"x-FuSa spec §1.6.2","level":"ASIL-B"},
{"id":"REQ-QB004","title":"qualitybar attestation validity requires independent reviewer and a non-stale content hash","standard":"x-FuSa spec §1.6.2","level":"ASIL-B"},
{"id":"REQ-QB005","title":"qualitybar attestation object extraction round-trips status/author/reviewer/reviewedAt/contentHash","standard":"x-FuSa spec §1.6.2","level":"ASIL-B"},
{"id":"REQ-QB006","title":"qualitybar rule-level disposition lookup suppresses FUSA-STUB001 via .fusa-dispositions.json","standard":"x-FuSa spec §1.6.1","level":"ASIL-B"},

{"id":"REQ-HARA-SCHEMA001","title":"cfusa hara init scaffolds empty operationalSituations/hazards/safetyGoals collections, never dummy rows","standard":"x-FuSa spec §1.2.5","level":"ASIL-D"},
{"id":"REQ-HARA-SCHEMA002","title":"cfusa hara show --format json reports completeness including safetyGoalsWithFssrRefs and danglingReferences","standard":"x-FuSa spec §1.2.5","level":"ASIL-B"},
{"id":"REQ-HARA-SCHEMA003","title":"cfusa hara show detects and gates on FUSA-STUB001 placeholder text in hazard/safety-goal descriptions","standard":"x-FuSa spec §1.6.1","level":"ASIL-D"},

{"id":"REQ-FMEA-SCHEMA001","title":"cfusa fmea --format json emits ratingScale, failureMode/effect/cause, actionPriority, and summary.componentsInProject/coveragePct","standard":"x-FuSa spec §9.2","level":"ASIL-B"},
{"id":"REQ-FMEA-SCHEMA002","title":"cfusa fmea failureMode/effect/cause text varies per function rather than one fixed string for every entry","standard":"x-FuSa spec §1.6.1","level":"ASIL-B"},
{"id":"REQ-FMEA-COV001","title":"cfusa fmea --min-coverage N exits 1 when summary.coveragePct < N (N=0 disables the gate)","standard":"x-FuSa spec §9.2","level":"ASIL-B"},
{"id":"REQ-FMEA-ATTEST001","title":"cfusa fmea --attest <reviewer> stamps a valid §1.6.2 attestation that suppresses FUSA-STUB002","standard":"x-FuSa spec §1.6.2","level":"ASIL-B"},

{"id":"REQ-TARA-SCHEMA001","title":"cfusa tara --format json emits threats[].impact as an SFOP object and summary.assetInventoryMethod","standard":"x-FuSa spec §9.2","level":"ASIL-B"},
{"id":"REQ-TARA006","title":"cfusa tara summary rolls up assetsAnalyzed/assetsInProject/coveragePct/assetInventoryMethod","standard":"ISO 21434","level":"ASIL-B"},

{"id":"REQ-SC002","title":"cfusa safety-case --format json emits nodes[]/edges[]/completeness using the six GSN node types","standard":"x-FuSa spec §9.2","level":"ASIL-B"},
{"id":"REQ-SC003","title":"cfusa safety-case solution nodes cite evidence only for files that actually exist in the project","standard":"x-FuSa spec §9.2","level":"ASIL-B"},
{"id":"REQ-SC-SCHEMA001","title":"cfusa safety-case JSON node/edge types conform to the GSN Community Standard v3 vocabulary","standard":"x-FuSa spec §9.2","level":"ASIL-B"},

{"id":"REQ-SAS-SCHEMA001","title":"cfusa sas --format json emits checklist[]/summary and always writes the sas.md companion","standard":"x-FuSa spec §9.3","level":"ASIL-A"},

{"id":"REQ-SCI-SCHEMA001","title":"cfusa sci --format json emits artifacts[].hash as sha256:-prefixed per x-FuSa spec §2.7","standard":"x-FuSa spec §2.7","level":"ASIL-A"},

{"id":"REQ-FSR-CHECK001","title":"cfusa check/lint shall not suppress or omit any finding for which the rule engine is configured to detect (functional safety requirement decomposing .fusa-hara.json SG-001)","standard":"ISO 26262-3","level":"ASIL-C"},
{"id":"REQ-FSR-CHECK002","title":"cfusa check shall keep its false-positive rate low enough, via the disposition system, that it does not cause systematic check-disabling (functional safety requirement decomposing .fusa-hara.json SG-002)","standard":"ISO 26262-3","level":"ASIL-C"}
]
}
75 changes: 70 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,77 @@ and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.

## [Unreleased]

## v0.5.46 — 2026-07-28

x-FuSa spec v1.13.0/v1.14.0 conformance sprint (issue #71): `hara`/`fmea`/
`tara`/`safety-case`/`sas`/`sci` schemas, the §1.6 content-quality baseline
(FUSA-STUB001/002 detection + §1.6.2 attestation), and `fmea`/`tara`
coverage metrics.

### Added
- `docker-publish.yml` now notifies `SoundMatt/FuSaOps` via `repository_dispatch`
(`xfusa-released`) after a successful image push, so FuSaOps rebuilds its
bundled image promptly instead of waiting for its weekly cron. Requires a
`FUSAOPS_DISPATCH_TOKEN` secret in this repo; falls back silently
(`continue-on-error`) to the weekly rebuild if it's not set.
- **`.fusa-hara.json` three-collection schema (§1.2.5).** `operationalSituations[]`/
`hazards[]`/`safetyGoals[]` replace the old flat `hazards[]` shape (each with a
singular `safety_goal` string). `safetyGoals[].fssrRefs` is now **MUST, ≥1
entry**, cross-checked against `.fusa-reqs.json`. `hara init` scaffolds
empty collections (never dummy rows); `hara show`/`--format json` add a
`completeness` block (`safetyGoalsWithFssrRefs`, `danglingReferences`) and
the §1.6.1 content-quality scan.
- **`fmea`/`tara`/`safety-case` real schemas (§9.2).** `fmea.json` gets
`ratingScale`, `failureMode`/`effect`/`cause` text that's heuristically
templated per function (name/file/category) instead of static/blank
fields, `actionPriority`, and `summary.componentsInProject`/`coveragePct`.
`tara.json` gets an SFOP `impact` object (safety/financial/operational/
privacy) per ISO 21434 Clause 15.7 instead of one generic severity, plus
`summary.assetsInProject`/`coveragePct`/`assetInventoryMethod`. `tara`'s
assets/threats are now discovered by scanning for functions that look
like they handle network/file/auth/memory input, instead of a static
placeholder-filled template. `safety-case --format json` is new:
`nodes[]`/`edges[]`/`completeness` using the six real GSN node types
(goal/strategy/solution/context/assumption/justification); `solution`
nodes only cite `evidence` for a file that actually exists.
- **`sas`/`sci` real schemas (§9.3).** `sas --format json` emits
`checklist[]`/`summary` (`present` reflects a real evidence-file check,
not a hardcoded `false`) and always also writes the `sas.md` companion.
`sci --format json` renames `files`→`artifacts` and `sha256`→`hash`
(`sha256:`-prefixed, per §2.7 — a field *named* `hash` carries a
algorithm-prefixed value, unlike a field named for its algorithm).
- **`--min-coverage N` on `fmea`/`tara`** (mirrors `trace --func-coverage`):
exits 1 when `summary.coveragePct < N`; `N=0` disables the gate.
`componentsInProject`/`assetsInProject` now exclude test files
(`test_*.c`/`*_test.c`), matching `trace --func-coverage`'s own
denominator, so the FMEA/TARA aren't diluted by test scaffolding.
- **§1.6.1 content-quality baseline**: a new `qualitybar` module implements
Rule A / `FUSA-STUB001` (always `ERROR`, a placeholder/template-text
deny-list scan; suppressible only via `.fusa-dispositions.json`, never
attestation) and Rule B / `FUSA-STUB002` (`WARNING` by default; a
distinct-value-ratio check across ≥10 entries), wired into
`hara`/`fmea`/`tara`/`safety-case`/`sas`.
- **§1.6.2 attestation**: any of the above commands accept
`--strict`/`--require-attestation` (escalates an unsuppressed Rule B to
exit 1) and `--attest <reviewer>` (stamps a `status: "reviewed"`
attestation with a canonical-content `sha256:` hash). A non-stale,
genuinely-independent attestation suppresses Rule B; a self-attestation
or one whose content hash no longer matches falls back to `"heuristic"`
(fail-safe).
- Regenerated this repo's own `.fusa-hara.json` (migrated from the retired
`.cfusa-hara.json`), `fmea.json`/`fmea.csv`, `tara.json`/`tara.md`, and
added `safety-case.json` against the new schemas — c-FuSa dogfooding its
own spec conformance work, mirroring FuSaOps' own PR #84/PR2.

### Fixed
- **`fmea.json`/`fmea.csv` could contain invalid JSON/CSV.** The function-name
scanner's naive paren-based heuristic occasionally misdetects a quoted
string literal (e.g. a known-answer-test table entry) as a function name;
the `item`/`Function` field was written unescaped, so an embedded `"`
broke both the JSON and CSV output. Every free-text field is now escaped
for its target format (JSON string-escaping; CSV quote-doubling per RFC
4180).
- `cmd_safety_rules.c`'s `HARA002`/`HARA003`/`HARA004` engine rules read the
old flat `.fusa-hara.json` shape; updated to the new nested
`risk.severity`/`.exposure`/`.controllability` and `safetyGoals[]`
reference-array fields, and scoped to the `hazards`/`safetyGoals` arrays
specifically so they don't cross-match a same-named nested key in a
sibling collection.

## v0.5.45 — 2026-07-27

Expand Down
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16)
project(cfusa
VERSION 0.5.45
VERSION 0.5.46
DESCRIPTION "C functional safety toolkit"
LANGUAGES C
)
Expand Down Expand Up @@ -37,6 +37,7 @@ add_library(cfusa_core STATIC
src/config.c
src/utils.c
src/cfusa_runtime.c
src/qualitybar.c
)
target_include_directories(cfusa_core PUBLIC include)
set_target_properties(cfusa_core PROPERTIES
Expand Down Expand Up @@ -157,6 +158,7 @@ cfusa_test(test_hlr_llr)
cfusa_test(test_qualify_vv)
cfusa_test(test_mcdc)
cfusa_test(test_gap_coverage)
cfusa_test(test_xfusa_v114)

# ---- Installation ----
include(GNUInstallDirs)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ cfusa fix --dir src/
| `verify` | Collect and bundle test evidence |
| `release` | SBOM (SPDX-3.0.1 JSON), SLSA v0.2 provenance, artifact manifest |
| `qualify` | Tool self-test and qualification record |
| `safety-case` | GSN safety case skeleton + evidence index |
| `safety-case` | GSN safety case (`--format json` → `nodes`/`edges`/`completeness`) + evidence index |
| `boundary` | Component dependency graph → `boundary.mermaid` + `boundary.dot` |
| `vuln` | Known-vulnerable function pattern scan (CWE/CVE) |
| `audit-pack` | Bundle all artifacts into audit package |
Expand Down
Loading
Loading