[GH-ISSUE #5745] [Bug] extract_firmware labels resolved Unblob extraction problems as unextracted regions #3490

Closed
opened 2026-10-31 00:41:06 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @coygeek on GitHub (Oct 21, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/5745

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

extract-firmware publishes the final file from a tar containing duplicate entries, but also emits an extractor-failure gap for the tar region. Its continuation recommends repeating the same immutable input and says “the region is not decoded content.” Unblob has already replaced the older entry and reports successful extraction with a resolved, non-fatal warning. A fresh-destination retry returns the same false gap.

Reproduction

The independent verifier executed these commands at the baseline below. From the built source checkout on Linux x64, with locked dependencies, Python 3, Unblob 26.6.4 on PATH, util-linux prlimit, and procps-compatible ps:

work_dir="$(mktemp -d)"
mkdir -p "$work_dir/home" "$work_dir/cfg" "$work_dir/data" "$work_dir/cache" "$work_dir/state" "$work_dir/tmp"
unblob_command="$(command -v unblob)"
python3 - "$work_dir" <<'PYTHON'
from pathlib import Path
import io
import sys
import tarfile
root = Path(sys.argv[1])
for name, payloads in (
    ("duplicate", (b"first copy\n", b"second copy\n")),
    ("control", (b"second copy\n",)),
):
    buffer = io.BytesIO()
    with tarfile.open(fileobj=buffer, mode="w", format=tarfile.USTAR_FORMAT) as archive:
        for payload in payloads:
            entry = tarfile.TarInfo("dup.txt")
            entry.size = len(payload)
            entry.mode = 0o644
            archive.addfile(entry, io.BytesIO(payload))
    (root / (name + ".bin")).write_bytes(b"\0" * 16 + buffer.getvalue() + b"\0" * 16)
PYTHON
run_isolated() {
  env -i PATH="$PATH" HOME="$work_dir/home" XDG_CONFIG_HOME="$work_dir/cfg" XDG_DATA_HOME="$work_dir/data" XDG_CACHE_HOME="$work_dir/cache" XDG_STATE_HOME="$work_dir/state" TMPDIR="$work_dir/tmp" REA_LOG_LEVEL=silent REA_UNBLOB_COMMAND="$unblob_command" "$@"
}
for name in duplicate control; do
  run_isolated node scripts/rea.mjs extract-firmware "$work_dir/$name.bin" "$work_dir/$name-out" --json > "$work_dir/$name.json"
done
run_isolated "$unblob_command" --process-num 1 --depth 3 --randomness-depth 0 --report "$work_dir/producer.json" --log "$work_dir/producer.log" --extract-dir "$work_dir/producer-out" "$work_dir/duplicate.bin"

Inspect normalized_result.extraction_gaps, extraction_continuations, diagnostics, and files in both CLI JSON files. Compare the extracted dup.txt bytes under 16-10256.tar_extract for REA duplicate, REA control, and direct Unblob duplicate. The verifier observed the false gap in 3/3 duplicate runs, including a fresh-destination retry and an execution of these exact commands; neither of 2 clean-control runs had a gap.

Expected behavior

Keep the resolved duplicate warning and published final file without describing the successfully extracted tar region as unextracted or prescribing an ineffective retry. This does not require recovering both historical versions of a duplicate entry.

At the baseline, the firmware guide and domain contract define gaps as unextracted regions or failed tasks/stages. src/contracts/firmware/firmwareToolContracts.ts:33 promises recovery instructions for those gaps.

partial coverage remains acceptable: the guide explicitly permits it for reported extraction problems. The chunk's extraction_failed flag is likewise documented as indicating reported problems; this report does not require either value to change.

Impact and scope

P2: a bounded machine-readable evidence and recovery defect. The final file is available, but callers receive a contradictory gap and retry advice that does not resolve it. For this fixture, callers can inspect the retained producer report/diagnostic and independently verified published bytes instead. Other warning types and MCP transport were not replayed; no lost published bytes or security-boundary violation was established.

REA version

rea-agents 6.7.0, source baseline 9d8e7803326a382cbbb3ffdb900f5e93e5442d68. Fetched current main d0067ba34a39ea47dd7e11bb2e6169bc0938cc3f: no intervening commits touch the five REA files cited in Expected behavior and Analysis. This was a source recheck; the independent Linux reproduction was at the baseline, not a fresh main runtime build.

Runtime and platform

Reproduction: Node.js v24.22.0, Linux x64 container, pinned Unblob 26.6.4; ps and prlimit available. Submission host: Node.js v26.12.0, macOS 27.0.1, arm64. Firmware reproduction ran only on Linux. Binwalk and 7z are unnecessary for this tar fixture.

Target and artifact context

Generated USTAR archive with two dup.txt entries (first copy\n, then second copy\n), padded with 16 zero bytes on each side. The control contains only the second entry. Default Unblob sandbox and skip rules remained enabled; REA and the direct producer used depth 3. No extracted program was executed.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

The verifier observed REA exit 0 and this gap subset:

{
  "kind": "extractor-failure",
  "input_path": "$input",
  "handler": "tar",
  "range": {"offset": 16, "length": 10240},
  "root_file_range": {"offset": 16, "length": 10240},
  "dependencies": []
}

The retained ExtractionProblem diagnostic says problem: "Duplicate tar entry.", resolution: "Removed older version.", path: "dup.txt". Direct Unblob also exited 0 and retained that resolved warning. Its installed unblob/report.py:280 describes ExtractionProblem as successful extraction with resolved non-fatal problems, subject to an exception for the reported path; _safe_tarfile.py:215 reports duplicate replacement.

REA duplicate, direct Unblob duplicate, and REA control each published a 12-byte dup.txt containing second copy\n, SHA-256 83260694f4619a55ad1e5e2130f4f36b16c7ae0b22c70706f22a253208876217. Duplicate coverage was partial; control coverage was complete, with no diagnostics or gaps. Evidence provenance: observed; independently reproduced by the verifier. The submitter inspected the retained evidence and source, without adding another runtime replay.

Typed outcome or recovery expected

Preserve the resolved diagnostic and identical final file bytes. Omit the false tar failure-gap and undecoded-content instruction. Keep appropriate gaps and actionable continuations for genuine execution failures or missing dependencies. That latter discriminating control is proposed and was not run during verification.

Analysis or suspected cause

Source-derived reasoning: FirmwareReports.ts:398 marks a chunk whenever its nested extraction-report list is nonempty. FirmwarePublication.ts:452 uses that broad problem flag to emit extractor-failure for a nonencrypted chunk without a missing dependency. Its continuation at line 31 assumes failure and undecoded content. The narrower gap claim does not distinguish Unblob's resolved warnings. This points to REA's projection of the producer report, rather than an Unblob extraction failure.

Additional context

Prepared with AI assistance from an independently verified draft. No fix or successful restoration is claimed; no known-good revision was established.

Related but distinct: #3756 and PR #4953 concern missing gaps when no chunks were recognized; #4175 concerns rewritten symlink-target provenance; #1853 and PRs #1879/#1892 concern missing-dependency recovery; #3888 concerns the producer-report byte budget. None covers the resolved duplicate-entry warning becoming a false failure gap.

Originally created by @coygeek on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5745 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior `extract-firmware` publishes the final file from a tar containing duplicate entries, but also emits an `extractor-failure` gap for the tar region. Its continuation recommends repeating the same immutable input and says “the region is not decoded content.” Unblob has already replaced the older entry and reports successful extraction with a resolved, non-fatal warning. A fresh-destination retry returns the same false gap. ### Reproduction The independent verifier executed these commands at the baseline below. From the built source checkout on Linux x64, with locked dependencies, Python 3, Unblob 26.6.4 on PATH, util-linux `prlimit`, and procps-compatible `ps`: ```sh work_dir="$(mktemp -d)" mkdir -p "$work_dir/home" "$work_dir/cfg" "$work_dir/data" "$work_dir/cache" "$work_dir/state" "$work_dir/tmp" unblob_command="$(command -v unblob)" python3 - "$work_dir" <<'PYTHON' from pathlib import Path import io import sys import tarfile root = Path(sys.argv[1]) for name, payloads in ( ("duplicate", (b"first copy\n", b"second copy\n")), ("control", (b"second copy\n",)), ): buffer = io.BytesIO() with tarfile.open(fileobj=buffer, mode="w", format=tarfile.USTAR_FORMAT) as archive: for payload in payloads: entry = tarfile.TarInfo("dup.txt") entry.size = len(payload) entry.mode = 0o644 archive.addfile(entry, io.BytesIO(payload)) (root / (name + ".bin")).write_bytes(b"\0" * 16 + buffer.getvalue() + b"\0" * 16) PYTHON run_isolated() { env -i PATH="$PATH" HOME="$work_dir/home" XDG_CONFIG_HOME="$work_dir/cfg" XDG_DATA_HOME="$work_dir/data" XDG_CACHE_HOME="$work_dir/cache" XDG_STATE_HOME="$work_dir/state" TMPDIR="$work_dir/tmp" REA_LOG_LEVEL=silent REA_UNBLOB_COMMAND="$unblob_command" "$@" } for name in duplicate control; do run_isolated node scripts/rea.mjs extract-firmware "$work_dir/$name.bin" "$work_dir/$name-out" --json > "$work_dir/$name.json" done run_isolated "$unblob_command" --process-num 1 --depth 3 --randomness-depth 0 --report "$work_dir/producer.json" --log "$work_dir/producer.log" --extract-dir "$work_dir/producer-out" "$work_dir/duplicate.bin" ``` Inspect `normalized_result.extraction_gaps`, `extraction_continuations`, `diagnostics`, and `files` in both CLI JSON files. Compare the extracted `dup.txt` bytes under `16-10256.tar_extract` for REA duplicate, REA control, and direct Unblob duplicate. The verifier observed the false gap in 3/3 duplicate runs, including a fresh-destination retry and an execution of these exact commands; neither of 2 clean-control runs had a gap. ### Expected behavior Keep the resolved duplicate warning and published final file without describing the successfully extracted tar region as unextracted or prescribing an ineffective retry. This does not require recovering both historical versions of a duplicate entry. At the baseline, [the firmware guide](https://github.com/morluto/rea/blob/9d8e7803326a382cbbb3ffdb900f5e93e5442d68/docs/firmware-analysis.md#L110) and [domain contract](https://github.com/morluto/rea/blob/9d8e7803326a382cbbb3ffdb900f5e93e5442d68/src/domain/firmware/firmwareAnalysis.ts#L101) define gaps as unextracted regions or failed tasks/stages. `src/contracts/firmware/firmwareToolContracts.ts:33` promises recovery instructions for those gaps. `partial` coverage remains acceptable: the guide explicitly permits it for reported extraction problems. The chunk's `extraction_failed` flag is likewise documented as indicating reported problems; this report does not require either value to change. ### Impact and scope P2: a bounded machine-readable evidence and recovery defect. The final file is available, but callers receive a contradictory gap and retry advice that does not resolve it. For this fixture, callers can inspect the retained producer report/diagnostic and independently verified published bytes instead. Other warning types and MCP transport were not replayed; no lost published bytes or security-boundary violation was established. ### REA version `rea-agents` 6.7.0, source baseline `9d8e7803326a382cbbb3ffdb900f5e93e5442d68`. Fetched current main `d0067ba34a39ea47dd7e11bb2e6169bc0938cc3f`: no intervening commits touch the five REA files cited in Expected behavior and Analysis. This was a source recheck; the independent Linux reproduction was at the baseline, not a fresh main runtime build. ### Runtime and platform Reproduction: Node.js v24.22.0, Linux x64 container, pinned Unblob 26.6.4; `ps` and `prlimit` available. Submission host: Node.js v26.12.0, macOS 27.0.1, arm64. Firmware reproduction ran only on Linux. Binwalk and 7z are unnecessary for this tar fixture. ### Target and artifact context Generated USTAR archive with two `dup.txt` entries (`first copy\n`, then `second copy\n`), padded with 16 zero bytes on each side. The control contains only the second entry. Default Unblob sandbox and skip rules remained enabled; REA and the direct producer used depth 3. No extracted program was executed. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence The verifier observed REA exit 0 and this gap subset: ```json { "kind": "extractor-failure", "input_path": "$input", "handler": "tar", "range": {"offset": 16, "length": 10240}, "root_file_range": {"offset": 16, "length": 10240}, "dependencies": [] } ``` The retained `ExtractionProblem` diagnostic says `problem: "Duplicate tar entry."`, `resolution: "Removed older version."`, `path: "dup.txt"`. Direct Unblob also exited 0 and retained that resolved warning. Its installed `unblob/report.py:280` describes `ExtractionProblem` as successful extraction with resolved non-fatal problems, subject to an exception for the reported path; `_safe_tarfile.py:215` reports duplicate replacement. REA duplicate, direct Unblob duplicate, and REA control each published a 12-byte `dup.txt` containing `second copy\n`, SHA-256 `83260694f4619a55ad1e5e2130f4f36b16c7ae0b22c70706f22a253208876217`. Duplicate coverage was `partial`; control coverage was `complete`, with no diagnostics or gaps. Evidence provenance: observed; independently reproduced by the verifier. The submitter inspected the retained evidence and source, without adding another runtime replay. ### Typed outcome or recovery expected Preserve the resolved diagnostic and identical final file bytes. Omit the false tar failure-gap and undecoded-content instruction. Keep appropriate gaps and actionable continuations for genuine execution failures or missing dependencies. That latter discriminating control is proposed and was not run during verification. ### Analysis or suspected cause Source-derived reasoning: [FirmwareReports.ts:398](https://github.com/morluto/rea/blob/9d8e7803326a382cbbb3ffdb900f5e93e5442d68/src/firmware/FirmwareReports.ts#L398) marks a chunk whenever its nested extraction-report list is nonempty. [FirmwarePublication.ts:452](https://github.com/morluto/rea/blob/9d8e7803326a382cbbb3ffdb900f5e93e5442d68/src/firmware/FirmwarePublication.ts#L452) uses that broad problem flag to emit `extractor-failure` for a nonencrypted chunk without a missing dependency. Its continuation at line 31 assumes failure and undecoded content. The narrower gap claim does not distinguish Unblob's resolved warnings. This points to REA's projection of the producer report, rather than an Unblob extraction failure. ### Additional context Prepared with AI assistance from an independently verified draft. No fix or successful restoration is claimed; no known-good revision was established. Related but distinct: #3756 and PR #4953 concern missing gaps when no chunks were recognized; #4175 concerns rewritten symlink-target provenance; #1853 and PRs #1879/#1892 concern missing-dependency recovery; #3888 concerns the producer-report byte budget. None covers the resolved duplicate-entry warning becoming a false failure gap.
Author
Owner

@XinwangTao commented on GitHub (Oct 21, 2026):

This is the mirror image of #3756: instead of reporting complete when nothing was extracted, here the tool publishes the correct final file (duplicate entry resolved, non-fatal warning) yet still emits a gap that tells the user to retry immutable input. The 3/3 duplicate vs 0/2 control split confirms the gap is derived from the extractor warning itself, not from any actual missing region — so the fix should treat resolved duplicate-entry warnings as diagnostics, not as extraction gaps, and gate the "region is not decoded content" continuation on regions that were truly never decoded. Also worth asserting in a regression test that the published file bytes match the control's (second copy wins) whenever the warning is present.

<!-- gh-comment-id:6311377847 --> @XinwangTao commented on GitHub (Oct 21, 2026): This is the mirror image of #3756: instead of reporting complete when nothing was extracted, here the tool publishes the correct final file (duplicate entry resolved, non-fatal warning) yet still emits a gap that tells the user to retry immutable input. The 3/3 duplicate vs 0/2 control split confirms the gap is derived from the extractor warning itself, not from any actual missing region — so the fix should treat resolved duplicate-entry warnings as diagnostics, not as extraction gaps, and gate the "region is not decoded content" continuation on regions that were truly never decoded. Also worth asserting in a regression test that the published file bytes match the control's (second copy wins) whenever the warning is present.
Author
Owner

@coygeek commented on GitHub (Oct 24, 2026):

Checked the reported fix on main at d87e73f2db.

Unblob extraction failures now derive from the report severity ERROR or a structured missing-dependency report. Mere ExtractionProblem presence is insufficient. Regressions include a resolved duplicate-path ExtractionProblem with failed:false across task/chunk/multi-file owners, preserve the diagnostic and distinguish real errors.

Implementation: FirmwareReports.ts.

The relevant regression checks in FirmwareReports.test.ts passed in the focused test run on this revision. This closure is based on the current source and those checks; provider fixtures do not establish a real-engine run. Closing as completed on main.

<!-- gh-comment-id:6380737611 --> @coygeek commented on GitHub (Oct 24, 2026): Checked the reported fix on `main` at d87e73f2db50be72d33a4b3c7199af35518b441c. Unblob extraction failures now derive from the report severity ERROR or a structured missing-dependency report. Mere ExtractionProblem presence is insufficient. Regressions include a resolved duplicate-path ExtractionProblem with failed:false across task/chunk/multi-file owners, preserve the diagnostic and distinguish real errors. Implementation: [FirmwareReports.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/src/firmware/FirmwareReports.ts#L64). The relevant regression checks in [FirmwareReports.test.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/src/firmware/FirmwareReports.test.ts) passed in the focused test run on this revision. This closure is based on the current source and those checks; provider fixtures do not establish a real-engine run. Closing as completed on main.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3490
No description provided.