[GH-ISSUE #5537] [Bug] Electron fuse limit refusals return misleading retry and recovery advice #3371

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

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

Before submitting

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

Area

CLI

Observed behavior

node scripts/rea.mjs inspect-electron-fuses <path> --json correctly refuses inputs above the fixed reader bounds, but returns recovery metadata that cannot help the unchanged request succeed:

  • A synthetic Mach-O slice with 33 fuse sentinels returns retryable: true and tells the caller to wait for an active analysis. The fixed cap is 32 sentinels per slice.
  • A regular file of 1,073,741,825 bytes returns retryable: false, but tells the caller to increase an evidence-reply file-size allowance. This command exposes no such allowance, and its fixed input limit is 1 GiB.

An independent verifier executed and replayed the CLI procedure below. Each refusal reproduced twice with byte-identical stdout and empty stderr. The intervening 32-sentinel control succeeded. No application was launched.

Reproduction

From the source revision below, with dependencies and the built runtime already prepared, run this exact verifier-executed script. It creates synthetic static fixtures, isolates configuration and state, and invokes the public CLI. No Electron installation or target execution is required.

Executed fixture and CLI procedure
python3 - <<'PYTHON'
import json, os, pathlib, struct, subprocess, tempfile
work = pathlib.Path(tempfile.mkdtemp(prefix='electron-fuse-check-', dir=os.environ.get('VERIFY_WORK_ROOT')))
env = {'PATH': os.environ['PATH']}
for key, name in [('HOME', 'home'), ('XDG_CONFIG_HOME', 'config'),
                  ('XDG_DATA_HOME', 'data'), ('XDG_CACHE_HOME', 'cache'),
                  ('XDG_STATE_HOME', 'state'), ('TMPDIR', 'temp')]:
    folder = work / name
    folder.mkdir()
    env[key] = str(folder)
header = struct.pack('<8I', 0xfeedfacf, 0x0100000c, 0, 2, 0, 0, 0, 0)
wire = b'dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX' + bytes([1, 9]) + b'101100000'
for count in [32, 33]:
    (work / (str(count) + '.bin')).write_bytes(header + wire * count)
large = work / 'large.bin'
with large.open('wb') as handle:
    handle.write(header + wire)
    handle.truncate(1024 * 1024 * 1024 + 1)
print(json.dumps({'work': str(work), 'node': subprocess.check_output(['node', '--version'], text=True).strip(), 'platform': os.uname().sysname, 'machine': os.uname().machine}))
for label, arguments in [('help', ['--help']), ('overflow', [str(work / '33.bin'), '--json']),
                         ('control', [str(work / '32.bin'), '--json']),
                         ('repeat', [str(work / '33.bin'), '--json']),
                         ('large', [str(large), '--json']), ('large-repeat', [str(large), '--json'])]:
    result = subprocess.run(['node', 'scripts/rea.mjs', 'inspect-electron-fuses', *arguments],
                            env=env, capture_output=True, text=True, timeout=45)
    (work / (label + '.stdout')).write_text(result.stdout)
    (work / (label + '.stderr')).write_text(result.stderr)
    if label == 'help':
        print(result.stdout)
        assert result.returncode == 0
        continue
    value = json.loads(result.stdout)
    print(json.dumps({'case': label, 'exit': result.returncode, 'stderr': result.stderr,
                      'result': value if result.returncode else {
                          'sentinel_count': value['normalized_result']['slices'][0]['sentinel_count'],
                          'bytes': value['normalized_result']['artifact']['bytes'],
                          'format': value['normalized_result']['artifact']['format']}}))
    assert result.returncode == (0 if label == 'control' else 1)
assert (work / 'overflow.stdout').read_bytes() == (work / 'repeat.stdout').read_bytes()
assert (work / 'large.stdout').read_bytes() == (work / 'large-repeat.stdout').read_bytes()
for count in [32, 33]:
    assert (work / (str(count) + '.bin')).read_bytes() == header + wire * count
assert large.stat().st_size == 1024 * 1024 * 1024 + 1
print('Repeated refusals were byte-identical; both small fixture byte sequences remained unchanged.')
PYTHON

The optional VERIFY_WORK_ROOT selects an existing working directory. The small fixtures are 1,408 and 1,451 bytes. Both 33-sentinel calls exited 1; the 32-sentinel control exited 0 and reported format: "mach-o" and sentinel_count: 32. Both oversized-file calls exited 1. Both small fixtures remained byte-for-byte unchanged, and the sparse file retained its size.

Expected behavior

Preserve the intentional refusals and numeric limits. Return retryable: false for a deterministic sentinel-count refusal, and identify the fixed input bound in both recovery actions. Waiting for another analysis or enlarging an evidence-output allowance cannot admit the unchanged input.

This expectation is source-derived from docs/electron-fuses.md:81-87, which documents the fixed 1 GiB and 32-sentinels-per-slice bounds, and src/domain/analysisErrorCore.ts:36-41, which defines retryability by whether the same request can succeed and excludes deterministic bounds. The strict path-only schema in src/domain/electron/electronFuses.ts:160-164 agrees with the executed CLI help, which offers no input-size or sentinel-count override.

Impact and scope

P2 for incorrect machine-readable retryability on an above-cap input. A client following the flag can repeat an unchanged request that cannot succeed by waiting. The size-recovery wording alone is P3 because its refusal and non-retryable status remain correct.

A practical caller workaround is to recognize the sentinel-count message and maximum_sentinels_per_slice and stop retrying despite the flag. This preserves the refusal; selecting a different artifact does not recover complete inspection of the original above-bound input. No automated retry loop, outage, data loss, incorrect successful report, or prevalence in real applications was established.

REA version

6.7.0, built source CLI at commit 074768901f3cdc8205b61773fb1faf6f6c7b3ca8.

Runtime and platform

Node.js v26.12.0; Darwin arm64. Static built-in inspection; no external analysis engine.

Target and artifact context

Synthetic thin arm64 Mach-O headers with 32 or 33 complete version-1 nine-fuse wires. These are reader fixtures, not complete packaged Electron applications. A regular sparse file with one wire is extended to exactly one byte above 1 GiB to exercise size admission before parsing or scanning.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

The verifier captured the following relevant fields from both 33-sentinel refusals:

{
  "code": "resource_constraint",
  "category": "resource_constraint",
  "message": "Slice 0 contains more than 32 Electron fuse sentinels.",
  "retryable": true,
  "remediation": {
    "action": "Wait for an active analysis to complete, then retry within the reported admission limits."
  },
  "details": {
    "operation": "inspect_electron_fuses",
    "resource": "capacity",
    "reported_limits": { "maximum_sentinels_per_slice": 32 }
  }
}

Both oversized-file refusals returned resource_constraint, retryable: false, details.resource: "file-size", and details.reported_limits.maximum_input_bytes: 1073741824. Their action was:

Review the reported worker file-size limits and write failure. Retry with a sufficient file-size allowance for the evidence reply; REA retains tighter inherited limits.

The script replay produced the same successful control and repeated refusals. The header and wire layout follows tests/fixtures/electron/fuseImage.ts:27-35 and the 32/33 boundary fixture in src/electron/ElectronFuseProvider.test.ts:554-601.

Typed outcome or recovery expected

Keep both failures as resource_constraint with their existing numeric bounds. Make sentinel overflow non-retryable and provide recovery specific to the fixed sentinel/input-size bounds. Preserve the 32-sentinel success and selected bytes. These are proposed restoration checks; no fix or restoration was tested.

Analysis or suspected cause

Source-derived reasoning at the tested revision: src/electron/ElectronFuseReader.ts:133-137,375-379 produces these fixed-bound failures. src/electron/ElectronFuseFailures.ts:88-97 maps them without recovery or retryability overrides. src/domain/analysisErrorProjection.ts:109-115 defaults capacity to retryable; src/domain/analysisErrorPresentation.ts:67-78 supplies the observed generic actions.

A fresh upstream history and source check at cf5194f68e286a79ee4b4ffbe626f9f5b5bbbaf1 found these behaviors unchanged. The intervening recovery commit e50a271c72325880b5ff944973b0b42d81b4b158 changes input-validation and timeout handling, leaving these resource-constraint branches unchanged. This latest-main applicability check was source inspection, not another runtime reproduction.

Additional context

Prepared with AI assistance and independently reproduced. Open/closed issue and PR searches covered the command name, sentinel retryability, fuse limits/recovery, and reader/failure modules.

Related fixed-budget reports #5405, #5456, #5459, #5460, #5504, #5505, and #5506 have different producers and caller triggers. #4658 concerns descriptor cleanup, and #4192 concerns PE input-byte classification. None reports these Electron fuse reader bounds.

NOT_ENOUGH_INFO: no last-known-good version or first-bad revision was established. Live MCP, installed-package behavior, other hosts, real Electron applications, and an exactly 1 GiB successful scan were not replayed. Real-world frequency is unknown.

Originally created by @coygeek on GitHub (Oct 20, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5537 ### 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 CLI ### Observed behavior `node scripts/rea.mjs inspect-electron-fuses <path> --json` correctly refuses inputs above the fixed reader bounds, but returns recovery metadata that cannot help the unchanged request succeed: - A synthetic Mach-O slice with 33 fuse sentinels returns `retryable: true` and tells the caller to wait for an active analysis. The fixed cap is 32 sentinels per slice. - A regular file of 1,073,741,825 bytes returns `retryable: false`, but tells the caller to increase an evidence-reply file-size allowance. This command exposes no such allowance, and its fixed input limit is 1 GiB. An independent verifier executed and replayed the CLI procedure below. Each refusal reproduced twice with byte-identical stdout and empty stderr. The intervening 32-sentinel control succeeded. No application was launched. ### Reproduction From the source revision below, with dependencies and the built runtime already prepared, run this exact verifier-executed script. It creates synthetic static fixtures, isolates configuration and state, and invokes the public CLI. No Electron installation or target execution is required. <details> <summary>Executed fixture and CLI procedure</summary> ```sh python3 - <<'PYTHON' import json, os, pathlib, struct, subprocess, tempfile work = pathlib.Path(tempfile.mkdtemp(prefix='electron-fuse-check-', dir=os.environ.get('VERIFY_WORK_ROOT'))) env = {'PATH': os.environ['PATH']} for key, name in [('HOME', 'home'), ('XDG_CONFIG_HOME', 'config'), ('XDG_DATA_HOME', 'data'), ('XDG_CACHE_HOME', 'cache'), ('XDG_STATE_HOME', 'state'), ('TMPDIR', 'temp')]: folder = work / name folder.mkdir() env[key] = str(folder) header = struct.pack('<8I', 0xfeedfacf, 0x0100000c, 0, 2, 0, 0, 0, 0) wire = b'dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX' + bytes([1, 9]) + b'101100000' for count in [32, 33]: (work / (str(count) + '.bin')).write_bytes(header + wire * count) large = work / 'large.bin' with large.open('wb') as handle: handle.write(header + wire) handle.truncate(1024 * 1024 * 1024 + 1) print(json.dumps({'work': str(work), 'node': subprocess.check_output(['node', '--version'], text=True).strip(), 'platform': os.uname().sysname, 'machine': os.uname().machine})) for label, arguments in [('help', ['--help']), ('overflow', [str(work / '33.bin'), '--json']), ('control', [str(work / '32.bin'), '--json']), ('repeat', [str(work / '33.bin'), '--json']), ('large', [str(large), '--json']), ('large-repeat', [str(large), '--json'])]: result = subprocess.run(['node', 'scripts/rea.mjs', 'inspect-electron-fuses', *arguments], env=env, capture_output=True, text=True, timeout=45) (work / (label + '.stdout')).write_text(result.stdout) (work / (label + '.stderr')).write_text(result.stderr) if label == 'help': print(result.stdout) assert result.returncode == 0 continue value = json.loads(result.stdout) print(json.dumps({'case': label, 'exit': result.returncode, 'stderr': result.stderr, 'result': value if result.returncode else { 'sentinel_count': value['normalized_result']['slices'][0]['sentinel_count'], 'bytes': value['normalized_result']['artifact']['bytes'], 'format': value['normalized_result']['artifact']['format']}})) assert result.returncode == (0 if label == 'control' else 1) assert (work / 'overflow.stdout').read_bytes() == (work / 'repeat.stdout').read_bytes() assert (work / 'large.stdout').read_bytes() == (work / 'large-repeat.stdout').read_bytes() for count in [32, 33]: assert (work / (str(count) + '.bin')).read_bytes() == header + wire * count assert large.stat().st_size == 1024 * 1024 * 1024 + 1 print('Repeated refusals were byte-identical; both small fixture byte sequences remained unchanged.') PYTHON ``` </details> The optional `VERIFY_WORK_ROOT` selects an existing working directory. The small fixtures are 1,408 and 1,451 bytes. Both 33-sentinel calls exited 1; the 32-sentinel control exited 0 and reported `format: "mach-o"` and `sentinel_count: 32`. Both oversized-file calls exited 1. Both small fixtures remained byte-for-byte unchanged, and the sparse file retained its size. ### Expected behavior Preserve the intentional refusals and numeric limits. Return `retryable: false` for a deterministic sentinel-count refusal, and identify the fixed input bound in both recovery actions. Waiting for another analysis or enlarging an evidence-output allowance cannot admit the unchanged input. This expectation is source-derived from `docs/electron-fuses.md:81-87`, which documents the fixed 1 GiB and 32-sentinels-per-slice bounds, and `src/domain/analysisErrorCore.ts:36-41`, which defines retryability by whether the same request can succeed and excludes deterministic bounds. The strict path-only schema in `src/domain/electron/electronFuses.ts:160-164` agrees with the executed CLI help, which offers no input-size or sentinel-count override. ### Impact and scope P2 for incorrect machine-readable retryability on an above-cap input. A client following the flag can repeat an unchanged request that cannot succeed by waiting. The size-recovery wording alone is P3 because its refusal and non-retryable status remain correct. A practical caller workaround is to recognize the sentinel-count message and `maximum_sentinels_per_slice` and stop retrying despite the flag. This preserves the refusal; selecting a different artifact does not recover complete inspection of the original above-bound input. No automated retry loop, outage, data loss, incorrect successful report, or prevalence in real applications was established. ### REA version 6.7.0, built source CLI at commit `074768901f3cdc8205b61773fb1faf6f6c7b3ca8`. ### Runtime and platform Node.js v26.12.0; Darwin arm64. Static built-in inspection; no external analysis engine. ### Target and artifact context Synthetic thin arm64 Mach-O headers with 32 or 33 complete version-1 nine-fuse wires. These are reader fixtures, not complete packaged Electron applications. A regular sparse file with one wire is extended to exactly one byte above 1 GiB to exercise size admission before parsing or scanning. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence The verifier captured the following relevant fields from both 33-sentinel refusals: ```json { "code": "resource_constraint", "category": "resource_constraint", "message": "Slice 0 contains more than 32 Electron fuse sentinels.", "retryable": true, "remediation": { "action": "Wait for an active analysis to complete, then retry within the reported admission limits." }, "details": { "operation": "inspect_electron_fuses", "resource": "capacity", "reported_limits": { "maximum_sentinels_per_slice": 32 } } } ``` Both oversized-file refusals returned `resource_constraint`, `retryable: false`, `details.resource: "file-size"`, and `details.reported_limits.maximum_input_bytes: 1073741824`. Their action was: ```text Review the reported worker file-size limits and write failure. Retry with a sufficient file-size allowance for the evidence reply; REA retains tighter inherited limits. ``` The script replay produced the same successful control and repeated refusals. The header and wire layout follows `tests/fixtures/electron/fuseImage.ts:27-35` and the 32/33 boundary fixture in `src/electron/ElectronFuseProvider.test.ts:554-601`. ### Typed outcome or recovery expected Keep both failures as `resource_constraint` with their existing numeric bounds. Make sentinel overflow non-retryable and provide recovery specific to the fixed sentinel/input-size bounds. Preserve the 32-sentinel success and selected bytes. These are proposed restoration checks; no fix or restoration was tested. ### Analysis or suspected cause Source-derived reasoning at the tested revision: `src/electron/ElectronFuseReader.ts:133-137,375-379` produces these fixed-bound failures. `src/electron/ElectronFuseFailures.ts:88-97` maps them without recovery or retryability overrides. `src/domain/analysisErrorProjection.ts:109-115` defaults capacity to retryable; `src/domain/analysisErrorPresentation.ts:67-78` supplies the observed generic actions. A fresh upstream history and source check at `cf5194f68e286a79ee4b4ffbe626f9f5b5bbbaf1` found these behaviors unchanged. The intervening recovery commit `e50a271c72325880b5ff944973b0b42d81b4b158` changes input-validation and timeout handling, leaving these resource-constraint branches unchanged. This latest-main applicability check was source inspection, not another runtime reproduction. ### Additional context Prepared with AI assistance and independently reproduced. Open/closed issue and PR searches covered the command name, sentinel retryability, fuse limits/recovery, and reader/failure modules. Related fixed-budget reports #5405, #5456, #5459, #5460, #5504, #5505, and #5506 have different producers and caller triggers. #4658 concerns descriptor cleanup, and #4192 concerns PE input-byte classification. None reports these Electron fuse reader bounds. NOT_ENOUGH_INFO: no last-known-good version or first-bad revision was established. Live MCP, installed-package behavior, other hosts, real Electron applications, and an exactly 1 GiB successful scan were not replayed. Real-world frequency is unknown.
Author
Owner

@matbrgz commented on GitHub (Oct 20, 2026):

Cross-referencing with canonical issue #5504 ([Bug] Rust compiler-hash capacity refusals incorrectly tell callers to retry) and siblings #5456, #5459, #5460, #5505, #5506. Addresses misleading retry/recovery hints on fixed reader bounds and fuse limits. Cataloged under Cluster AJ in consolidation tracker #4330.

<!-- gh-comment-id:6293051065 --> @matbrgz commented on GitHub (Oct 20, 2026): Cross-referencing with canonical issue #5504 (`[Bug] Rust compiler-hash capacity refusals incorrectly tell callers to retry`) and siblings #5456, #5459, #5460, #5505, #5506. Addresses misleading retry/recovery hints on fixed reader bounds and fuse limits. Cataloged under Cluster AJ in consolidation tracker #4330.
Author
Owner

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

Closing as fixed on main by github.com/morluto/rea@ef59174c1e, retained at 67a6477f01.

Electron fuse failures now distinguish the fixed input allowance from the sentinel count allowance, with non-retryable guidance appropriate to each. Producer tests cover 32/33 sentinels and the sparse oversized-input case while preserving meaningful reported limits.

This audit inspected the current producer, regression source, issue discussion and main ancestry. Tests/runtime reproductions were not rerun, and no additional real-provider or platform coverage is implied.

<!-- gh-comment-id:6324328490 --> @morluto commented on GitHub (Oct 21, 2026): Closing as fixed on main by https://github.com/morluto/rea/commit/ef59174c1edd6ed9adb0722b86a5b9a57217e310, retained at 67a6477f011ae358fc333e5a6e26c86d932654ed. Electron fuse failures now distinguish the fixed input allowance from the sentinel count allowance, with non-retryable guidance appropriate to each. Producer tests cover 32/33 sentinels and the sparse oversized-input case while preserving meaningful reported limits. This audit inspected the current producer, regression source, issue discussion and main ancestry. Tests/runtime reproductions were not rerun, and no additional real-provider or platform coverage is implied.
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#3371
No description provided.