[GH-ISSUE #6812] [Bug] WASM inspection rejects a valid core module when optional custom metadata cannot be interpreted #4160

Closed
opened 2026-10-31 00:47:17 +00:00 by bsakaguchi · 0 comments
Owner

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

Before submitting

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

Area

Native analysis or decompilation

Observed behavior

WabtArtifactProvider.inspect refuses the 18-byte core WASM module 0061736d010000000008046e616d65616263 with Invalid analysis input for inspect_wasm_artifact, retaining validation: "rejected-by-selected-profile". Its only section is a correctly framed custom section named name, containing opaque bytes abc. Those bytes are not valid optional debug-name metadata, but the core module is valid. Node's WebAssembly.validate returns true, and the admitted WABT release validates and decodes the same bytes with --ignore-custom-section-errors, retaining a warning.

The same payload under the custom name note, an empty module, and a well-formed name payload all pass through the real REA provider. This executed the production provider with official WABT binaries, not CLI/MCP transports. No module was instantiated and no target code exists in these fixtures.

Reproduction

Use the stated source checkout with locked dependencies at /tmp/rea-wasm-repro/rea, or substitute its import prefix. Supply the unchanged official WABT 1.0.42 Linux x64 release under /tmp/rea-wasm-repro/wabt-1.0.42/bin. Its downloaded archive passed the release's SHA-256 sidecar check before these probes. No global tool installation or configuration is required.

Save the following executed probe, with only scratch paths normalized, as /tmp/rea-wasm-repro/probe.mts. All binary fixtures are inline; no compiler is required. Each final matrix case ran once. An earlier exploratory probe also observed the name refusal.

mkdir -p /tmp/rea-wasm-repro/work /tmp/rea-wasm-repro/home /tmp/rea-wasm-repro/config
HOME=/tmp/rea-wasm-repro/home XDG_CONFIG_HOME=/tmp/rea-wasm-repro/config node --import /tmp/rea-wasm-repro/rea/node_modules/tsx/dist/loader.mjs /tmp/rea-wasm-repro/probe.mts
import { writeFile } from 'node:fs/promises';
import { spawnSync } from 'node:child_process';
import { WabtArtifactProvider } from '/tmp/rea-wasm-repro/rea/src/wasm/WabtArtifactProvider.ts';
const root='/tmp/rea-wasm-repro';
const bin=root+'/wabt-1.0.42/bin';
for(const [label,hex] of [
 ['empty-control','0061736d01000000'],
 ['opaque-note-control','0061736d010000000008046e6f7465616263'],
 ['opaque-name','0061736d010000000008046e616d65616263'],
 ['valid-name-control','0061736d010000000009046e616d6500020178'],
] as const){
 const bytes=Buffer.from(hex,'hex');const path=root+'/work/'+label+'.wasm';await writeFile(path,bytes);
 const validation=spawnSync(bin+'/wasm-validate',['--enable-all',path],{encoding:'utf8'});
 const tolerant=spawnSync(bin+'/wasm-validate',['--enable-all','--ignore-custom-section-errors',path],{encoding:'utf8'});
 const decode=spawnSync(bin+'/wasm2wat',['--enable-all','--ignore-custom-section-errors',path],{encoding:'utf8'});
 const provider=new WabtArtifactProvider({...process.env,REA_WABT_BIN_DIRECTORY:bin});
 const result=await provider.inspect({path,glue_paths:[],candidate_paths:[]});await provider.close();
 console.log(JSON.stringify({label,hex,node_validate:WebAssembly.validate(bytes),wabt_status:validation.status,wabt_stderr:validation.stderr.trim(),tolerant_status:tolerant.status,tolerant_stderr:tolerant.stderr.trim(),decoded_status:decode.status,decoded_wat:decode.stdout.trim(),provider:result.ok?{ok:true}:{ok:false,message:result.error.message,partial_validation:(result.error.partialObservation as any)?.normalized_result?.validation}}));
}

Expected behavior

Inspect the valid core module while retaining the uninterpreted custom bytes and reporting the debug-metadata interpretation failure as a limitation or warning. Optional custom-data errors should not make the selected core artifact unusable for section/interface inspection.

The WebAssembly specification's custom-section rule defines the payload after its name as uninterpreted bytes and says interpretation errors must not invalidate the module. REA's WASM inspection contract inventories local WASM bytes, sections, imports/exports and decoded WAT. The opaque custom payload changes none of this module's core declarations. Failure of optional name interpretation should remain distinct from invalid core WASM.

Impact and scope

A conforming core module with optional metadata this adapter cannot interpret cannot produce a complete REA inspection. The single final failing case is 18 bytes; all three controls succeed. The failure happens before interface extraction and affects even a module with no code, imports, or exports. Prevalence in production artifacts and other custom-section conventions were not measured. Source inspection shows additional warning-rejection and debug-name decoding gates, so simply changing one command argument is not established as a complete fix.

REA version

Executed source: e2efd10b70a2b5f15a7ac1b5a457a9a1dbcab4d4, package manifest 6.7.0. Latest published tag rea-agents-6.7.0 (27dc42d10249f0410904a75c0997842eb03b931c) was source-compared: its WABT command profile also omits --ignore-custom-section-errors. Only main's source provider was executed, not the published package runtime.

Runtime and platform

Node.js v26.12.1; Linux x64; repository-locked tsx loader; official WABT 1.0.42 Linux x64 release. GitHub's latest WABT release was checked and is 1.0.42, matching REA's admitted profile. No Hopper, Ghidra, browser, WASM instantiation, or target execution was used. Node 26.12.1 is admitted by package engines; pinned Node 24.22.1 was not separately exercised.

Target and artifact context

Self-authored core WASM version-1 binaries of 8–19 bytes. The failing fixture has the valid magic/version prefix and custom section id 0, payload length 8, UTF-8 name length 4, name name, and three opaque bytes abc. The section and module extents are exact. Only the optional interpretation of the three custom bytes is invalid; core binary framing and validation are valid.

Interface

Other

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

The final four-case provider probe exited 0, printing refusals as data. Relevant fields from its executed output:

{"label":"empty-control","node_validate":true,"wabt_status":0,"provider":{"ok":true}}
{"label":"opaque-note-control","node_validate":true,"wabt_status":0,"provider":{"ok":true}}
{"label":"opaque-name","hex":"0061736d010000000008046e616d65616263","node_validate":true,"wabt_status":1,"wabt_stderr":"0000011: error: invalid sub-section size: extends past end","tolerant_status":0,"tolerant_stderr":"0000011: warning: invalid sub-section size: extends past end","decoded_status":0,"decoded_wat":"(module\n  (@custom \"name\" \"abc\"))","provider":{"ok":false,"message":"Invalid analysis input for inspect_wasm_artifact","partial_validation":"rejected-by-selected-profile"}}
{"label":"valid-name-control","node_validate":true,"wabt_status":0,"provider":{"ok":true}}

node_validate comes only from the nonexecuting validation API. WABT's tolerant validator and decoder actually ran against the same bytes. They returned exit 0 while warning about optional metadata. REA's selected arguments request strict custom-data interpretation; its validation refusal reports an invalid-format input issue. Later stderr gates and custom-name interpretation also need to preserve this distinction; those later failure paths were not executed by the failing REA request.

Typed outcome or recovery expected

Successful static core inspection with exact selected byte identity, a retained opaque custom section, and an explicit limitation for unavailable debug-name metadata. Preserve the producer warning rather than declaring core bytes invalid or silently claiming debug-name coverage.

Analysis or suspected cause

Source-derived: the adapter makes strict interpretation of known custom sections part of module admission. WABT already exposes an explicit mode that separates custom-metadata warnings from core validation, but REA's current profile and downstream framing expect warning-free interpreted metadata. This is an integration limitation, not evidence that WABT lacks the ability to decode the core artifact.

Additional context

Open issue titles and bodies were searched first. All-state searches for WASM/WABT custom sections, name section, malformed custom metadata, and the exact ignore-custom-section-errors flag found no matching report. Closed #1956 concerns a different failure parsing valid DataCount section output. Open #5395 concerns debug-name collisions affecting exported function signature identity; this fixture has no functions or exports.

AI assistance: a delegated Codex researcher authored the inert fixtures, executed the producer/provider probes, checked the specification, and drafted this report. No code fix was made and no global configuration changed. CLI/MCP transports and real-world artifact frequency remain untested.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: The real REA provider refuses a specification-valid 18-byte module solely because of optional metadata interpretation, while three controls pass and independent nonexecuting validation accepts every case.
  • Workaround status: available
  • Workaround basis: WABT 1.0.42 with --ignore-custom-section-errors actually validated and decoded the unchanged failing bytes, preserving a warning. This is a direct-tool fallback for static inspection; it does not produce REA Evidence or supply a REA CLI/MCP recovery option.
Originally created by @coygeek on GitHub (Oct 23, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/6812 ## 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 Native analysis or decompilation ## Observed behavior `WabtArtifactProvider.inspect` refuses the 18-byte core WASM module `0061736d010000000008046e616d65616263` with `Invalid analysis input for inspect_wasm_artifact`, retaining `validation: "rejected-by-selected-profile"`. Its only section is a correctly framed custom section named `name`, containing opaque bytes `abc`. Those bytes are not valid optional debug-name metadata, but the core module is valid. Node's `WebAssembly.validate` returns true, and the admitted WABT release validates and decodes the same bytes with `--ignore-custom-section-errors`, retaining a warning. The same payload under the custom name `note`, an empty module, and a well-formed `name` payload all pass through the real REA provider. This executed the production provider with official WABT binaries, not CLI/MCP transports. No module was instantiated and no target code exists in these fixtures. ## Reproduction Use the stated source checkout with locked dependencies at `/tmp/rea-wasm-repro/rea`, or substitute its import prefix. Supply the unchanged official [WABT 1.0.42 Linux x64 release](https://github.com/WebAssembly/wabt/releases/tag/1.0.42) under `/tmp/rea-wasm-repro/wabt-1.0.42/bin`. Its downloaded archive passed the release's SHA-256 sidecar check before these probes. No global tool installation or configuration is required. Save the following executed probe, with only scratch paths normalized, as `/tmp/rea-wasm-repro/probe.mts`. All binary fixtures are inline; no compiler is required. Each final matrix case ran once. An earlier exploratory probe also observed the `name` refusal. ```sh mkdir -p /tmp/rea-wasm-repro/work /tmp/rea-wasm-repro/home /tmp/rea-wasm-repro/config HOME=/tmp/rea-wasm-repro/home XDG_CONFIG_HOME=/tmp/rea-wasm-repro/config node --import /tmp/rea-wasm-repro/rea/node_modules/tsx/dist/loader.mjs /tmp/rea-wasm-repro/probe.mts ``` ```ts import { writeFile } from 'node:fs/promises'; import { spawnSync } from 'node:child_process'; import { WabtArtifactProvider } from '/tmp/rea-wasm-repro/rea/src/wasm/WabtArtifactProvider.ts'; const root='/tmp/rea-wasm-repro'; const bin=root+'/wabt-1.0.42/bin'; for(const [label,hex] of [ ['empty-control','0061736d01000000'], ['opaque-note-control','0061736d010000000008046e6f7465616263'], ['opaque-name','0061736d010000000008046e616d65616263'], ['valid-name-control','0061736d010000000009046e616d6500020178'], ] as const){ const bytes=Buffer.from(hex,'hex');const path=root+'/work/'+label+'.wasm';await writeFile(path,bytes); const validation=spawnSync(bin+'/wasm-validate',['--enable-all',path],{encoding:'utf8'}); const tolerant=spawnSync(bin+'/wasm-validate',['--enable-all','--ignore-custom-section-errors',path],{encoding:'utf8'}); const decode=spawnSync(bin+'/wasm2wat',['--enable-all','--ignore-custom-section-errors',path],{encoding:'utf8'}); const provider=new WabtArtifactProvider({...process.env,REA_WABT_BIN_DIRECTORY:bin}); const result=await provider.inspect({path,glue_paths:[],candidate_paths:[]});await provider.close(); console.log(JSON.stringify({label,hex,node_validate:WebAssembly.validate(bytes),wabt_status:validation.status,wabt_stderr:validation.stderr.trim(),tolerant_status:tolerant.status,tolerant_stderr:tolerant.stderr.trim(),decoded_status:decode.status,decoded_wat:decode.stdout.trim(),provider:result.ok?{ok:true}:{ok:false,message:result.error.message,partial_validation:(result.error.partialObservation as any)?.normalized_result?.validation}})); } ``` ## Expected behavior Inspect the valid core module while retaining the uninterpreted custom bytes and reporting the debug-metadata interpretation failure as a limitation or warning. Optional custom-data errors should not make the selected core artifact unusable for section/interface inspection. The [WebAssembly specification's custom-section rule](https://www.w3.org/2021/11/wasm-stage/binary/modules.html#custom-section) defines the payload after its name as uninterpreted bytes and says interpretation errors must not invalidate the module. [REA's WASM inspection contract](https://github.com/morluto/rea/blob/e2efd10b70a2b5f15a7ac1b5a457a9a1dbcab4d4/docs/wasm-artifacts.md) inventories local WASM bytes, sections, imports/exports and decoded WAT. The opaque custom payload changes none of this module's core declarations. Failure of optional `name` interpretation should remain distinct from invalid core WASM. ## Impact and scope A conforming core module with optional metadata this adapter cannot interpret cannot produce a complete REA inspection. The single final failing case is 18 bytes; all three controls succeed. The failure happens before interface extraction and affects even a module with no code, imports, or exports. Prevalence in production artifacts and other custom-section conventions were not measured. Source inspection shows additional warning-rejection and debug-name decoding gates, so simply changing one command argument is not established as a complete fix. ## REA version Executed source: `e2efd10b70a2b5f15a7ac1b5a457a9a1dbcab4d4`, package manifest 6.7.0. Latest published tag `rea-agents-6.7.0` (`27dc42d10249f0410904a75c0997842eb03b931c`) was source-compared: its WABT command profile also omits `--ignore-custom-section-errors`. Only main's source provider was executed, not the published package runtime. ## Runtime and platform Node.js v26.12.1; Linux x64; repository-locked tsx loader; official WABT 1.0.42 Linux x64 release. GitHub's latest WABT release was checked and is 1.0.42, matching REA's admitted profile. No Hopper, Ghidra, browser, WASM instantiation, or target execution was used. Node 26.12.1 is admitted by package engines; pinned Node 24.22.1 was not separately exercised. ## Target and artifact context Self-authored core WASM version-1 binaries of 8–19 bytes. The failing fixture has the valid magic/version prefix and custom section id 0, payload length 8, UTF-8 name length 4, name `name`, and three opaque bytes `abc`. The section and module extents are exact. Only the optional interpretation of the three custom bytes is invalid; core binary framing and validation are valid. ## Interface Other ## Earliest failure stage Native analysis or reconstruction ## Relevant output or evidence The final four-case provider probe exited 0, printing refusals as data. Relevant fields from its executed output: ```json {"label":"empty-control","node_validate":true,"wabt_status":0,"provider":{"ok":true}} {"label":"opaque-note-control","node_validate":true,"wabt_status":0,"provider":{"ok":true}} {"label":"opaque-name","hex":"0061736d010000000008046e616d65616263","node_validate":true,"wabt_status":1,"wabt_stderr":"0000011: error: invalid sub-section size: extends past end","tolerant_status":0,"tolerant_stderr":"0000011: warning: invalid sub-section size: extends past end","decoded_status":0,"decoded_wat":"(module\n (@custom \"name\" \"abc\"))","provider":{"ok":false,"message":"Invalid analysis input for inspect_wasm_artifact","partial_validation":"rejected-by-selected-profile"}} {"label":"valid-name-control","node_validate":true,"wabt_status":0,"provider":{"ok":true}} ``` `node_validate` comes only from the nonexecuting validation API. WABT's tolerant validator and decoder actually ran against the same bytes. They returned exit 0 while warning about optional metadata. REA's [selected arguments](https://github.com/morluto/rea/blob/e2efd10b70a2b5f15a7ac1b5a457a9a1dbcab4d4/src/wasm/WabtArtifactProvider.ts#L152-L155) request strict custom-data interpretation; its [validation refusal](https://github.com/morluto/rea/blob/e2efd10b70a2b5f15a7ac1b5a457a9a1dbcab4d4/src/wasm/WabtArtifactProvider.ts#L330-L369) reports an invalid-format input issue. Later [stderr gates](https://github.com/morluto/rea/blob/e2efd10b70a2b5f15a7ac1b5a457a9a1dbcab4d4/src/wasm/WabtArtifactProvider.ts#L371-L391) and custom-name interpretation also need to preserve this distinction; those later failure paths were not executed by the failing REA request. ## Typed outcome or recovery expected Successful static core inspection with exact selected byte identity, a retained opaque custom section, and an explicit limitation for unavailable debug-name metadata. Preserve the producer warning rather than declaring core bytes invalid or silently claiming debug-name coverage. ## Analysis or suspected cause Source-derived: the adapter makes strict interpretation of known custom sections part of module admission. WABT already exposes an explicit mode that separates custom-metadata warnings from core validation, but REA's current profile and downstream framing expect warning-free interpreted metadata. This is an integration limitation, not evidence that WABT lacks the ability to decode the core artifact. ## Additional context Open issue titles and bodies were searched first. All-state searches for WASM/WABT custom sections, `name section`, malformed custom metadata, and the exact `ignore-custom-section-errors` flag found no matching report. Closed [#1956](https://github.com/morluto/rea/issues/1956) concerns a different failure parsing valid DataCount section output. Open [#5395](https://github.com/morluto/rea/issues/5395) concerns debug-name collisions affecting exported function signature identity; this fixture has no functions or exports. AI assistance: a delegated Codex researcher authored the inert fixtures, executed the producer/provider probes, checked the specification, and drafted this report. No code fix was made and no global configuration changed. CLI/MCP transports and real-world artifact frequency remain untested. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: The real REA provider refuses a specification-valid 18-byte module solely because of optional metadata interpretation, while three controls pass and independent nonexecuting validation accepts every case. - Workaround status: available - Workaround basis: WABT 1.0.42 with --ignore-custom-section-errors actually validated and decoded the unchanged failing bytes, preserving a warning. This is a direct-tool fallback for static inspection; it does not produce REA Evidence or supply a REA CLI/MCP recovery option.
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#4160
No description provided.