[GH-ISSUE #1594] [Bug] Binary plist __proto__ keys are omitted without a limitation #539

Closed
opened 2026-10-15 18:25:59 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @Adolanium on GitHub (Oct 10, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/1594

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

A binary property list dictionary keyed __proto__ decodes without a limitation. The entry is missing from the result.

XML plists with the same key report 1 dictionary entry keyed __proto__ was omitted because REA results cannot represent that key. Binary plists take the parseBinary path and pass omittedPrototypeKeys: 0. Keyed archive limitations and Interface Builder archive coverage therefore stay complete for that omission.

plist 5.0.0 assigns dictionary entries with dict[key] = value. The key __proto__ sets that object's prototype. Object.entries drops it, so the projection has no entry to count.

Reproduction

  1. Build a small bplist00 NSKeyedArchiver archive whose top dictionary contains an ordinary key plus a 9-byte placeholder key.
  2. Patch that placeholder's ASCII bytes to __proto__. buildBinary cannot keep __proto__ as an own key.
  3. Decode the bytes with decodeKeyedArchiveBytes (the inspect_keyed_archive decoder).
  4. Observe a successful archive whose limitations do not mention the omitted key.

The same bytes, written as a .nib inside an app bundle and passed to Interface Builder analysis, keep archive decoding complete.

Expected behavior

The result still omits the key, because REA results cannot represent it. The existing limitation reports the number of omitted dictionary entries, once per dictionary that references the key. A shared key object used by two dictionaries counts as two entries. ASCII and UTF-16BE spellings both count. An ordinary binary archive has no such limitation.

Impact and scope

Keyed archive and Interface Builder results can drop a legal dictionary entry and still look complete. XML plists, closed by the earlier __proto__ plist fixes, already report the omission. NIBArchive documents are a different container and are unaffected. Object.prototype is unchanged. The assignment changes only the decoded dictionary's prototype.

REA version

6.3.0, revision 02ef2b1c41e80364b6482e4586ae40e575c6d5a5

Runtime and platform

Node 22 or 24. Binary plist decoding is platform-independent.

Target and artifact context

Synthetic bplist00 keyed archive and a synthetic binary .nib plist. No third-party application bundle.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

A binary archive with one __proto__ dictionary entry returns no limitation of the form dictionary entry keyed __proto__ was omitted. The sibling XML fixture returns 1 dictionary entry keyed __proto__ was omitted because REA results cannot represent that key.

Typed outcome or recovery expected

The same limitation string, with the entry count. Interface Builder coverage status: partial and reason dictionary_entries_omitted when a binary archive omits one or more of those entries.

Analysis or suspected cause

Source-derived. decodeKeyedArchiveBytes and decodePlist in the Apple artifact readers set omittedPrototypeKeys: 0 after plist.parseBinary. The XML path in parseXmlPropertyList counts the key before projection. estimateBinaryPlistExpansion already walks dictionary key references and can count this string there.

Additional context

XML reporting landed with the __proto__ plist fixes. Open issue #1476 is binary Info.plist decoding without plutil, which is a different failure. The fix is in https://github.com/morluto/rea/pull/1593.

Originally created by @Adolanium on GitHub (Oct 10, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/1594 ### 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 A binary property list dictionary keyed `__proto__` decodes without a limitation. The entry is missing from the result. XML plists with the same key report `1 dictionary entry keyed __proto__ was omitted because REA results cannot represent that key.` Binary plists take the `parseBinary` path and pass `omittedPrototypeKeys: 0`. Keyed archive limitations and Interface Builder archive coverage therefore stay complete for that omission. `plist` 5.0.0 assigns dictionary entries with `dict[key] = value`. The key `__proto__` sets that object's prototype. `Object.entries` drops it, so the projection has no entry to count. ### Reproduction 1. Build a small `bplist00` NSKeyedArchiver archive whose top dictionary contains an ordinary key plus a 9-byte placeholder key. 2. Patch that placeholder's ASCII bytes to `__proto__`. `buildBinary` cannot keep `__proto__` as an own key. 3. Decode the bytes with `decodeKeyedArchiveBytes` (the `inspect_keyed_archive` decoder). 4. Observe a successful archive whose limitations do not mention the omitted key. The same bytes, written as a `.nib` inside an app bundle and passed to Interface Builder analysis, keep archive decoding complete. ### Expected behavior The result still omits the key, because REA results cannot represent it. The existing limitation reports the number of omitted dictionary entries, once per dictionary that references the key. A shared key object used by two dictionaries counts as two entries. ASCII and UTF-16BE spellings both count. An ordinary binary archive has no such limitation. ### Impact and scope Keyed archive and Interface Builder results can drop a legal dictionary entry and still look complete. XML plists, closed by the earlier `__proto__` plist fixes, already report the omission. NIBArchive documents are a different container and are unaffected. `Object.prototype` is unchanged. The assignment changes only the decoded dictionary's prototype. ### REA version 6.3.0, revision `02ef2b1c41e80364b6482e4586ae40e575c6d5a5` ### Runtime and platform Node 22 or 24. Binary plist decoding is platform-independent. ### Target and artifact context Synthetic `bplist00` keyed archive and a synthetic binary `.nib` plist. No third-party application bundle. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence A binary archive with one `__proto__` dictionary entry returns no limitation of the form `dictionary entry keyed __proto__ was omitted`. The sibling XML fixture returns `1 dictionary entry keyed __proto__ was omitted because REA results cannot represent that key.` ### Typed outcome or recovery expected The same limitation string, with the entry count. Interface Builder coverage `status: partial` and reason `dictionary_entries_omitted` when a binary archive omits one or more of those entries. ### Analysis or suspected cause Source-derived. `decodeKeyedArchiveBytes` and `decodePlist` in the Apple artifact readers set `omittedPrototypeKeys: 0` after `plist.parseBinary`. The XML path in `parseXmlPropertyList` counts the key before projection. `estimateBinaryPlistExpansion` already walks dictionary key references and can count this string there. ### Additional context XML reporting landed with the `__proto__` plist fixes. Open issue #1476 is binary Info.plist decoding without `plutil`, which is a different failure. The fix is in https://github.com/morluto/rea/pull/1593.
bsakaguchi 2026-10-15 18:25:59 +00:00
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#539
No description provided.