[GH-ISSUE #2751] [Bug] inspect_keyed_archive rejects XML keyed archives not named .plist #991

Closed
opened 2026-10-15 18:30:10 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @michaelkillgta on GitHub (Oct 13, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/2751

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

rea inspect-keyed-archive <path> rejects a well-formed XML NSKeyedArchiver archive unless its file name ends in .plist. The same archive in binary form opens with any extension, because binary plists are recognized by their bplist00 signature. XML plists are only recognized by the .plist name, so an XML archive saved as state.archive fails during target opening with unsupported binary format.

docs/native-investigation.md says inspect_keyed_archive "reads XML or binary Foundation keyed archives".

Reproduction

  1. Write a minimal XML keyed archive under a name other than .plist:

    cat > /tmp/state.archive <<'XML'
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0"><dict><key>$archiver</key><string>NSKeyedArchiver</string>
    <key>$objects</key><array><string>$null</string></array>
    <key>$top</key><dict/><key>$version</key><integer>100000</integer></dict></plist>
    XML
    
  2. Run rea inspect-keyed-archive /tmp/state.archive --format json. It fails.

  3. Copy the same bytes to /tmp/state.plist and rerun. It succeeds with archive_format: "xml-plist".

  4. For comparison, a binary keyed archive named state.archive (same objects, plutil -convert binary1 or Python plistlib.FMT_BINARY) opens with format: "plist".

Expected behavior

An XML property list is recognized by content, as binary plists already are, so a standalone XML keyed archive opens regardless of its extension. Non-plist XML and files whose name selects another format (.js, .map, .asar) keep their current classification.

Impact and scope

It affects the standalone-file route of inspect_keyed_archive (CLI and MCP) for XML archives that aren't named .plist. Archives selected inside an .app bundle by relative path are unaffected, and so are binary archives. The failure is a typed rejection, so no evidence is corrupted, but valid input is refused.

REA version

6.4.0 (main at 9928f357f)

Runtime and platform

Node 24.18.0; Debian 13 x64 (static artifact path, no native engine involved)

Target and artifact context

Standalone XML NSKeyedArchiver plist with a non-.plist extension

Interface

CLI

Earliest failure stage

Artifact or evidence registration

Relevant output or evidence

{"error":"Analysis failed","code":"target_unavailable","category":"unsupported_target","message":"Cannot open artifact: unsupported binary format.","retryable":false,"details":{"path":"/tmp/state.archive","reason":"unsupported binary format","constraint":"file_format_rejected"}}

Typed outcome or recovery expected

The target resolves as { kind: "artifact", format: "plist" } and inspect_keyed_archive returns the object graph with archive_format: "xml-plist".

Analysis or suspected cause

Source-derived: detectArtifactFormat in src/application/BinaryTargetResolver.ts reads an 8-byte prefix and calls hasBinaryPlistSignature ("Binary plists, including keyed archives, often use other extensions"). XML plists are only matched by namedArtifactFormat through the .plist suffix. KeyedArchiveReader itself already decodes XML (BOM-aware via decodeXmlPlistText), so only target classification is missing.

Additional context

Proposed fix: recognize an XML plist by its leading bytes (optional UTF-8/UTF-16 BOM, whitespace, XML declaration and comments, then <!DOCTYPE plist or <plist) next to the binary signature check, without overriding names that select another format. I can open a PR with a regression test in tests/boundary/filesystem/binaryTarget.test.ts.

Originally created by @michaelkillgta on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2751 ### 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 `rea inspect-keyed-archive <path>` rejects a well-formed XML `NSKeyedArchiver` archive unless its file name ends in `.plist`. The same archive in binary form opens with any extension, because binary plists are recognized by their `bplist00` signature. XML plists are only recognized by the `.plist` name, so an XML archive saved as `state.archive` fails during target opening with `unsupported binary format`. `docs/native-investigation.md` says `inspect_keyed_archive` "reads XML or binary Foundation keyed archives". ### Reproduction 1. Write a minimal XML keyed archive under a name other than `.plist`: ```sh cat > /tmp/state.archive <<'XML' <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"><dict><key>$archiver</key><string>NSKeyedArchiver</string> <key>$objects</key><array><string>$null</string></array> <key>$top</key><dict/><key>$version</key><integer>100000</integer></dict></plist> XML ``` 2. Run `rea inspect-keyed-archive /tmp/state.archive --format json`. It fails. 3. Copy the same bytes to `/tmp/state.plist` and rerun. It succeeds with `archive_format: "xml-plist"`. 4. For comparison, a binary keyed archive named `state.archive` (same objects, `plutil -convert binary1` or Python `plistlib.FMT_BINARY`) opens with `format: "plist"`. ### Expected behavior An XML property list is recognized by content, as binary plists already are, so a standalone XML keyed archive opens regardless of its extension. Non-plist XML and files whose name selects another format (`.js`, `.map`, `.asar`) keep their current classification. ### Impact and scope It affects the standalone-file route of `inspect_keyed_archive` (CLI and MCP) for XML archives that aren't named `.plist`. Archives selected inside an `.app` bundle by relative path are unaffected, and so are binary archives. The failure is a typed rejection, so no evidence is corrupted, but valid input is refused. ### REA version 6.4.0 (main at 9928f357f) ### Runtime and platform Node 24.18.0; Debian 13 x64 (static artifact path, no native engine involved) ### Target and artifact context Standalone XML NSKeyedArchiver plist with a non-`.plist` extension ### Interface CLI ### Earliest failure stage Artifact or evidence registration ### Relevant output or evidence ```text {"error":"Analysis failed","code":"target_unavailable","category":"unsupported_target","message":"Cannot open artifact: unsupported binary format.","retryable":false,"details":{"path":"/tmp/state.archive","reason":"unsupported binary format","constraint":"file_format_rejected"}} ``` ### Typed outcome or recovery expected The target resolves as `{ kind: "artifact", format: "plist" }` and `inspect_keyed_archive` returns the object graph with `archive_format: "xml-plist"`. ### Analysis or suspected cause Source-derived: `detectArtifactFormat` in `src/application/BinaryTargetResolver.ts` reads an 8-byte prefix and calls `hasBinaryPlistSignature` ("Binary plists, including keyed archives, often use other extensions"). XML plists are only matched by `namedArtifactFormat` through the `.plist` suffix. `KeyedArchiveReader` itself already decodes XML (BOM-aware via `decodeXmlPlistText`), so only target classification is missing. ### Additional context Proposed fix: recognize an XML plist by its leading bytes (optional UTF-8/UTF-16 BOM, whitespace, XML declaration and comments, then `<!DOCTYPE plist` or `<plist`) next to the binary signature check, without overriding names that select another format. I can open a PR with a regression test in `tests/boundary/filesystem/binaryTarget.test.ts`.
bsakaguchi 2026-10-15 18:30:10 +00:00
Author
Owner

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

The compiled CLI now recognizes and inspects an XML keyed archive from its content when the filename uses a non-.plist suffix. The end-to-end CLI regression passes on current main.

Root cause: Target resolution recognized XML plist only by .plist suffix even though the keyed-archive decoder accepts XML content.

Validation: tests/boundary/cli/keyedArchiveXmlExtensionCli.test.ts: 'compiled CLI inspects an XML keyed archive with a non-plist suffix' confirms Model.archive resolves and returns xml-plist object data. tests/boundary/filesystem/binaryTarget.test.ts: 'classifies XML plists by content while preserving named formats' confirms .archive positive and .js negative. These assertions passed in CI at 500e32399; the reviewed implementation is present on current main. Fix: ec271121e4996f89f666a5a2ed1cd2f3229411b4.

Verification scope: Source precedence was checked for .asar and .map; the cited XML-signature regression directly exercises .js as the named-format control, not each suffix.

<!-- gh-comment-id:6161951728 --> @morluto commented on GitHub (Oct 14, 2026): The compiled CLI now recognizes and inspects an XML keyed archive from its content when the filename uses a non-.plist suffix. The end-to-end CLI regression passes on current main. Root cause: Target resolution recognized XML plist only by .plist suffix even though the keyed-archive decoder accepts XML content. Validation: tests/boundary/cli/keyedArchiveXmlExtensionCli.test.ts: 'compiled CLI inspects an XML keyed archive with a non-plist suffix' confirms Model.archive resolves and returns xml-plist object data. tests/boundary/filesystem/binaryTarget.test.ts: 'classifies XML plists by content while preserving named formats' confirms .archive positive and .js negative. These assertions passed in [CI at 500e32399](https://github.com/morluto/rea/actions/runs/38514789942); the reviewed implementation is present on current main. Fix: [ec271121e4996f89f666a5a2ed1cd2f3229411b4](https://github.com/morluto/rea/commit/ec271121e4996f89f666a5a2ed1cd2f3229411b4). Verification scope: Source precedence was checked for .asar and .map; the cited XML-signature regression directly exercises .js as the named-format control, not each suffix.
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#991
No description provided.