Repository navigation
A non-finite metric makes an untouched Annex IV artefact or pipeline manifest fail its own hash check (false exit 6) (CR-A04-004) #373
Description
Wave 1 · theme D1-2: Audit chain, integrity manifest and verifier robustness · highest severity High · 1 finding(s) · effort small
Summary
A stage diverges (NaN loss). The untouched chain manifest is then reported as tampered (exit 6), paging the security owner and hiding the real cause.
Primary finding
CR-A04-004 — A non-finite metric makes an untouched Annex IV artefact or pipeline manifest fail its own hash check (false exit 6)
severity High · reachability default · intent contract-violation · confidence confirmed · independently confirmed · reproduced end to end · already tracked: PARTIALLY-FIXED TRUST-15 — docs/roadmap/phase-16-trust-surface-hardening.md:9-11,339-343 (S2 done); CHANGELOG.md:91-101
What happens. build_annex_iv_artifact (compliance.py:1878) and generate_pipeline_manifest (compliance.py:3049) stamp manifest_hash via compute_annex_iv_manifest_hash, which canonicalises with plain json.dumps/json.loads allowing NaN (compliance.py:1935, 1945). The writers then persist through dumps_strict (compliance.py:2235, 3072; cli/_pipeline.py:267 _atomic_write_json), which turns NaN/Inf into 'nan'/'inf' strings (_strict_json.py:78-83). The verifier re-hashes the on-disk strings and reports 'manifest hash mismatch', exit 6. Stage metrics keep non-finite floats (cli/_pipeline.py:1630).
Where.
forgelm/cli/_pipeline.py:1382(the write; 1381 is the generate_pipeline_manifest call)forgelm/cli/_pipeline.py:1382forgelm/cli/_pipeline.py:1630(confirmed)forgelm/compliance.py:1945(confirmed)forgelm/compliance.py:3053/3072 export_pipeline_manifest: library-only, no production caller in forgelm/forgelm/compliance.py:3072(confirmed)forgelm/cli/_pipeline.py:267(confirmed)forgelm/_strict_json.py:82-83(the repr() substitution; :78-81 is the float() conversion)forgelm/compliance.py:1878(confirmed)forgelm/compliance.py:2217(build_annex_iv_artifact call inside export_compliance_artifacts)
Evidence.
- nan_manifest.py through the production _save_state: finite gives no hash violation; nan and inf both give 'manifest hash mismatch'. E2E e2e_nan/ (2-stage pipeline under scripted evalloss-nan): EXIT 0, both stages completed with eval_loss 'nan'; verify-annex-iv --pipeline EXIT=6, hash_state 'mismatch'.
- dyn/nan_manifest.py: the stage metrics have eval_loss=NaN and the pipeline exits 0. The on-disk metrics are {'eval_loss': 'nan', ...}. verify_pipeline_manifest(read-back) returns ['manifest hash mismatch ...'], and
forgelm verify-annex-iv --pipeline dyn/run_nan/pipeline_rungives EXIT=6. dyn/nan_single.py: export_compliance_artifacts with a NaN metric, then verify-annex-iv on annex_iv_metadata.json, gives EXIT=6 'Manifest hash mismatch'. - annex_nan.py: metrics eval_loss=nan, train_runtime=inf -> the on-disk performance_metrics carry 'nan'/'inf' strings, and
fpy -m forgelm verify-annex-iv out/compliance/annex_iv_metadata.json-> 'Manifest hash mismatch' EXIT=6. A control with finite metrics gives EXIT=0. pipe_nan2.py (production _atomic_write_json, failed stage with eval_loss nan) ->verify-annex-iv --pipeline-> 'manifest hash mismatch' EXIT=6. pipe_nan.py: verify_pipeline_manifest(in-memory)=[] but the on-disk copy shows a…
Recommended fix. Canonicalise through sanitize_non_finite before hashing in compute_annex_iv_manifest_hash, so writer and verifier hash the same structure. Route production writes through one fsync'd writer, export_pipeline_manifest, or delete it.
Acceptance criteria
- A regression test reproduces the failure scenario and asserts the corrected behaviour.
- Documentation listed above is corrected in English and in its Turkish mirror in the same PR.
- Every finding in this issue is resolved or explicitly closed with a reason.
Found by the October 2026 ForgeLM code and documentation review against commit cab2947. Code links point at that commit; line numbers may have moved since. Finding IDs (CR-…, DOC-…, TECH-…) are stable references for this backlog.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
cemililik commentedon Oct 9, 2026
Fixed on
development:compute_annex_iv_manifest_hashnow hashes the strict-JSON form the writers emit (f94595f), so an untouched Annex IV artefact or pipeline manifest with a NaN / Inf metric verifies, and08f2426addsmatch_annex_iv_manifest_hashso artefacts stamped by an earlier release over a bareNaNstill verify while a real edit reports exit 6. Pinned bytests/test_strict_json.py(incl.TestLegacyNonFiniteArtefactStillVerifies) andtests/test_pipeline_compliance.py. Verified 2026-10-09.