mirror of
https://github.com/morluto/rea.git
synced 2026-11-05 06:45:22 +00:00
[PR #1400] [MERGED] fix(electron): support packaged app.asar pages and rewritten unpacked companions #2857
Closed
opened 2026-10-17 21:11:05 +00:00 by bsakaguchi
·
0 comments
No Branch/Tag specified
main
codex/procedure-reference-stacked
release-please--branches--main--components--rea-agents
release-please--branches--main--components--rea-agents--release-notes
codex/kuna-independent-retry
codex/byte-search-overlay-coverage
codex/open-failure-target-receipt
codex/kuna-xref-evidence
codex/ghidra-ambiguous-procedure-recovery
codex/function-source-bundle
codex/trace-function-integration-prototype
codex/snapshot-source-closure
codex/recorded-evidence-array-pages
codex/evidence-recovery-redesign
codex/trace-feature-address-scope
codex/call-discovery-scope
codex/ghidra-literal-candidate-evidence
codex/decompile-directory-independent-retry
codex/retry-provenance-base
codex/value-flow-capability-experiment
codex/ghidra-containing-instruction
cursor/readme-discord-button-ef9f
dependabot/github_actions/actions/setup-node-7.1.0
dependabot/github_actions/actions/upload-artifact-7.0.2
dependabot/npm_and_yarn/npm-minor-and-patch-d8d97ce6df
codex/kuna-1989
fix/8559-native-ui-fixture-ownership
fix/8555-go-verifier-mcp-ownership
codex/provider-capability-recovery
fix/8642-rizin-target-stdin
codex/ghidra-memory-effect-scope
codex/ghidra-annotation-entry-selector
codex/ghidra-readonly-recovery
codex/ghidra-regex-verifier-recovery
codex/evidence-discovery-view-guidance
fix/8545-bulk-append-overflow
fix/8428-navigation-refusal-alternatives
codex/address-context-recovery
codex/matching-member-limitations
codex/unknown-scope-contract
codex/evidence-view-guidance
feat/8373-native-trace-views
codex/ghidra-snapshot-verifier-binding
codex/elf-export-visibility
codex/evidence-view-recovery
codex/native-reference-cli-help
codex/provider-candidate-observation-scope
codex/kuna-session-verification
codex/ghidra-switch-lifetime-guidance
codex/pseudocode-paging-discovery
codex/clarify-evidence-view-support
codex/kuna-xrefs-selector-recovery
codex/context-capacity-recovery
codex/evidence-closure-large-links
codex/same-function-evidence-identity
codex/ghidra-verifier-inspected-jdk
codex/audit-guided-workflows
codex/crash-prompt-retained-dossiers
codex/analysis-view-error-recovery
codex/kuna-verifier-target-selection
codex/ghidra-selected-project-call-coverage
codex/docs-native-analysis-scope
codex/ghidra-java-socket-boundary
codex/ghidra-retained-snapshot-verifier
codex/ghidra-search-inventory-facts
fix/8284-zero-argument-parameter-bindings
fix/8198-ui-action-handler-offset
fix/8257-elf-entry-label-identity
fix/8304-deferred-output-schema-projection
fix/8277-call-path-computed-target-uncertainty
fix/pr-8089-conflicts
fix/ci-static-duplicate-export
dependabot/npm_and_yarn/lint-staged-17.6.0
dependabot/github_actions/actions/download-artifact-8.0.2
dependabot/npm_and_yarn/write-file-atomic-8.0.0
dependabot/npm_and_yarn/canonicalize-5.1.0
dependabot/github_actions/actions/cache/restore-6.1.0
dependabot/npm_and_yarn/toon-format/toon-4.4.0
dependabot/github_actions/actions/deploy-pages-5.0.1
codex/review-fixes-pr-2403
codex/review-fixes-pr-2400
codex/process-terminal-width
codex/test-brittleness-cleanup
verify/7167-browser-connect-macos
fix/7167-browser-connect
feat/native-matching-allowance-setting
feat/browser-scenario-dry-run
test/managed-caller-parameters-20261024
codex/parser-fortythird-boundaries
fix/6926-pinvoke-platform-decorations-20261023
fix/6889-har-body-encoding-20261023
fix/6888-sqlite-schema-budget-20261023
fix/dependency-security-gates-6708
cursor/evidence-overwrite-rebase-b4ac
feat/4057-verify-native-exports
fix/windows-acl-observer-overhead-20261022
cursor/erlang-beam-restack-4476
cursor/pe-certificate-review-bf32
fix/6116-javascript-application-fs-errors
fix/6061-unmapped-runtime-script-unknown
feat/browser-scenario-summary
fix/pe-certificates
codex/verify-3407
cursor/rebase-5699
cursor/rebase-5352
cursor/rebase-5600
cursor/fix-cli-schema-omission-10a8
codex/audit-hopper-shutdown-reasons-20261021
fix/demangle-swift-omitted-record
fix/nib-boolean-value-types
cursor/cancellation-partial-observation-a5ac
fix/ib-object-limit-reasons
fix/electron-fuse-limit-advice
fix/kuna-doctor-dangling-cache
fix/fixed-budget-refusal-advice
fix/js-ipc-listener-dedup
fix/js-return-member-provenance
fix/dmg-integrity-retry-advice
fix/ida-doctor-readiness
fix/kuna-version-probe-output-drain
fix/legacy-swift-runtime-name-matching
fix/dylib-lazy-load-commands
fix/browser-scenario-startup-cancel
fix/swift-nested-punycode-classification
fix/compare-unselected-scopes
fix/objc-method-budget-coverage
fix/dmg-mounted-root-observations
audit/ci-tests-20261019-round2
release/6.7.0
fix/wabt-cleanup-retry-resolution
fix/electron-fuse-elf-pe-architecture
fix/native-plist-descriptor-ownership
fix/kuna-caller-cleanup-ownership
experiment/atomic-codemode-20261016
review/first-contributor-3776
fix/call-resolution-full-read-cycles
fix/member-mutation-selection-repeat
experiment/atomic-re-tools-20261015
perf/member-mutation-lazy-origins
perf/static-network-mutation-index
fix/hopper-startup-lifecycle
audit/3050-windows-proof-20261015
feat/windows-window-capture-2183
audit/3049-windows-proof-20261015
audit/3735-macos-fixtures-20261015
fix/batch-decompile-null-pseudocode
fix/kuna-inventory-honors-jobs
experiment/browser-codemode-tool-design-20261015
fix/hopper-clean-runtime-argv
codex/review-2049-27f1b367
review-fixes/pr-2787-routing
fix/3360-scoped-this-emitters
fix/3367-replaced-global-effects
fix/3838-compact-any-value-items
test/hopper-download-probe-20261015
codex/windows-runtime-creation-red-green-20261015
codex/windows-readonly-root-red-green-20261015
codex/windows-root-share-red-green-20261015
codex/exp-1685-win-mcp-startup
codex/bug-sweep-20261015
investigate/2190-windows-package-phases
investigate/3543-macos-cli-deadline
perf/3281-reverse-tools-feedback-quality
fix/3406-hopper-doctor-fixture
fix/3341-wrapper-require-test-context
fix/3301-owned-uninstall-fixtures
fix/3164-compiler-input-ownership
fix/pcap-cleanup-stdout-newline-20261014
perf/interface-builder-summary
codex/review-fixes-pr-1977
fix/ghidra-effective-jvm-platform
fix/docs-turkish-rust-link-20261013
fix/main-maintenance-ci-20261010
fix/recover-binary-session-process-effects
codex/review-fixes-pr-2457
codex/ci-required-cancellation-gate
fix/main-format-baseline-20261013
fix/setup-preserve-entry-fields
cursor/restore-main-checks-1ffc
fix/ghidra-bridge-hashmap-import
codex/shared-ci-jadx-json-default-20261013
codex/shared-ci-ghidra-test-groups-20261013
codex/shared-ci-java-fixture-format-20261013
codex/fix-intrinsic-invocation-boundaries
test/release-preflight-reusable-jobs
test/js-parameter-provenance-expectation
fix/linux-hopper-verification-current
test/2419-ghidra-elf-probe-size
followup/pr-1544-native-ida
codex/fold-pr-2230-contribution
docs/readme-responsible-use
fix/issue-2064
fix/issue-2050
fix/issue-2053
fix/issue-1968
fix/issue-1945
experiment/codemode-bridge-20261011
fix/tool-effects-negative-wording-1904-20261012
fix/1842-electron-interop-provenance
feat/recover-javascript-multi-input
refactor/website-i18n-prep
fix/nativeaot-pe-virtual-extent
fix/browser-verifier-ci-hang
fix/pe-resources-input-selection
docs/beginner-friendly-guides
docs/beginner-setup-guide
fix/javascript-analysis-worker-1563
fix/1649-ghidra-duplicate-names
fix/javascript-export-keys-integration-1369
test/maintenance-boundary-contracts-20261011
review/javascript-export-keys-1369
review/process-live-progress-1483
test/javascript-1495-growth-ratio
fix/ci-escape-timing
docs/normalized-terminal-geometry-1450
release/6.3.0
archive/release-6.3.0-pr1381
release/6.2.0
fix/electron-preload-dynamic-override
fix/javascript-self-referential-bundler-edges
release/6.1.0
cursor/grok-client-cherry-pick-0b56
feat/signature-posture
feat/dyld-shared-cache
feat/artifact-integrity-policy
feat/pkg-inventory
release/6.0.0
chore/sync-release-5.0.0
release/5.0.0
cursor/cloud-agent-node-787e
fix/javascript-xhr-open-endpoints
review/pr-711-realpath-fallback-wording
cleanup/replay-confinement
codex/test-suite-performance
codex/issue-foundations
codex/address-open-issues-2026-07-20
agent/javascript-vite-rollup-esbuild-adapters
agent/process-cleanup
agent/triage-integration
agent/unknown-commands-registry
feat/mcp-identity-metadata
morlvps/issue_cleanup
codex/installer-redesign
morl/roadmap-investigation-core
morl/roadmap-investigation-docs
release-please--branches--main--components--rea
rea-agents-6.8.0
rea-agents-6.7.0
rea-agents-6.6.0
experiment/atomic-codemode-wait-runtime-20261016
rea-agents-6.5.0
rea-agents-6.4.0
rea-agents-6.3.0
rea-agents-6.2.0
rea-agents-6.1.0
rea-agents-6.0.0
rea-agents-5.0.0
rea-agents-4.1.0
rea-agents-4.0.1
rea-agents-4.0.0
rea-agents-3.2.1
rea-agents-3.2.0
rea-agents-3.1.0
rea-agents-3.0.0
rea-agents-2.7.0
rea-agents-2.6.0
rea-agents-2.5.1
rea-agents-2.5.0
rea-agents-2.4.0
rea-agents-2.3.0
rea-agents-2.2.0
rea-agents-2.1.0
rea-agents-2.0.0
rea-agents-1.7.0
rea-agents-1.6.0
rea-agents-1.5.0
rea-agents-1.4.0
rea-agents-1.3.0
rea-agents-1.2.0
rea-agents-1.1.0
rea-agents-1.0.0
rea-agents-0.5.0
rea-agents-0.4.0
rea-agents-0.3.0
rea-0.2.1
rea-0.2.0
Labels
Clear labels
area: bridge
area: bridge
area: build
area: build
area: build
area: cli
area: domain
area: evidence
area: mcp
area: native
area: providers
area: runtime
area: server
area: setup
area: tests
bug
design
documentation
enhancement
enhancement
enhancement
experiment
help wanted
i18n
invalid
P0: critical
P1: high
P2: medium
P2: medium
P2: medium
P3: low
performance
provider-request
pull-request
Mirrored from GitHub Pull Request
question
roadmap
triage
No labels
area: bridge
area: bridge
area: build
area: build
area: build
area: cli
area: domain
area: evidence
area: mcp
area: native
area: providers
area: runtime
area: server
area: setup
area: tests
bug
design
documentation
enhancement
enhancement
enhancement
experiment
help wanted
i18n
invalid
P0: critical
P1: high
P2: medium
P2: medium
P2: medium
P3: low
performance
provider-request
pull-request
question
roadmap
triage
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
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#2857
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/morluto/rea/pull/1400
Author: @suninrain086
Created: 10/10/2026
Status: ✅ Merged
Merged: 10/10/2026
Merged by: @morluto
Base:
main← Head:fix/electron-asar-signed-unpacked📝 Commits (4)
b07161efix(electron): resolve pages served from inside app.asarc08130afix(artifacts): extract and explain rewritten ASAR unpacked companionsf873177fix(electron): bound ASAR headers before allocation6fea8fbMerge remote-tracking branch 'origin/main' into HEAD📊 Changes
17 files changed (+480 additions, -41 deletions)
View changed files
📝
docs/electron-observation.md(+7 -1)📝
docs/mcp-contracts.md(+12 -0)📝
src/application/javascript/JavaScriptArtifactReconstructionInput.ts(+2 -1)📝
src/artifacts/ArtifactProvider.ts(+1 -0)📝
src/artifacts/extraction/ArtifactExtraction.ts(+32 -0)📝
src/browser/ElectronFileScope.ts(+143 -8)📝
src/cli/artifactCommands.ts(+11 -2)📝
src/contracts/artifactToolContracts.ts(+10 -6)📝
src/domain/analysisErrorPresentation.ts(+25 -9)📝
src/domain/artifactGraph.ts(+1 -0)➕
src/domain/artifactIntegrityPolicy.ts(+16 -0)📝
src/domain/javascript/javascriptApplicationAnalysis.ts(+2 -1)📝
tests/boundary/browser/cdpElectronProvider.test.ts(+47 -1)📝
tests/boundary/filesystem/electronFileScope.test.ts(+64 -1)📝
tests/boundary/mcp/artifactMcp.test.ts(+9 -6)➕
tests/boundary/mcp/asarUnpackedExtractionMcp.test.ts(+95 -0)📝
tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts(+3 -5)📄 Description
Summary
Using REA on a shipped macOS Electron application (Neat Reader 9.0.10, Electron 13.6.9) exposed two gaps in the packaged-app workflow:
file:///…/app.asar/…URLs.authorizedElectronFilestats the URL path on the host filesystem, which cannot resolve paths inside an archive. Solist_electron_targetsreportedtargets: []withexcluded.unsupported_url: 1, andinspect_electron_pagecould not select the page at all..asar.unpackedcompanion blocked extraction and gave the wrong advice. The app shipsnode_modules/font-list/libs/darwin/fontlistas an unpacked Mach-O that was code-signed after the ASAR header was written, so its declared SHA-256 no longer matches.7915ee51(feat(javascript): record Electron integrity mismatches) already letsanalyze_javascript_applicationcontinue past this.extract_artifactstill had nointegrity_policy, though, andinspect_artifact/extract_artifactstill said "Artifact is invalid or has changed. Get a fresh copy and try again." A fresh copy of a signed app has the same mismatch. Separately, extracting an archive whose unpacked companion file is missing was reported as aformatfailure ("not an extractable regular child file").No issue is linked: I hit both problems while reverse-engineering a real application and am reporting them here with the fix.
Problem and expected behavior
Packaged pages
file:///Applications/App.app/Contents/Resources/app.asar/build-app/index.html?x=0#/library.unsupported_url, and so were every script, frame, and resource loaded from the archive..asarpath component that is a regular file is the archive, and the remainder must name a regular file in its header (packed or unpacked). The reported path is the canonical archive path joined with that member.Rewritten unpacked companions
createPackageWithOptions(src, "app.asar", { unpack: "**/*.node" }), then rewrite the unpacked.nodefile (as macOS signing or distro stripping does) and runextract_artifact.record-and-continueexactly as forinspect_artifactandanalyze_javascript_application.unavailable, with its logical path.Change and scope
Two commits:
fix(electron): resolve pages served from inside app.asarsrc/browser/ElectronFileScope.ts: if the URL path is not a regular host file, walk its components to the first.asarcomponent that is a regular file. Then look the remainder up in the archive header through@electron/asar'sgetRawHeader.linkentries, missing members, and empty/./..segments are rejected.dev,ino,size,mtimeMs), with at most 8 entries, because one inspection authorizes every frame, script, and resource URL.list_electron_targets,inspect_electron_pageframes/scripts/resources/DOM, Electron workers, V8 Inspector runtime locations) goes through the same function, so all of them pick this up without further changes.fix(artifacts): extract and explain rewritten ASAR unpacked companionsextract_artifactacceptsintegrity_policy(MCP input andrea extract-artifact --integrity-policy). Withrecord-and-continueit writes the observed bytes. It returns the extracted files' canonicalintegrity_contradictionsrecords (the same schema the JavaScript application result uses), plus one summary limitation.analysisErrorPresentation: this generalizes the JavaScript-only message added in7915ee51to every operation that acceptsintegrity_policy(inventory_artifact/inspect_artifact,extract_artifact,analyze_javascript_application), naming the operation to rerun.analyze_javascript_applicationis unchanged.artifact_id: null,hash_status: "unavailable") now fails asunavailablewithartifactDetails(logical_path,unpacked: true) instead offormat. The message tells the caller to keep the.unpackeddirectory beside the archive.src/domain/artifactIntegrityPolicy.ts: one sharedintegrity_policyschema now replaces the three duplicated inline enums, and the new extraction input uses it too.Intentionally not included:
AsarArtifactReaderdocuments thatunpackedis not an integrity exemption, and existing tests rely on the fail-closed default. The caller still choosesrecord-and-continue.analyze_javascript_applicationoutput is not addressed. For this app it was about 830 MB of JSON; that deserves its own issue.Contract and boundary impact
ElectronFileScope(URL authorization, before any Electron observation);ArtifactExtraction(inventory selection and result);analysisErrorPresentation(error projection).extract_artifactgains the optional inputintegrity_policy(defaultfail) and the result fieldintegrity_contradictions(an empty array when there is no contradiction).rea extract-artifactgains--integrity-policy. Theextract_artifactdescription is updated. Existing calls are unchanged.file://URLs inside regular.asarfiles on all hosts. Paths are built with the hostpathmodule, andfileURLToPathstill owns URL→path conversion.integrity_contradictionsschema (trust: "observed-untrusted") and are scoped to the extracted occurrences.file_pathvalues for packaged pages are<realpath(archive)>/<member>. They identify the member and are never opened as host files..asarfile. It still rejects remote hosts, credentials, encoded separators, archive directories and links, and unknown members. Extraction containment and cleanup are unchanged. A failed extraction still leaves no output root (covered by the existing completeness test).npm run docs:checkpasses against the changed contracts.Evidence and regression coverage
Tests added or updated:
tests/boundary/filesystem/electronFileScope.test.ts: packed, nested, query/hash-bearing, and unpacked ASAR members resolve. Archive directories, missing members, and a non-ASAR file used as a parent are rejected.tests/boundary/browser/cdpElectronProvider.test.ts:listTargetsandinspectPageagainst a fake CDP endpoint whose page and script live inside a realapp.asar.tests/boundary/mcp/asarUnpackedExtractionMcp.test.ts(MCP, reusescreateStrippedAsarAddon):extract_artifact.record-and-continueextracts the observed bytes and returnsintegrity_contradictionsplus the summary limitation.unavailablewith the logical path.tests/boundary/mcp/artifactMcp.test.ts: the embedded/unpackedinspect_artifactintegrity messages are updated.tests/boundary/providers/native/artifactProvider.extractionCompleteness.test.ts: the active-member refusal is now asserted asunavailablewithlogical_path/unpackedinstead offormat. Refusal and no output root are still asserted. The directmaterializeArtifactInventorycall passesintegrityPolicy: "fail".Base reproduction:
src/reverted toorigin/main, both new extraction MCP tests fail.ElectronFileScope.tsreverted to the base, the new ASAR file-scope test fails.list-electron-targetsreturned"targets": [],"excluded": {"unsupported_url": 1, "non_page": 0}.User-visible CLI/MCP output (paths shortened):
Remaining proof gaps:
Debugger.scriptParsedevents that all were Node/Electron internals or anonymous scripts. Everyapp.asarscript (11) was included.data:images and 1https:avatar.For evidence-bearing changes:
Validation performed
npm run check:changed— typecheck and lint passed; 98 test files / 973 tests passed (6 skipped).npm run docs:check— 6/6 tasks passed.npx vitest runover the touched boundary suites (tests/boundary/mcp/{asarUnpackedExtractionMcp,artifactMcp,electronMcp}.test.ts,tests/boundary/filesystem/electronFileScope.test.ts,tests/boundary/browser/cdpElectronProvider.test.ts,tests/boundary/providers/native) — all passed exceptnativeSignatureTargetBinding.test.ts › keeps real codesign bound to registered bytes during an ancestor directory swap, which also fails on unmodifiedorigin/mainon this host.rea extract-artifact,rea inspect-artifact, andrea analyze-javascript-applicationonapp.asar(default policy) each return the unpacked-entry message naming their own operation.rea extract-artifact --integrity-policy record-and-continueextracted 5321 files with oneobserved-untrustedcontradiction.--remote-debugging-port,rea list-electron-targets,rea inspect-electron-page, and the MCP toolslist_electron_targets/inspect_electron_pageall list and inspect theapp.asarpage, with identical results between CLI and MCP.Compatibility, safety, and release
unavailablewithlogical_path/unpackeddetails instead ofartifact_operation_faileddetails{operation, reason: "format", detail}. The error code (artifact_operation_failed) and the refusal itself are unchanged.inspect_artifact/extract_artifactchanged from the generic "get a fresh copy" text..asarfile reached through a hostlessfile://URL. It reads only the archive header and never executes or extracts archive content. Header reads are bounded by the existing@electron/asarparser and cached per file identity.Review checklist
type(scope): outcome.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.