[PR #857] [MERGED] fix(target): decode app Info.plist executables with an XML parser #2294

Closed
opened 2026-10-16 21:16:51 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/857
Author: @kaoru0822-kitauji
Created: 10/7/2026
Status: ✅ Merged
Merged: 10/7/2026
Merged by: @kaoru0822-kitauji

Base: main ← Head: fix/app-xml-plist-executable


📝 Commits (1)

  • c182f72 fix(target): decode app Info.plist executables with an XML parser

📊 Changes

2 files changed (+71 additions, -14 deletions)

View changed files

📝 src/application/BinaryTargetResolver.ts (+15 -14)
📝 tests/boundary/filesystem/binaryTarget.test.ts (+56 -0)

📄 Description

Summary

A macOS .app target resolves to Contents/MacOS/<CFBundleExecutable>. For XML Info.plist files, BinaryTargetResolver read that value with a regular expression and a hand-written entity decoder. Several valid plists therefore resolved to the wrong name, and inspect-macho, list-architectures, and session open reported app program file is missing:

Info.plist content Native plutil -extract CFBundleExecutable raw REA on main
<string>a&amp;lt;b</string> a&lt;b decodes twice to a<b → missing
<string>a&#32;b</string> a b numeric reference left undecoded → missing
<string><![CDATA[a&b]]></string> a&b no match → "no readable CFBundleExecutable"
commented-out <key>CFBundleExecutable</key><string>Old</string> before the real key App picks Old
a nested dict with its own CFBundleExecutable before the top-level key top-level value picks the nested value

Fix

XML plists are decoded with the plist package, which InterfaceBuilderAnalysis already uses in the application layer. The resolver reads the top-level dictionary's CFBundleExecutable string. Binary plists still use native plutil -n, unchanged. The existing name-safety and Contents/MacOS containment checks are unchanged. An empty <string/> is now rejected as an unsafe name instead of an unreadable key.

This only affects file resolution. Nothing is executed, and there is no provider claim. The whitespace cases from #765 were already handled on main and remain covered.

Verification

  • New regressions in tests/boundary/filesystem/binaryTarget.test.ts cover entity, numeric-reference, CDATA, and commented/nested key cases. 4 fail on main and pass here. The existing whitespace, unsafe-name, symlink-escape, and binary-plist tests still pass (21/21).
  • Real CLI check on macOS arm64: Clang-compiled programs in three .app bundles (a&amp;lt;b, a&#32;b, and a commented key). node scripts/rea.mjs inspect-macho X.app reported app program file is missing for all three on main. With this change it resolves Contents/MacOS/a&lt;b, a b, and App and reports arm64.
  • npm run check:changed: 18 files / 144 tests passed. npm run check:fast passed.
  • tests/composition/analysis-sessions/appleApplication.test.ts and tests/boundary/providers/native/nativeProvider.test.ts passed. In interfaceBuilderBundle.test.ts, the Xcode-compiled storyboard case fails locally on both main and this branch, because ibtool requires full Xcode and this host has only Command Line Tools.

No Hopper/Ghidra/IDA verification is needed (target path resolution only).

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/857 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/7/2026 **Status:** ✅ Merged **Merged:** 10/7/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `fix/app-xml-plist-executable` --- ### 📝 Commits (1) - [`c182f72`](https://github.com/morluto/rea/commit/c182f72ad3d9eea10b084a43527acb7c8ca2d6bf) fix(target): decode app Info.plist executables with an XML parser ### 📊 Changes **2 files changed** (+71 additions, -14 deletions) <details> <summary>View changed files</summary> 📝 `src/application/BinaryTargetResolver.ts` (+15 -14) 📝 `tests/boundary/filesystem/binaryTarget.test.ts` (+56 -0) </details> ### 📄 Description ## Summary A macOS `.app` target resolves to `Contents/MacOS/<CFBundleExecutable>`. For XML `Info.plist` files, `BinaryTargetResolver` read that value with a regular expression and a hand-written entity decoder. Several valid plists therefore resolved to the wrong name, and `inspect-macho`, `list-architectures`, and session open reported `app program file is missing`: | `Info.plist` content | Native `plutil -extract CFBundleExecutable raw` | REA on `main` | |---|---|---| | `<string>a&amp;lt;b</string>` | `a&lt;b` | decodes twice to `a<b` → missing | | `<string>a&#32;b</string>` | `a b` | numeric reference left undecoded → missing | | `<string><![CDATA[a&b]]></string>` | `a&b` | no match → "no readable CFBundleExecutable" | | commented-out `<key>CFBundleExecutable</key><string>Old</string>` before the real key | `App` | picks `Old` | | a nested dict with its own `CFBundleExecutable` before the top-level key | top-level value | picks the nested value | ## Fix XML plists are decoded with the `plist` package, which `InterfaceBuilderAnalysis` already uses in the application layer. The resolver reads the **top-level** dictionary's `CFBundleExecutable` string. Binary plists still use native `plutil -n`, unchanged. The existing name-safety and `Contents/MacOS` containment checks are unchanged. An empty `<string/>` is now rejected as an unsafe name instead of an unreadable key. This only affects file resolution. Nothing is executed, and there is no provider claim. The whitespace cases from #765 were already handled on `main` and remain covered. ## Verification - New regressions in `tests/boundary/filesystem/binaryTarget.test.ts` cover entity, numeric-reference, CDATA, and commented/nested key cases. **4 fail on `main` and pass here.** The existing whitespace, unsafe-name, symlink-escape, and binary-plist tests still pass (21/21). - Real CLI check on macOS arm64: Clang-compiled programs in three `.app` bundles (`a&amp;lt;b`, `a&#32;b`, and a commented key). `node scripts/rea.mjs inspect-macho X.app` reported `app program file is missing` for all three on `main`. With this change it resolves `Contents/MacOS/a&lt;b`, `a b`, and `App` and reports `arm64`. - `npm run check:changed`: 18 files / 144 tests passed. `npm run check:fast` passed. - `tests/composition/analysis-sessions/appleApplication.test.ts` and `tests/boundary/providers/native/nativeProvider.test.ts` passed. In `interfaceBuilderBundle.test.ts`, the Xcode-compiled storyboard case fails locally on both `main` and this branch, because `ibtool` requires full Xcode and this host has only Command Line Tools. No Hopper/Ghidra/IDA verification is needed (target path resolution only). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-16 21:16:51 +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#2294
No description provided.