[GH-ISSUE #3913] [Bug] scalar root named UID creates a false keyed-archive reference #1524

Closed
opened 2026-10-16 21:06:37 +00:00 by bsakaguchi · 2 comments
Owner

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

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

inspect-keyed-archive --root UID treats an ordinary integer root named UID as an unresolved object reference. The supplied valid archive has no references. Selecting all roots avoids the false edge because the enclosing root dictionary then has two keys. This changes the typed reference inventory and total while leaving the raw scalar accessible. The failure is source-derived; REA execution was not run.

The static proof predicts roots: {"UID":1}, total_objects: 1, total_references: 1, and a false edge:

{"source":null,"path":[],"target":1,"status":"unresolved","raw":{"UID":1}}

Without a root selector, the two-key top dictionary is traversed normally and the reference list is empty. No REA runtime output or exit status was observed.

Reproduction

These public REA steps are proposed and unexecuted. Save the complete fixture as scalar-roots.plist in a disposable directory:

<?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>$version</key><integer>100000</integer>
<key>$archiver</key><string>NSKeyedArchiver</string>
<key>$top</key><dict><key>UID</key><integer>1</integer><key>ordinary</key><integer>7</integer></dict>
<key>$objects</key><array><string>$null</string></array>
</dict></plist>

Run rea inspect-keyed-archive scalar-roots.plist --root UID --json. Compare with rea inspect-keyed-archive scalar-roots.plist --json and rea inspect-keyed-archive scalar-roots.plist --root ordinary --json. The input is small and shallow, has the required archiver, object table and nonempty top dictionary, and selects an existing root.

The initial executed validity probe allocated NSKeyedArchiver with initRequiringSecureCoding:false, called encodeInt64:forKey: with (1, "UID") and (7, "ordinary"), called finishEncoding, and read encodedData. Python plistlib decoded the 149-byte binary output to exactly:

{"$archiver":"NSKeyedArchiver","$objects":["$null"],"$top":{"UID":1,"ordinary":7},"$version":100000}

The XML fixture preserves those serialized values. This Foundation output is a validity control only. It does not establish executed REA parsing or output.

Expected behavior

Selecting UID preserves primitive integer 1, reports no reference edges, and returns total_references: 0. A root's name must not turn its scalar into a serialized UID. Named selection must preserve the root's value type and reference identity.

Impact and scope

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: A valid Foundation-produced primitive root becomes false unresolved-reference evidence under an explicitly supported selector. The raw scalar remains accessible, and the affected input/selector combination is bounded.

REA version

The inspected source baseline is published rea-agents-6.5.0, revision 3b79af28e80785afce9f5998d8f03289402a1847. The source review compared fetched main cf0a38ad9774ee9acff3164052688f7a58a1c72c; main changes the path-schema import/use in src/domain/apple/keyedArchive.ts, while the UID detector, root selection, scan and result construction remain unchanged. A separate Foundation serialization probe ran on macOS through Python ctypes. Its exact OS version, architecture and Python version are NOT_ENOUGH_INFO in the supplied evidence. That probe establishes input validity only, not REA behavior. REA runtime results, installed-runtime behavior and MCP transport behavior were not measured.

Runtime and platform

REA runtime reproduction was not run. Runtime and platform details for any smaller premise checks are recorded in the version/environment field above. Real-provider versions and end-to-end output are NOT_ENOUGH_INFO because no provider was launched.

Target and artifact context

Standalone XML plist containing a valid NSKeyedArchiver envelope, two primitive integer roots and a one-entry nil object table; Foundation binary serialization supplies the validity control.

Interface

CLI

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

  • Expected source: documented named-root and reference-identity contract and named top-entry selection. The Foundation serialization result establishes that the root is a primitive integer.
  • Failure source: UID detection and root projection. Lines 79-84 treat a one-key numeric UID dictionary as a reference; lines 125-128 construct that shape for this selected scalar; lines 130-179 scan the entire root map and generate the false edge at lines 142-158. Lines 223-227 retain root-source references and report their total.
  • Evidence provenance: static
  • Local verification: static-proof
  • Reproduction completeness: complete

Primary violation evidence is the source trace. The observed Foundation output supports only the valid-input premise. Runtime REA reproduction was not run.

The public path is src/cli/artifactCommands.ts:20-58, accepting a plist path and unrestricted optional root string and dispatching inspect_keyed_archive; src/application/DirectAnalysis.ts:130-157,322-326,442, selecting the artifact-only session, opening the target and dispatching; and src/application/BinaryTargetResolver.ts:319-323,192-200, admitting the .plist artifact. src/artifacts/ArtifactProvider.ts:131-173 accepts the target and default archive selector ., converts it to the basename, and invokes inspectBundleKeyedArchive. src/artifacts/apple/KeyedArchiveReader.ts:140-215,69-81 reads the regular file, decodes and projects it. Domain lines 102-128 accept this envelope and root; the numeric scalar survives projection. No class, provider or resource-limit prerequisite blocks this small fixture. Completeness describes this static proof, not an executed REA reproduction.

Typed outcome or recovery expected

The exact fixture must return zero references when selecting UID, selecting ordinary, or selecting all roots, while preserving selected values and the sole nil object. A genuine reference-valued root named UID, such as $top: {"UID":{"CF$UID":1}} with object 1 present, must still produce a resolved root edge at path ["UID"]. This distinguishes scalar preservation from disabling reference detection. These proposed checks have not run.

Additional context

The defect can make a consumer mistake a scalar for a missing object; real-application prevalence is unknown. Initial duplicate screening found no clear duplicate. Existing coverage in scripts/verify/apple/keyed-archive.mjs:125-170 and tests/conformance/native/keyed-archive-uid-root.swift concerns reference-valued roots named UID and CF$UID, rather than numeric scalar roots.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: A valid Foundation-produced primitive root becomes false unresolved-reference evidence under an explicitly supported selector. The raw scalar remains accessible, and the affected input/selector combination is bounded.
  • Workaround status: unverified
  • Workaround basis: Omitting root selection for this two-root archive avoids the one-key detector by source reasoning. No REA command verified that workaround, and it changes the requested root selection.
Originally created by @coygeek on GitHub (Oct 15, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3913 ## 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 `inspect-keyed-archive --root UID` treats an ordinary integer root named `UID` as an unresolved object reference. The supplied valid archive has no references. Selecting all roots avoids the false edge because the enclosing root dictionary then has two keys. This changes the typed reference inventory and total while leaving the raw scalar accessible. The failure is source-derived; REA execution was not run. The static proof predicts `roots: {"UID":1}`, `total_objects: 1`, `total_references: 1`, and a false edge: ```json {"source":null,"path":[],"target":1,"status":"unresolved","raw":{"UID":1}} ``` Without a root selector, the two-key top dictionary is traversed normally and the reference list is empty. No REA runtime output or exit status was observed. ## Reproduction These public REA steps are proposed and unexecuted. Save the complete fixture as `scalar-roots.plist` in a disposable directory: ```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>$version</key><integer>100000</integer> <key>$archiver</key><string>NSKeyedArchiver</string> <key>$top</key><dict><key>UID</key><integer>1</integer><key>ordinary</key><integer>7</integer></dict> <key>$objects</key><array><string>$null</string></array> </dict></plist> ``` Run `rea inspect-keyed-archive scalar-roots.plist --root UID --json`. Compare with `rea inspect-keyed-archive scalar-roots.plist --json` and `rea inspect-keyed-archive scalar-roots.plist --root ordinary --json`. The input is small and shallow, has the required archiver, object table and nonempty top dictionary, and selects an existing root. The initial executed validity probe allocated `NSKeyedArchiver` with `initRequiringSecureCoding:false`, called `encodeInt64:forKey:` with `(1, "UID")` and `(7, "ordinary")`, called `finishEncoding`, and read `encodedData`. Python plistlib decoded the 149-byte binary output to exactly: ```json {"$archiver":"NSKeyedArchiver","$objects":["$null"],"$top":{"UID":1,"ordinary":7},"$version":100000} ``` The XML fixture preserves those serialized values. This Foundation output is a validity control only. It does not establish executed REA parsing or output. ## Expected behavior Selecting `UID` preserves primitive integer `1`, reports no reference edges, and returns `total_references: 0`. A root's name must not turn its scalar into a serialized UID. Named selection must preserve the root's value type and reference identity. ## Impact and scope - Impact level: P2 - Assessment status: supported - Impact basis: A valid Foundation-produced primitive root becomes false unresolved-reference evidence under an explicitly supported selector. The raw scalar remains accessible, and the affected input/selector combination is bounded. ## REA version The inspected source baseline is published `rea-agents-6.5.0`, revision `3b79af28e80785afce9f5998d8f03289402a1847`. The source review compared fetched main `cf0a38ad9774ee9acff3164052688f7a58a1c72c`; main changes the path-schema import/use in `src/domain/apple/keyedArchive.ts`, while the UID detector, root selection, scan and result construction remain unchanged. A separate Foundation serialization probe ran on macOS through Python ctypes. Its exact OS version, architecture and Python version are NOT_ENOUGH_INFO in the supplied evidence. That probe establishes input validity only, not REA behavior. REA runtime results, installed-runtime behavior and MCP transport behavior were not measured. ## Runtime and platform REA runtime reproduction was not run. Runtime and platform details for any smaller premise checks are recorded in the version/environment field above. Real-provider versions and end-to-end output are NOT_ENOUGH_INFO because no provider was launched. ## Target and artifact context Standalone XML plist containing a valid NSKeyedArchiver envelope, two primitive integer roots and a one-entry nil object table; Foundation binary serialization supplies the validity control. ## Interface CLI ## Earliest failure stage Native analysis or reconstruction ## Relevant output or evidence - Expected source: [documented named-root and reference-identity contract](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/docs/native-investigation.md#L311-L323) and [named top-entry selection](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/domain/apple/keyedArchive.ts#L231-L234). The Foundation serialization result establishes that the root is a primitive integer. - Failure source: [UID detection and root projection](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/domain/apple/keyedArchive.ts#L79-L84). Lines 79-84 treat a one-key numeric `UID` dictionary as a reference; lines 125-128 construct that shape for this selected scalar; lines 130-179 scan the entire root map and generate the false edge at lines 142-158. Lines 223-227 retain root-source references and report their total. - Evidence provenance: static - Local verification: static-proof - Reproduction completeness: complete Primary violation evidence is the source trace. The observed Foundation output supports only the valid-input premise. Runtime REA reproduction was not run. The public path is `src/cli/artifactCommands.ts:20-58`, accepting a plist path and unrestricted optional root string and dispatching `inspect_keyed_archive`; `src/application/DirectAnalysis.ts:130-157,322-326,442`, selecting the artifact-only session, opening the target and dispatching; and `src/application/BinaryTargetResolver.ts:319-323,192-200`, admitting the `.plist` artifact. `src/artifacts/ArtifactProvider.ts:131-173` accepts the target and default archive selector `.`, converts it to the basename, and invokes `inspectBundleKeyedArchive`. `src/artifacts/apple/KeyedArchiveReader.ts:140-215,69-81` reads the regular file, decodes and projects it. Domain lines 102-128 accept this envelope and root; the numeric scalar survives projection. No class, provider or resource-limit prerequisite blocks this small fixture. Completeness describes this static proof, not an executed REA reproduction. ## Typed outcome or recovery expected The exact fixture must return zero references when selecting `UID`, selecting `ordinary`, or selecting all roots, while preserving selected values and the sole nil object. A genuine reference-valued root named `UID`, such as `$top: {"UID":{"CF$UID":1}}` with object 1 present, must still produce a resolved root edge at path `["UID"]`. This distinguishes scalar preservation from disabling reference detection. These proposed checks have not run. ## Additional context The defect can make a consumer mistake a scalar for a missing object; real-application prevalence is unknown. Initial duplicate screening found no clear duplicate. Existing coverage in `scripts/verify/apple/keyed-archive.mjs:125-170` and `tests/conformance/native/keyed-archive-uid-root.swift` concerns reference-valued roots named `UID` and `CF$UID`, rather than numeric scalar roots. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: A valid Foundation-produced primitive root becomes false unresolved-reference evidence under an explicitly supported selector. The raw scalar remains accessible, and the affected input/selector combination is bounded. - Workaround status: unverified - Workaround basis: Omitting root selection for this two-root archive avoids the one-key detector by source reasoning. No REA command verified that workaround, and it changes the requested root selection.
Author
Owner

@Sriram-PR commented on GitHub (Oct 15, 2026):

I'll take this one. Reproduced on main (6fcfc5b): --root UID gives total_references: 1 with the {"UID":1} edge. The cause is scan(null, roots) running the UID check on the one-key roots wrapper itself. Plan: scan each selected root's value under its key instead, plus a regression test with the scalar UID root and the all-roots control. PR shortly.

<!-- gh-comment-id:6186767250 --> @Sriram-PR commented on GitHub (Oct 15, 2026): I'll take this one. Reproduced on main (6fcfc5b): `--root UID` gives `total_references: 1` with the `{"UID":1}` edge. The cause is `scan(null, roots)` running the UID check on the one-key roots wrapper itself. Plan: scan each selected root's value under its key instead, plus a regression test with the scalar `UID` root and the all-roots control. PR shortly.
Author
Owner

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

Fixed on main in 5a590e61b. Keyed-archive traversal treats top-level names separately from their values, so a scalar root named UID or CF$UID is not an encoded reference.

Root-selection and filesystem reader regressions cover the reported scalar-root behavior; the unrelated aggregate-budget stress case was not run locally.

Hosted main CI is still pending; this closure is based on the implemented fix and the scoped regression evidence.

<!-- gh-comment-id:6206039993 --> @morluto commented on GitHub (Oct 16, 2026): Fixed on `main` in [5a590e61b](https://github.com/morluto/rea/commit/5a590e61b1f2b026c2eca0add1514a61b86a3088). Keyed-archive traversal treats top-level names separately from their values, so a scalar root named UID or CF$UID is not an encoded reference. Root-selection and filesystem reader regressions cover the reported scalar-root behavior; the unrelated aggregate-budget stress case was not run locally. Hosted main CI is still pending; this closure is based on the implemented fix and the scoped regression evidence.
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#1524
No description provided.