[GH-ISSUE #4312] [Feature] Report Mach-O placements that violate Apple's documented bundle layout rules #1716

Open
opened 2026-10-16 21:09:22 +00:00 by bsakaguchi · 1 comment
Owner

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

Before submitting

  • I searched the open and closed issues and pull requests for a related proposal.
  • I understand the contribution scope must be reviewed before integration; open questions are welcome here.
  • This request does not include credentials, private samples, or sensitive target data.

Area

Evidence, artifacts, or reconstruction

Current limitation

Have project_apple_application_graph report placement findings when a bundle holds Mach-O code where Apple's "Placing content in a bundle" rules say code does not belong: Mach-O images under resource directories, standalone dynamic libraries in iOS, watchOS, or tvOS bundles, frameworks inside iOS or tvOS app extensions, non-symlink content at a macOS framework root, and grouping directories inside code locations. Each finding cites the Apple rule, the exact paths, and the facts it rests on. The check stays static: it never signs, verifies, or launches anything.

An analyst triaging an IPA or a macOS .app wants to know whether code sits where the platform expects it. Misplaced code can point to a hand-assembled, repackaged, or tampered bundle, and Apple warns that it causes code-signing and distribution problems that "aren't always immediately obvious". REA lists every component but never says that a placement contradicts Apple's layout, so the analyst compares each path with Apple's table by hand.

The graph assigns roles by path convention (appleBundleAnatomy.ts L244-L267). It derives the platform from layout alone: macos-deep becomes macos, and a shallow root with an Info.plist becomes ios (L367-L379). Neither the bundle schema (L20-L43) nor the result schema (appleApplication.ts L44-L96) has a findings, warnings, or anomaly field. The fixed limitations (L397-L454) say nothing about placement.

Observed with REA 6.5.0 (npx -y rea-agents@6.5.0) on macOS 27.0.1 (26A434) arm64 with Xcode 27.0 (27A266a), using inspect-artifact and then project-apple-application-graph on two self-built fixtures:

# macOS fixture: ./fixture/Fixture.app
mkdir -p Fixture.app/Contents/{MacOS,Resources,PlugIns/Group.v2/Inner.bundle/Contents/MacOS}
clang -o Fixture.app/Contents/MacOS/Fixture main.c
clang -o Fixture.app/Contents/Resources/payload.dat main.c        # Mach-O, no code-like extension
clang -dynamiclib -o Fixture.app/Contents/Resources/libextra.dylib lib.c
printf '#!/bin/sh\n' > Fixture.app/Contents/Resources/run.sh      # script = resource
clang -bundle -o Fixture.app/Contents/PlugIns/Group.v2/Inner.bundle/Contents/MacOS/Inner lib.c
# plus Contents/Frameworks/Demo.framework in the standard Versions/A + symlink layout,
# with one extra regular file Demo.framework/libstray.dylib (Mach-O) at its root,
# and Info.plist files at the documented locations
# tvOS-shaped IPA: Payload/Shallow.app built with -target arm64-apple-tvos17.0
#   Shallow.app/libloose.dylib and Shallow.app/PlugIns/Ext.appex/Frameworks/Inner.framework/Inner
  • For the macOS fixture, the release build reports platforms: ["macos"] and lists Contents/Resources/payload.dat, Contents/Resources/libextra.dylib, and Contents/Frameworks/Demo.framework/libstray.dylib under components.executables with format mach-o. It ignores run.sh, which is correct. It reports Inner.bundle with role bundle rather than plug-in because its parent is Group.v2. Nothing in the result marks any of these placements.
  • For the IPA, whose main executable's LC_BUILD_VERSION platform is TVOS according to vtool -show-build, the release build reports platforms: ["ios"]. It lists libloose.dylib only under native_libraries and reports Inner.framework as a framework whose parent is Ext.appex. Again, no finding is reported.

Use cases

No response

Desired outcome and success criteria

project_apple_application_graph adds a placement-findings section to its result. Each finding carries a stable rule identifier, the bundle path, the offending path or paths, the facts the rule used (Mach-O format from magic, Mach-O file type, the platform and how it was established, and whether the entry is a symlink), and a short citation of the Apple rule. A finding reports a mismatch with Apple's documented layout. It is not a verdict that the bundle is malicious or will fail.

Rules, each evaluated per bundle:

  1. Code in a resource location: a Mach-O image, or a nested bundle that contains one, under macOS Contents/Resources/ or a macOS framework's Versions/<version>/Resources/. Report one finding for each outermost misplaced item. Scripts and other non-Mach-O files never match.
  2. Standalone dynamic library: a Mach-O image whose header file type is MH_DYLIB (every slice of a FAT file) and that lies outside every .framework bundle, in a bundle whose platform is established as iOS, watchOS, or tvOS. Swift system libraries (libswift*.dylib, the convention REA already uses in nativeConvention.ts L36-L40) are exempt. The filename extension is never the basis.
  3. Framework in a nested bundle: a .framework inside an app extension (.appex) whose platform is established as iOS or tvOS. watchOS is exempt, because Apple documents a Frameworks/ directory inside the WatchKit extension.
  4. macOS framework root: in a versioned-framework layout, any root entry other than the Versions directory and symlinks, or any entry in Versions other than real version directories and a Current symlink.
  5. Grouping directory in a code location: a directory directly inside a code location (for example Contents/PlugIns/, Contents/Frameworks/, Contents/XPCServices/, or iOS PlugIns/) that has no bundle anatomy of its own but contains code. If the directory name contains a dot, the finding also cites the dotted-name rule.

Platform handling stays fail-closed. The macOS rules (1 and 4) apply only to observed macos-deep or versioned-framework layouts. Mac Catalyst is covered too, because Apple's table treats Mac Catalyst as macOS. Rules 2 and 3 apply only when the bundle's platform is established from target content, such as the build-platform load command of its main executable. A shallow layout alone establishes only an iOS-family layout, so iOS, tvOS, watchOS, and visionOS cannot be told apart from it. When the platform is unknown, or is a platform the rule does not name (visionOS for rule 2, watchOS and visionOS for rule 3), the result records the rule as not evaluated for that bundle, with the reason, and emits no finding. Partial inventory coverage, and entries whose format is unknown (for example a truncated FAT header), make the affected rules partial, so an empty findings list is never presented as a clean result.

Acceptance criteria

  • On the macOS fixture above, the result contains rule-1 findings for Contents/Resources/payload.dat and Contents/Resources/libextra.dylib and none for Contents/Resources/run.sh.
  • Renaming payload.dat to payload.txt does not change its rule-1 finding, and an executable shell script renamed helper.dylib under Contents/Resources/ produces no finding.
  • A .bundle directory under Contents/Resources/ that holds Contents/MacOS/<Mach-O> yields exactly one rule-1 finding, which names the nested bundle and lists its Mach-O path.
  • Contents/Frameworks/Demo.framework/libstray.dylib produces a rule-4 finding. The standard root symlinks Demo, Resources, and Versions/Current produce none.
  • Contents/PlugIns/Group.v2/Inner.bundle produces a rule-5 finding on Contents/PlugIns/Group.v2 that cites both the flat-list rule and the dotted-name rule. An undotted grouping directory, Contents/PlugIns/Waffles/Belgian.plugin, produces a rule-5 finding that cites only the flat-list rule.
  • On the tvOS-built IPA fixture, libloose.dylib produces a rule-2 finding and PlugIns/Ext.appex/Frameworks/Inner.framework produces a rule-3 finding, and each finding records the platform as tvOS together with its basis. A Frameworks/libswiftCore.dylib built the same way produces no rule-2 finding.
  • The same IPA rebuilt with -target arm64-apple-xros2.0 (visionOS) produces no rule-2 or rule-3 finding, and the result records both rules as not evaluated for that bundle, with the reason.
  • An IPA whose shallow app has an Info.plist and the loose libloose.dylib but no main executable at its root produces no rule-2 or rule-3 findings and records both rules as not evaluated because the platform is unknown.
  • /System/Applications/Stickies.app produces no rule-1, rule-4, or rule-5 findings.
  • Every finding names the Apple page it relies on, and the projection still never executes, signs, or verifies target code.

Expected interaction with targets

Read existing files or captured data

Target and scope details (optional)

Affected area

  • project_apple_application_graph (MCP tool and project-apple-application-graph CLI): result schema, Apple bundle anatomy projection, and the related documentation in docs/apple-application-analysis.md.

Non-goals

  • Code-signature verification, sealed-resource checks, and nested-code signature validation.
  • Mapping launchd, XPC, privileged-helper, login-item, or system-extension relationships as graph edges.
  • Privacy-manifest parsing or validation.
  • Resolving @rpath and other load paths, which trace_dylib_resolution already covers.
  • Judging whether a placement is malicious, or predicting App Store or notarization outcomes.
  • Flagging every Mach-O image that sits outside the table's code locations. That broader check is discussed under Alternatives considered.

Verification available so far

I can suggest a sample or manual check

Verification details (optional)

No response

Alternatives considered

  • A new standalone tool. This would duplicate the bundle-anatomy logic and force the analyst to join two results.
  • Fold the rules into trace_dylib_resolution. That tool models dyld loading, but resource placement, framework-root layout, and grouping directories are not dyld concerns.
  • Flag any Mach-O outside the table's code locations. This was rejected for this issue because Apple's table omits locations documented elsewhere (for example the ExtensionKit Extensions/ folder), and on iOS-family layouts the bundle root holds both the main executable and resources. Absence from the table is therefore not a stated rule, and the check would produce noisy findings.

Possible direction

No response

References

  • Apple, Placing content in a bundle (https://developer.apple.com/documentation/bundleresources/placing-content-in-a-bundle):
    • "In this context, executable code means a Mach-O image. It doesn't include things like shell scripts, Python scripts, and AppleScripts ... you treat it as a resource." The same page says "Resources are everything that's not code" and "The macOS platform covers both Mac and Mac Catalyst apps."
    • The page's table places resources at macOS Contents/Resources/, at a macOS framework's Versions/A/Resources/, and at / for iOS, watchOS, tvOS, and visionOS. It places frameworks and dynamic libraries at Contents/Frameworks/ and Versions/A/Frameworks/ on macOS and at Frameworks/ on iOS, tvOS, and visionOS, and it refers watchOS to a separate section.
    • "iOS, watchOS, and tvOS support third-party frameworks but don't support third-party standalone dynamic libraries, which are those outside a framework bundle, typically with the .dylib filename extension. The only exception to this rule is the Swift system libraries provided by Xcode." visionOS is not named in this sentence.
    • "iOS and tvOS support frameworks and Swift system libraries at the topmost app level; a nested bundle, like an app extension, can't include a framework." For watchOS, Apple says to "Place watchOS frameworks in the WatchKit extension's Frameworks directory".
    • "The framework's root must contain only the Versions directory and symlinks." "Similarly, the Versions directory must contain only version directories — ideally just one, called A — and a symlink called Current that targets one version directory."
    • "Each code location must contain a flat list of code content." "The code-signing machinery assumes that any directory with a name that contains a dot is a bundle, and then fails when signing that directory because it's not a well-formed bundle."
  • The required evidence already exists: inventory formats come from Mach-O magic, thin or FAT (ArtifactGraphConstruction.ts L532-L588), symlinks are reported by path, and trace_dylib_resolution already reads build-platform load commands in TypeScript (MachoLoadCommandReader.ts L37-L41, L385-L399).
  • Related: #3359 (open; PR #3505 open) reports that a regular Contents resource misclassifies a shallow IPA as macOS. That fix decides which layout these rules see, whereas this request adds placement findings on top of the layout. #3353 (open; PR #3504 open) fixes launchd-plist domain labeling in the same projection and does not address code placement. PR #922 (merged) introduced the macOS bundle anatomy that this request builds on.
  • Searches of issues and pull requests for bundle layout, placement, and anomaly terms found no request for this outcome. Main at d52a488 does not change the anatomy or projection files.
Originally created by @coygeek on GitHub (Oct 16, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4312 ### Before submitting - [X] I searched the open and closed issues and pull requests for a related proposal. - [X] I understand the [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope) must be reviewed before integration; open questions are welcome here. - [X] This request does not include credentials, private samples, or sensitive target data. ### Area Evidence, artifacts, or reconstruction ### Current limitation Have `project_apple_application_graph` report placement findings when a bundle holds Mach-O code where Apple's "Placing content in a bundle" rules say code does not belong: Mach-O images under resource directories, standalone dynamic libraries in iOS, watchOS, or tvOS bundles, frameworks inside iOS or tvOS app extensions, non-symlink content at a macOS framework root, and grouping directories inside code locations. Each finding cites the Apple rule, the exact paths, and the facts it rests on. The check stays static: it never signs, verifies, or launches anything. An analyst triaging an IPA or a macOS `.app` wants to know whether code sits where the platform expects it. Misplaced code can point to a hand-assembled, repackaged, or tampered bundle, and Apple warns that it causes code-signing and distribution problems that "aren't always immediately obvious". REA lists every component but never says that a placement contradicts Apple's layout, so the analyst compares each path with Apple's table by hand. The graph assigns roles by path convention ([`appleBundleAnatomy.ts` L244-L267](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/domain/apple/appleBundleAnatomy.ts#L244-L267)). It derives the platform from layout alone: `macos-deep` becomes `macos`, and a shallow root with an `Info.plist` becomes `ios` ([L367-L379](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/domain/apple/appleBundleAnatomy.ts#L367-L379)). Neither the bundle schema ([L20-L43](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/domain/apple/appleBundleAnatomy.ts#L20-L43)) nor the result schema ([`appleApplication.ts` L44-L96](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/domain/apple/appleApplication.ts#L44-L96)) has a findings, warnings, or anomaly field. The fixed limitations ([L397-L454](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/domain/apple/appleApplication.ts#L397-L454)) say nothing about placement. Observed with REA 6.5.0 (`npx -y rea-agents@6.5.0`) on macOS 27.0.1 (26A434) arm64 with Xcode 27.0 (27A266a), using `inspect-artifact` and then `project-apple-application-graph` on two self-built fixtures: ```sh # macOS fixture: ./fixture/Fixture.app mkdir -p Fixture.app/Contents/{MacOS,Resources,PlugIns/Group.v2/Inner.bundle/Contents/MacOS} clang -o Fixture.app/Contents/MacOS/Fixture main.c clang -o Fixture.app/Contents/Resources/payload.dat main.c # Mach-O, no code-like extension clang -dynamiclib -o Fixture.app/Contents/Resources/libextra.dylib lib.c printf '#!/bin/sh\n' > Fixture.app/Contents/Resources/run.sh # script = resource clang -bundle -o Fixture.app/Contents/PlugIns/Group.v2/Inner.bundle/Contents/MacOS/Inner lib.c # plus Contents/Frameworks/Demo.framework in the standard Versions/A + symlink layout, # with one extra regular file Demo.framework/libstray.dylib (Mach-O) at its root, # and Info.plist files at the documented locations # tvOS-shaped IPA: Payload/Shallow.app built with -target arm64-apple-tvos17.0 # Shallow.app/libloose.dylib and Shallow.app/PlugIns/Ext.appex/Frameworks/Inner.framework/Inner ``` - For the macOS fixture, the release build reports `platforms: ["macos"]` and lists `Contents/Resources/payload.dat`, `Contents/Resources/libextra.dylib`, and `Contents/Frameworks/Demo.framework/libstray.dylib` under `components.executables` with format `mach-o`. It ignores `run.sh`, which is correct. It reports `Inner.bundle` with role `bundle` rather than `plug-in` because its parent is `Group.v2`. Nothing in the result marks any of these placements. - For the IPA, whose main executable's `LC_BUILD_VERSION` platform is TVOS according to `vtool -show-build`, the release build reports `platforms: ["ios"]`. It lists `libloose.dylib` only under `native_libraries` and reports `Inner.framework` as a `framework` whose parent is `Ext.appex`. Again, no finding is reported. ### Use cases _No response_ ### Desired outcome and success criteria `project_apple_application_graph` adds a placement-findings section to its result. Each finding carries a stable rule identifier, the bundle path, the offending path or paths, the facts the rule used (Mach-O format from magic, Mach-O file type, the platform and how it was established, and whether the entry is a symlink), and a short citation of the Apple rule. A finding reports a mismatch with Apple's documented layout. It is not a verdict that the bundle is malicious or will fail. Rules, each evaluated per bundle: 1. Code in a resource location: a Mach-O image, or a nested bundle that contains one, under macOS `Contents/Resources/` or a macOS framework's `Versions/<version>/Resources/`. Report one finding for each outermost misplaced item. Scripts and other non-Mach-O files never match. 2. Standalone dynamic library: a Mach-O image whose header file type is `MH_DYLIB` (every slice of a FAT file) and that lies outside every `.framework` bundle, in a bundle whose platform is established as iOS, watchOS, or tvOS. Swift system libraries (`libswift*.dylib`, the convention REA already uses in [`nativeConvention.ts` L36-L40](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/domain/nativeConvention.ts#L36-L40)) are exempt. The filename extension is never the basis. 3. Framework in a nested bundle: a `.framework` inside an app extension (`.appex`) whose platform is established as iOS or tvOS. watchOS is exempt, because Apple documents a `Frameworks/` directory inside the WatchKit extension. 4. macOS framework root: in a `versioned-framework` layout, any root entry other than the `Versions` directory and symlinks, or any entry in `Versions` other than real version directories and a `Current` symlink. 5. Grouping directory in a code location: a directory directly inside a code location (for example `Contents/PlugIns/`, `Contents/Frameworks/`, `Contents/XPCServices/`, or iOS `PlugIns/`) that has no bundle anatomy of its own but contains code. If the directory name contains a dot, the finding also cites the dotted-name rule. Platform handling stays fail-closed. The macOS rules (1 and 4) apply only to observed `macos-deep` or `versioned-framework` layouts. Mac Catalyst is covered too, because Apple's table treats Mac Catalyst as macOS. Rules 2 and 3 apply only when the bundle's platform is established from target content, such as the build-platform load command of its main executable. A shallow layout alone establishes only an iOS-family layout, so iOS, tvOS, watchOS, and visionOS cannot be told apart from it. When the platform is unknown, or is a platform the rule does not name (visionOS for rule 2, watchOS and visionOS for rule 3), the result records the rule as not evaluated for that bundle, with the reason, and emits no finding. Partial inventory coverage, and entries whose format is `unknown` (for example a truncated FAT header), make the affected rules partial, so an empty findings list is never presented as a clean result. **Acceptance criteria** - On the macOS fixture above, the result contains rule-1 findings for `Contents/Resources/payload.dat` and `Contents/Resources/libextra.dylib` and none for `Contents/Resources/run.sh`. - Renaming `payload.dat` to `payload.txt` does not change its rule-1 finding, and an executable shell script renamed `helper.dylib` under `Contents/Resources/` produces no finding. - A `.bundle` directory under `Contents/Resources/` that holds `Contents/MacOS/<Mach-O>` yields exactly one rule-1 finding, which names the nested bundle and lists its Mach-O path. - `Contents/Frameworks/Demo.framework/libstray.dylib` produces a rule-4 finding. The standard root symlinks `Demo`, `Resources`, and `Versions/Current` produce none. - `Contents/PlugIns/Group.v2/Inner.bundle` produces a rule-5 finding on `Contents/PlugIns/Group.v2` that cites both the flat-list rule and the dotted-name rule. An undotted grouping directory, `Contents/PlugIns/Waffles/Belgian.plugin`, produces a rule-5 finding that cites only the flat-list rule. - On the tvOS-built IPA fixture, `libloose.dylib` produces a rule-2 finding and `PlugIns/Ext.appex/Frameworks/Inner.framework` produces a rule-3 finding, and each finding records the platform as tvOS together with its basis. A `Frameworks/libswiftCore.dylib` built the same way produces no rule-2 finding. - The same IPA rebuilt with `-target arm64-apple-xros2.0` (visionOS) produces no rule-2 or rule-3 finding, and the result records both rules as not evaluated for that bundle, with the reason. - An IPA whose shallow app has an `Info.plist` and the loose `libloose.dylib` but no main executable at its root produces no rule-2 or rule-3 findings and records both rules as not evaluated because the platform is unknown. - `/System/Applications/Stickies.app` produces no rule-1, rule-4, or rule-5 findings. - Every finding names the Apple page it relies on, and the projection still never executes, signs, or verifies target code. ### Expected interaction with targets Read existing files or captured data ### Target and scope details (optional) **Affected area** - `project_apple_application_graph` (MCP tool and `project-apple-application-graph` CLI): result schema, Apple bundle anatomy projection, and the related documentation in `docs/apple-application-analysis.md`. **Non-goals** - Code-signature verification, sealed-resource checks, and nested-code signature validation. - Mapping launchd, XPC, privileged-helper, login-item, or system-extension relationships as graph edges. - Privacy-manifest parsing or validation. - Resolving `@rpath` and other load paths, which `trace_dylib_resolution` already covers. - Judging whether a placement is malicious, or predicting App Store or notarization outcomes. - Flagging every Mach-O image that sits outside the table's code locations. That broader check is discussed under Alternatives considered. ### Verification available so far I can suggest a sample or manual check ### Verification details (optional) _No response_ ### Alternatives considered - A new standalone tool. This would duplicate the bundle-anatomy logic and force the analyst to join two results. - Fold the rules into `trace_dylib_resolution`. That tool models dyld loading, but resource placement, framework-root layout, and grouping directories are not dyld concerns. - Flag any Mach-O outside the table's code locations. This was rejected for this issue because Apple's table omits locations documented elsewhere (for example the ExtensionKit `Extensions/` folder), and on iOS-family layouts the bundle root holds both the main executable and resources. Absence from the table is therefore not a stated rule, and the check would produce noisy findings. ### Possible direction _No response_ ### References - Apple, Placing content in a bundle (https://developer.apple.com/documentation/bundleresources/placing-content-in-a-bundle): - "In this context, executable code means a Mach-O image. It doesn't include things like shell scripts, Python scripts, and AppleScripts ... you treat it as a resource." The same page says "Resources are everything that's not code" and "The macOS platform covers both Mac and Mac Catalyst apps." - The page's table places resources at macOS `Contents/Resources/`, at a macOS framework's `Versions/A/Resources/`, and at `/` for iOS, watchOS, tvOS, and visionOS. It places frameworks and dynamic libraries at `Contents/Frameworks/` and `Versions/A/Frameworks/` on macOS and at `Frameworks/` on iOS, tvOS, and visionOS, and it refers watchOS to a separate section. - "iOS, watchOS, and tvOS support third-party frameworks but don't support third-party standalone dynamic libraries, which are those outside a framework bundle, typically with the `.dylib` filename extension. The only exception to this rule is the Swift system libraries provided by Xcode." visionOS is not named in this sentence. - "iOS and tvOS support frameworks and Swift system libraries at the topmost app level; a nested bundle, like an app extension, can't include a framework." For watchOS, Apple says to "Place watchOS frameworks in the WatchKit extension's `Frameworks` directory". - "The framework's root must contain only the `Versions` directory and symlinks." "Similarly, the `Versions` directory must contain only version directories — ideally just one, called `A` — and a symlink called `Current` that targets one version directory." - "Each code location must contain a flat list of code content." "The code-signing machinery assumes that any directory with a name that contains a dot is a bundle, and then fails when signing that directory because it's not a well-formed bundle." - The required evidence already exists: inventory formats come from Mach-O magic, thin or FAT ([`ArtifactGraphConstruction.ts` L532-L588](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/artifacts/inventory/ArtifactGraphConstruction.ts#L532-L588)), symlinks are reported by path, and `trace_dylib_resolution` already reads build-platform load commands in TypeScript ([`MachoLoadCommandReader.ts` L37-L41](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/artifacts/apple/MachoLoadCommandReader.ts#L37-L41), [L385-L399](https://github.com/morluto/rea/blob/3b79af28e80785afce9f5998d8f03289402a1847/src/artifacts/apple/MachoLoadCommandReader.ts#L385-L399)). - Related: #3359 (open; PR #3505 open) reports that a regular `Contents` resource misclassifies a shallow IPA as macOS. That fix decides which layout these rules see, whereas this request adds placement findings on top of the layout. #3353 (open; PR #3504 open) fixes launchd-plist domain labeling in the same projection and does not address code placement. PR #922 (merged) introduced the macOS bundle anatomy that this request builds on. - Searches of issues and pull requests for bundle layout, placement, and anomaly terms found no request for this outcome. Main at `d52a488` does not change the anatomy or projection files.
Author
Owner

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

Useful capability — misplaced code is a strong signal of hand-assembled or repackaged bundles, and citing the exact Apple rule plus paths makes it actionable. Some suggestions: (1) tier the findings by severity, since some violations (e.g. standalone dylib in an iOS bundle) will actually break code-signing/distribution while others (grouping dirs in code locations) are mostly unconventional; a rule + impact field would let analysts triage quickly; (2) be explicit about symlink handling — a symlinked framework inside a framework root is legal on macOS, so only non-symlink content should be flagged; (3) worth noting the platform-specific rule set (iOS/watchOS/tvOS vs macOS) per slice, since the same path pattern can be a violation on one platform and fine on another.

<!-- gh-comment-id:6207084906 --> @XinwangTao commented on GitHub (Oct 16, 2026): Useful capability — misplaced code is a strong signal of hand-assembled or repackaged bundles, and citing the exact Apple rule plus paths makes it actionable. Some suggestions: (1) tier the findings by severity, since some violations (e.g. standalone dylib in an iOS bundle) will actually break code-signing/distribution while others (grouping dirs in code locations) are mostly unconventional; a `rule` + `impact` field would let analysts triage quickly; (2) be explicit about symlink handling — a symlinked framework inside a framework root is legal on macOS, so only non-symlink content should be flagged; (3) worth noting the platform-specific rule set (iOS/watchOS/tvOS vs macOS) per slice, since the same path pattern can be a violation on one platform and fine on another.
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#1716
No description provided.