mirror of
https://github.com/morluto/rea.git
synced 2026-11-05 06:45:22 +00:00
[GH-ISSUE #1701] [Bug] Windows native authority self-test fails on real Windows: "Delete owned object by handle failed" (Win32 5), and leaves probe directories behind #568
Open
opened 2026-10-15 18:26:15 +00:00 by bsakaguchi
·
22 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#568
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?
Originally created by @koljs on GitHub (Oct 11, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/1701
Summary
On a real Windows 11 x64 host,
rea doctorreports the Windows native authority capability as unavailable, which hard-gates the Ghidra provider off. The reported cause is the bundled addon's own load-time self-test failing to remove an object it just created:Ghidra itself is detected perfectly — 8 of the 9 provider checks pass. Only
native_authorityfails.I believe this is an addon-internal defect rather than a host constraint: every underlying operation involved succeeds when performed directly on this machine. Details and controlled experiments below.
Environment
Reproduction
Result:
No environment variable or configuration changes this. The gate is enforced in
GhidraProvider.inspectAvailability(), in the session-open path, and independentlyin
WINDOWS_P0_CAPABILITIES(GhidraProviderCapabilities.ts) — the tableBinarySessionExecution.prepareSessionExecution()consults.Expected
With a conforming Ghidra 12.1.4 + JDK 21 installation and a bundled native artifact
whose manifest, ABI, Node-API version, PE architecture, and SHA-256 all validate,
the native authority self-test should pass and the Windows Ghidra P0 lane should be
reachable.
Evidence 1 — the self-test leaks the object it fails to delete
Every run leaves a directory behind in the OS temp directory. After ~14 runs:
So object creation succeeds; only removal fails. The object is a directory,
and it is empty.
Its security descriptor is exactly what REA intends — protected, owner correct,
current user holding full rights:
FA(FILE_ALL_ACCESS) includesDELETE, so the DACL is not the problem.Evidence 2 — Win32 5 maps to "the handle used lacks DELETE access"
Controlled experiments on this host, deleting an empty directory through a handle
opened with
FILE_FLAG_BACKUP_SEMANTICS:SetFileInformationByHandle(FileDispositionInformation)DELETE | FILE_LIST_DIRECTORYerr=0, object goneFILE_READ_ATTRIBUTESonlyerr=5ACCESS_DENIED, object remainsAnd, to rule out the "not empty" explanation:
DELETEerr=145(ERROR_DIR_NOT_EMPTY) — not 5So Win32
5here is the signature of a handle withoutDELETEaccess being usedto mark the object for deletion, which matches the observed failure exactly.
Evidence 3 — everything else on the host works
Performed directly on this machine, all successful:
SetFileInformationByHandle(FileDispositionInformation)on a fileNtSetInformationFile(FileDispositionInformationEx)—DELETE(0x1)DELETE | POSIX(0x3)DELETE | POSIX | IGNORE_READONLY(0x7)NtCreateFilewith an inline protected security descriptorFILE_PERSISTENT_ACLSThe native artifact itself loads fine — package version, ABI 1, Node-API 8, PE x64,
and SHA-256 all validate. Only the
inspectself-test fails.Ruled out
(
%LOCALAPPDATA%\Temp, a directory onC:\, and a directory under the user profile).TokenRestrictedSidsgroup count is0; the process runs asthe ordinary user with a normal High-integrity token (
Administrators,Users,Authenticated Userspresent).third-party AV product is registered.
Impact
On Windows, everything requiring a deep-analysis provider is unavailable:
open_binary,binary_overview,batch_decompile,get_call_graph,xrefs,procedure_pseudo_code,analyze_function,trace_feature, and native functiondossiers. Provider-independent tooling works fine.
Secondary impact: the failed self-test leaks a directory into the OS temp directory
on every run, with no cleanup path.
Relationship to existing issues
closure pass ran no real Windows tests. That issue covered the period when
WindowsAuthority.tsreturnednotProvenunconditionally; the native addon nowexists and is wired in, so the remaining blocker is the addon's self-test.
(integrate it into release + a real-Windows verifier) — both still open.
GHIDRA_HEADLESS_JAVA_OPTIONSbreaking
analyzeHeadless.batwithThe syntax of the command is incorrect.(exit 255) — is fixed in 6.4.0.
ghidraHeadlessJavaOptions()now emitsGHIDRA_HEADLESS_JAVA_OPTIONS: ""on win32 and routes throughJDK_JAVA_OPTIONSwith
quoteWindowsBatchToken. Confirmed working here. Thanks for that one.Suggested direction
inspectself-test so the failing step reports the accessmask the creation handle was granted — or re-open the object with
DELETEbeforethe disposition call. The evidence points at the delete being attempted through a
handle that does not carry
DELETE.visible in any user's temp directory.
rea providers/rea doctordistinguish "platform notimplemented" from "platform implemented but the native self-test failed" — they
need different user actions, and the current wording reads as though correct setup
could satisfy it.
Happy to run further diagnostics on this host if useful — it is a stable Windows 11
x64 box with Ghidra 12.1.4 + JDK 21 installed and verified working outside REA.
@ranceil commented on GitHub (Oct 11, 2026):
Independent reproduction on a second Windows host, with three data points not covered above.
Environment (different from the original report)
REA: rea-agents 6.4.0 — also fails on 6.3.0 AND 5.0.0
Host: Windows 11 Pro, 10.0.26200, x64 (fixed local NTFS on C:, D:, E:)
Node: v22.22.2 (also reproduced with v22.22.0)
Ghidra: 12.1.4 PUBLIC
JDK: Eclipse Temurin 21.0.12.1+1 (64-bit, full JDK, javac present)
Same symptom: 8 of 9 provider checks pass,
native_authorityfails withDelete owned object by handle failed ... (Win32 5),available: false,and each run leaks one empty
rea-native-probe-<32hex>directory into%TEMP%(10 accumulated during this investigation).
1. The defect predates 6.3.0.
rea-agents@5.0.0reportsproviderInspections.ghidra.available: falseas well, with the same eightconforming checks. In that release the check is not yet surfaced under the
native_authorityname, but the gate behaves identically. So this is not aregression introduced in the 6.3.x line.
2. It is not antivirus-related, in both directions. This host had a
third-party endpoint product installed (kernel drivers loaded, plus a resident
client). After fully removing it and confirming its services and drivers were
gone, the self-test failed identically. Your report has no AV product registered
at all; this host reproduces it both with and without third-party AV. That
closes the AV direction from both sides.
3. It survives a full reboot. A clean restart (no lingering drivers or
hooks) changes nothing.
4. Your access-mask conclusion is confirmed, and share mode is not the
constraint. On this host, from the same session and the same directory as the
failing self-test:
@jhuang-tw commented on GitHub (Oct 11, 2026):
Additional independent Windows countercheck (not a fix claim):
c4fd9f377e567bcf15ba3fec3e0b0ed965d82b765a2adcdac49e46f14524b6d5). On this Windows x64 fixed-NTFS host, with process-local TMP/TEMP pointing into an isolated NTFS test directory,addon.call("inspect", [])passed, including private-DACL and job-control capability reporting; there were zero residualrea-native-probe-*directories.DELETE | FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | READ_CONTROLandFILE_SHARE_READ, duplicated the handle withDUPLICATE_SAME_ACCESS, then calledSetFileInformationByHandle(FileDispositionInfo, DeleteFile=TRUE)on the duplicate while the original was still open. It succeeded. The control withFILE_SHARE_DELETEincluded also succeeded. Both test objects were removed.createRuntimerequestsDELETEfor its owned directory inNtCreateFile;closeRuntimeduplicates the owned handle withDUPLICATE_SAME_ACCESSand later appliesFileDispositionInfo. Thus the original handle not requestingDELETE, or duplication inherently making this deletion impossible, is not established by the present code or this passing host. The affected-host failures in this issue remain important and independently reported; this successful control does not disprove them.A useful next discriminator on a failing host would be the actual
GrantedAccesson the creation handle and the frame duplicate at the point of failure (e.g.,NtQueryObject(ObjectBasicInformation)), along with the exact failed disposition status. Reopening the path independently withDELETEproves the security descriptor permits a new handle, but does not establish the granted mask on the retained original. That would distinguish a granted-rights problem from a host-specific directory-disposition constraint before changing the handle-sharing or POSIX unlink semantics.I have not opened a code PR for this yet: the published addon self-test and the independent duplicate-handle control both pass on my available Windows host, so a speculative security-sensitive fallback would not be responsibly verified. All temporary test objects were confined to and cleaned from the isolated checkout test directory.
@gaodanbendan commented on GitHub (Oct 11, 2026):
Third Windows host — same failure, but transient: it self-cleared with no code or config change
TL;DR. On a third Windows 11 x64 host I hit the exact failure reported here
(
native_authority→unsupported_host,Delete owned object by handle failed … (Win32 5),one leaked
rea-native-probe-<32hex>directory per run). Then, on the same machine, same%TEMP%, samerea-agents 6.4.0, same Ghidra 12.1.4 + JDK 21, with nothing changed in codeor configuration, the gate started passing — and it has now passed 30/30 times, with
zero leaked directories. Two end-to-end analyses that previously failed on identical
inputs now complete.
This does not contradict the reports above; it adds a dimension they do not cover: the
failure is not deterministic on a given host. That matters for triage, because a
deterministic-looking repro invites a code-path fix, while a transient one points at a race
or a third-party holder of the freshly created object.
Environment
rea-agents6.4.0 (isolated install)C:NTFS, fixed, 201 GBC:\Users\<user>\AppData\Local\Temp(standard, untouched all session)AMRunningMode = NormalThe window, verbatim — identical inputs, opposite outcomes
All four runs below are on the same host, same temp directory, same release.
Timestamps are local (UTC+8).
Ghidra, target
C:\Windows\System32\notepad.exe14:23 — fails
14:59 — succeeds
Elapsed 5 m 17 s, exit 0.
JavaScript application analysis — identical subject digest
This pair is the cleanest control I have: the
subjectdigest is byte-for-byte the same inboth runs, so the analysed object provably did not change.
14:26 — fails
14:57 — succeeds
Exit 0, 79.8 MB of JSON output. Same digest, failure → success.
Data point not covered by the reports above: the gate also blocks non-native providers
The Impact section says "Provider-independent tooling works fine." On this host that is not
what I measured.
analyze-javascript-applicationis not a deep-analysis provider — it ispure static parsing of a directory of
.jsfiles — and it was rejected by the same nativeself-test string, with
capability_unavailable/unsupported_provider.Two things follow:
that goes through
BinarySessionExecution.prepareSessionExecution()is affected,including JavaScript/Electron application analysis, HAR capture, and anything else
routing through the native authority.
capability_unavailable/unsupported_providerwording is misleading here. Theprovider is supported on this platform; the gate mislabels a self-test failure as an
unsupported capability. (Related to what the original report calls out in "suggested
direction 3", but the JS path is a second, non-provider surface for it.)
Note also the
partial_observationin the 14:26 failure: the subject digest was alreadycomputed and the file/directory was already read. So creation and reading succeed; only
the removal of the self-test object fails — consistent with the original report's
Evidence 1.
Current state of the same host (after the window)
rea doctor—native_authorityrow now:Direct addon call,
addon.call("inspect", []):All four capability flags
true; the probe directory it names was removed cleanly.Statistics
native_authorityok:false×Nok:true×30, 0 failuresCounts after recovery: 2 sandboxed + 2 unsandboxed + 20 consecutive + 5 under artificial
load = 30
doctorruns, no failure, no leak.I could not re-trigger it
Attempts to bring the failure back, all unsuccessful (0 failures, 0 leaks):
%TEMP%immediately before 5 runs, to put the AV/IO pathunder load — still 5/5 pass.
Facts about the transition (no causal claim)
What I know changed on the host between the last observed failure (14:26) and the first
success (14:54):
rea-native-probe-*directories that thefailing runs had accumulated in
%TEMP%.Microsoft-Windows-Windows Defender/Operational): configuration-change events (5007) at 13:42:37, ten more between13:57:19 and 13:57:34, then 14:00:01 and 14:07:54; a security-intelligence update
(2000 ×2) at 14:07:53; cloud-protection lookups (2010) at 14:09:12, then 14:50:59 and
14:51:55. Real-time protection was ON for the entire period, including the successful runs.
I am not claiming Defender caused the failure — RTP was on in both windows, which
weakens a straightforward AV explanation. I am recording the telemetry because it is the
only correlated activity I can see, and because the two obvious "code-path" explanations
(handle without
DELETE, duplicate-handle semantics) are already argued in the thread anddo not by themselves explain a state change with no code change.
The pattern that fits best, in my reading: the disposition call is racing something that
holds the freshly created object for a short interval, and on this host that interval
closed. That is a hypothesis, not a finding.
Suggested direction (additions to the three already in the report)
a bounded retry (e.g. 3 attempts, tens of ms apart) converts most of these into passes
and eliminates the whole class of "host-dependent flaky gate". This is cheap and does
not weaken the security property — the self-test only proves the capability exists, and
retrying a probe cannot make it less real.
user-visible symptom and, as the original report notes, is what made this diagnosable.
It is also a correctness bug independent of the gate: a failed check must not leave
state behind.
GrantedAccessof the creation handle and of theduplicated handle (e.g. via
NtQueryObject(ObjectBasicInformation)), plus the exactstatus of the disposition call. This is the discriminator the thread is missing; my
host's transient behaviour makes it more, not less, important.
failure — a transient failure that leaves no record is undiagnosable after the fact.
(On my host the failure is now unreproducible, so without a logged trace the evidence
is gone.)
Happy to run further diagnostics on this host. Note that it is currently in the passing
state, which may be exactly what is needed to diff against a failing host — for instance,
the same
inspectcall and the same access-mask instrumentation on both.Footnote, unrelated to this issue: in my environment
rea doctor's Java probe(
GhidraInstallation.js, the barespawnSynccall) also fails spuriously, becauseinheriting
stdinin this process environment returnsEBUSYand the child is nevercreated; a process-local preload that sets the child's
stdiotoignorefixes it. The14:23 and later runs above include that workaround, so
javashows healthy and the onlyremaining rejection is the native one. Reporting it for completeness; I do not think it is
related.
@pablodiazjorge commented on GitHub (Oct 11, 2026):
Another data point, from a host that has never been in the failing state so far, with the published npm package:
%TEMP%AMRunningMode = Normal, no third-party AVrea-agents6.4.0 from npm, installed in a project foldernative_authoritypassed in 31 of 31rea doctor --provider ghidra --jsonruns (1 earlier in the day plus 30 back to back), with zerorea-native-probe-*directories left in%TEMP%. Each run took 1.6 to 27 s.rea inspect WinHelloCPP.exe --provider ghidra --format json(the x86 PE from Ghidra's own GhidraClass exercises) completes in about 25 s: 6 segments, 388 procedures, 254 strings, with nojavaprocess or probe directory left behind.So, like jhuang-tw's countercheck and gaodanbendan's host after recovery, the shipped 6.4.0 addon passes
inspecthere, with Defender real-time protection on the whole time.#1826 notes that Windows Ghidra/JDK were not verified there. Once it lands (or from a build of that branch, if that helps), I can run the Ghidra path end to end on this host, plus
npm run verify:ghidra:windowsandverify:ghidra:windows:package, and report the results here. This host can also be the passing side of a diff with access-mask instrumentation.@pablodiazjorge commented on GitHub (Oct 11, 2026):
Follow-up on my offer above: I verified
mainat0b4ce836(with #1826) on the same host, built from source with the native addon fromnpm run build:windows-native, and installed fromnpm packinto an isolated folder:rea doctor --provider ghidra:native_authoritypassed 30/30, with norea-native-probe-*directory left.rea inspect WinHelloCPP.exein 27 s, and an MCP session (open_binary,binary_overview,close_binary) with a clean exit and nojavaprocess left.npm run verify:windows-nativepasses.The real Windows Ghidra lanes needed two verifier fixes unrelated to #1826 (#1859, PR #1863). With them, all four
verify:ghidra:windowsvariants and all fourverify:ghidra:windows:packagevariants pass on this host.@liudong-geek commented on GitHub (Oct 12, 2026):
Fourth independent host — 100% deterministic failure, plus a faithful native replication that pins the mechanism.
Environment
rea-agents@6.4.0(npm, global) — also reproduced with the isolated replay belowapplication.java.min=21, native decompiler present%LOCALAPPDATA%\Temp(NTFS, fixed) — also reproduced with TMP redirected to another volumerea doctor --json: all 9 ghidra checks pass exceptnative_authority→Delete owned object by handle failed [...\rea-native-probe-<32hex>] (Win32 5).available: false.Determinism: 70+ consecutive failures (50×
runtime_create+runtime_close, 20×inspect, plus doctor runs). Zero successes. Not a race on this host.Reproduction outside REA — the addon loaded directly
The mechanism — faithful Win32 replication
I replicated
createRuntime's exact call shape withNtCreateFile(empty directory, private protected DACLO:<user> D:P(A;OICI;FA;;;<user>)(A;OICI;FA;;;SY),FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,FILE_CREATE), thenSetFileInformationByHandle(FileDispositionInfo)on the same handle:FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETEFILE_SHARE_READ|FILE_SHARE_WRITE(noFILE_SHARE_DELETE)0(exclusive)Independent of the DACL (same result with a default inherited DACL). This is the documented rule — an object open by any handle without
FILE_SHARE_DELETEcannot be marked delete-pending — and it matches the observed failure exactly. Two follow-ups on this host:RemoveDirectoryW→ ERROR_SHARING_VIOLATION). After the addon process exits, the same external delete succeeds.runtime_closedoes not release the blocking handle — the external delete still fails afterwards, and only process exit releases it.Ruled out on this host
TokenRestrictedSids= 0), reparse points, DACL contents (FA includes DELETE), directory emptiness, external/persistent holders (leaked probe dirs are deletable once the creating process exits).tsbx.dll, hooksNtCreateFile/NtOpenFile/NtSetInformationFile) into agent-spawned processes. Ruled out as the cause: an injected Python process creates and deletes directories by handle without issue, and a directory created by an injected Node process viafs.mkdirSyncis deletable externally. No shadow handles are held.Suggested fix (concrete)
In
createRuntime, addFILE_SHARE_DELETEto theShareAccesspassed toNtCreateFilefor the owned directory. Alternatively/additionally, incloseRuntime, re-open the object by path withDELETE+ full share and close the retained original before the disposition call — but note the re-open alone is insufficient while the original (share-without-DELETE) handle is still open, per the matrix above.Two secondary asks, unchanged from the original report:
Happy to run any instrumented build on this host — notably
NtQueryObject(ObjectBasicInformation)on the creation handle and the frame duplicate at the point of failure, which would confirm the granted mask directly (I cannot extract the handle through the addon's opaque wrapper).@pablodiazjorge commented on GitHub (Oct 12, 2026):
Data point for the share-mode theory from the passing host in my earlier comment, on the same Windows build as @liudong-geek: Windows 11 Pro 26H2, build 26300.9457, non-elevated, Defender real-time on, no other security product. The test processes load only Windows and Node modules (PowerShell adds Defender's AMSI provider); nothing hooks
NtCreateFileorNtSetInformationFile.Your addon replay, unchanged.
rea-agents@6.4.0from npm,rea-windows-x64.nodeloaded directly,runtime_createthenruntime_closeinos.tmpdir(), Node 22.22.3: 50/50 succeed, no probe directories left behind.Your share-mode matrix, plus the granted mask.
NtCreateFilewith the access maskcreateRelativeuses (DELETE | FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | READ_CONTROL | SYNCHRONIZE),FILE_CREATEandFILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT; thenNtQueryObject(ObjectBasicInformation)on that handle, andSetFileInformationByHandle(FileDispositionInfo)on the same handle. 20 runs per row:FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE0x130081FILE_SHARE_READ | FILE_SHARE_WRITE0x130081FILE_SHARE_READ(whatcreateRelativepasses today,native/windows/src/filesystem.cc:168)0x1300810(exclusive)0x1300810x130081is exactly the requested mask,DELETE(0x10000) included. On a host without instrumentation, the creating handle's own share mode does not stop its own disposition; share access only constrains other opens. That is consistent with the addon passing here althoughcreateRelativeomitsFILE_SHARE_DELETE.What this suggests. The build and the share mode are the same on both hosts, so they do not explain the difference. Your host injects
tsbx.dll, which hooksNtCreateFile,NtOpenFileandNtSetInformationFile, into agent-spawned processes. If the matrix ran from one of those processes, the hook may be what turns the disposition into Win32 5.On the instrumented build. You don't need one for the granted mask: your matrix owns its handle, so
NtQueryObject(ObjectBasicInformation)right afterNtCreateFilegivesGrantedAccessdirectly, as in the table above. Two runs would settle it:GrantedAccess, from an agent-spawned process and again from a terminal you open yourself outside the sandbox.If
DELETEis missing fromGrantedAccessinside the sandbox, or both runs pass outside it, the cause is the hook and not rea.On the suggested fixes. Adding
FILE_SHARE_DELETEwould let other processes open the private runtime directory withDELETEaccess, which the runtime avoids on purpose (see the comment aboveruntime_openinfilesystem.cc). The alternative, closing the retained original and re-opening by path before the disposition, gives up the handle that keeps the directory from being replaced between creation and cleanup. Both trade a protection for a failure that does not reproduce on an uninstrumented host, so I would wait until the hook is ruled out. Your two secondary asks stand either way: the probe should not leak when the self-test fails, and #2108 now proposes telling a failed self-test apart from an unsupported host.Happy to share both scripts.
@xiaojianghoo-sys commented on GitHub (Oct 12, 2026):
<html>Another data point — and the first Windows 10 host so far (all previous reports are Windows 11).
Environment
Result: 100% deterministic on this host
5/5 consecutive
analyze-javascript-applicationruns failed identically, plus ~20 further runs across the session:Same signature as the original report and @liudong-geek's replication — object creation succeeds, only delete-by-handle fails, and empty probe directories leak (13 accumulated during my session; cleaned manually with
rmdir).Impact is wider than the Ghidra lane
On this host the same native-authority failure also hard-gates the JavaScript static-analysis provider:
The MCP path behaves the same:
initialize+tools/listsucceed (177 tools advertised), but any tool routed through the gated provider returnscapability_unavailablewith the native-authority cause. Provider-independent tooling works — verifiedinspect_pe_resourcesend-to-end via MCPtools/callagainstC:\Windows\System32\notepad.exe(full Evidence record returned).Notes against the existing ruled-out list
AV: Huorong HIPS is resident here. Combined with @ranceil's both-directions test, AV stays ruled out as the universal cause (though per-host interception cannot be excluded).
Temp location: redirecting
TMP/TEMPto a different NTFS path did not change the outcome — consistent with @liudong-geek.Mechanism: matches @liudong-geek's share-mode replication; the retained create handle appears to lack
FILE_SHARE_DELETE, so the object cannot be marked delete-pending.Cannot verify the fix locally
No Visual Studio / MSVC build tools on this host, so building the addon from main (
npm run build:windows-native) to check #1826 / #1863 is not possible here. Confirmation of which release will carry the fix would help — happy to re-verify onnpm updateonce it ships.Thanks to everyone who narrowed this down — the share-mode replication in particular made the cause obvious.
</html>rea-issue-1701-comment.md
@xiaojianghoo-sys commented on GitHub (Oct 12, 2026):
Another data point — and the first Windows 10 host so far (all previous reports are Windows 11).
Environment
rea-agents@6.4.0from npm, isolated project install (not global)C:NTFS, fixedHipsTray.exe)%LOCALAPPDATA%\Temp; also reproduced with process-localTMP/TEMPredirected to another NTFS pathResult: 100% deterministic on this host
5/5 consecutive
analyze-javascript-applicationruns failed identically, plus ~20 further runs across the session:Same signature as the original report and @liudong-geek's replication — object creation succeeds, only delete-by-handle fails, and empty probe directories leak (13 accumulated during my session; cleaned manually with
rmdir).Impact is wider than the Ghidra lane
On this host the same native-authority failure also hard-gates the JavaScript static-analysis provider:
The MCP path behaves the same:
initialize+tools/listsucceed (177 tools advertised), but any tool routed through the gated provider returnscapability_unavailablewith the native-authority cause. Provider-independent tooling works — verifiedinspect_pe_resourcesend-to-end via MCPtools/callagainstC:\Windows\System32\notepad.exe(full Evidence record returned).Notes against the existing ruled-out list
TMP/TEMPto a different NTFS path did not change the outcome — consistent with @liudong-geek.FILE_SHARE_DELETE, so the object cannot be marked delete-pending.Cannot verify the fix locally
No Visual Studio / MSVC build tools on this host, so building the addon from main (
npm run build:windows-native) to check #1826 / #1863 is not possible here. Confirmation of which release will carry the fix would help — happy to re-verify onnpm updateonce it ships.Thanks to everyone who narrowed this down — the share-mode replication in particular made the cause obvious.
@chqcjq commented on GitHub (Oct 12, 2026):
Source analysis of the failing delete (addon reads, not a fix claim)
I traced the probe lifecycle in the bundled addon source (main
7ae3c50a, matching the npm artifact SHA c4fd9f37):inspect() (process.cc:415) → createRuntime(temp, 'rea-native-probe-') (filesystem.cc:214) → createRelative(parent, name, DELETE | FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | READ_CONTROL, ...) (filesystem.cc:154) → NtCreateFile(..., FILE_SHARE_READ, FILE_CREATE, FILE_DIRECTORY_FILE, ...) (filesystem.cc:167) → identity(env, probe->directory.get(), ...) (filesystem.cc:80) → closeRuntime(*probe) (filesystem.cc:330) → DuplicateHandle(root.directory) — same access mask, includes DELETE → Frame(directory): FindFirstFileExW → empty dir → pending=false → dispose(frame.directory) (filesystem.cc:299) → SetFileInformationByHandle(handle, FileDispositionInfo, TRUE)Key observation: the handle used for deletion does carry DELETE access — createRelative requests DELETE | ... at line 165, and closeRuntime duplicates that same handle at line 352. The probe directory is empty, so ERROR_DIR_NOT_EMPTY (145) is ruled out, matching the report.
Why some hosts pass and others fail: on a Windows 11 build 22631 host with UAC disabled (EnableLUA=0) and an elevated Administrator token, the same npm artifact's self-test passes cleanly (no residual probe directories). All failing reports are on UAC-enabled hosts with non-elevated or Medium-integrity tokens. The difference may be in how the object manager grants the requested access mask at creation time under different integrity/token configurations — worth instrumenting the self-test to report the granted access mask of the probe directory handle (via GetGrantedAccess or AccessCheck) rather than the requested one, as the issue already suggests.
This confirms the failure is not in share-mode flags (the handle is deleted through SetFileInformationByHandle, not a separate open) and not in the DACL (which grants FILE_ALL_ACCESS including DELETE). The remaining variable is the granted access mask on the creation handle itself under non-elevated tokens.
@Rinkia commented on GitHub (Oct 12, 2026):
Fifth host, passing, with a source-built addon — plus one measurement that I think narrows the mechanism, because it does not reproduce @liudong-geek's matrix row 2.
Environment
mainat5190843(includes #1826), addon cross-compiled with the documented lane (Linux + MinGW-w64 g++ 12),abiVersion: 1,nodeApiVersion: 8C:NTFS fixed; default%LOCALAPPDATA%\TempResult: 30/30 pass, zero leaked probe directories
requireWindowsNativeAuthority()called 30 times in one process:First inspection reports
privateDacl: true,atomicJobAssignment: true,killOnOwnerClose: true,protocolStdin: true,jobMemoryLimit: true, NTFS,directory: true.npm run verify:windows-nativewith the boundary fixture also passes end to end (20/20 filesystem controls, 12/12 process observations).The measurement that does not line up
REA creates owned objects with
ShareAccess = FILE_SHARE_READatnative/windows/src/filesystem.cc:167— i.e. withoutFILE_SHARE_DELETE— and on this hostSetFileInformationByHandle(FileDispositionInfo)on that same retained handle succeeds, 30 times out of 30. An isolated replication agrees: an empty directory, one handle openedDELETE | GENERIC_READ | READ_CONTROLwithFILE_SHARE_READand no share-delete, deletes by handle with0, including while a second read-only opener (FILE_READ_ATTRIBUTES,FILE_SHARE_READ, also not sharing delete) is held open:So on this host the create-time share mode is not what decides the outcome, which suggests
ShareAccesswithoutFILE_SHARE_DELETEis necessary but not sufficient rather than the cause. The documented share rule constrains a new opener against existing opens; a sole handle does not block its own transition to delete-pending here. That a single handle does block it on the failing hosts is the part still unexplained, and it is consistent with a second, unobserved handle on those hosts (filter driver, HIPS, or the injectedtsbx.dllon @liudong-geek's) rather than with the share mode alone.This does not argue against adding
FILE_SHARE_DELETEincreateRuntime: it is inert on hosts like this one and would make delete-pending reachable wherever something else does hold the object. I would just expect it to be a mitigation whose success on an affected host is the actual evidence, and note it relaxes the exclusivity thatfilesystem.cc:547keeps deliberately for snapshot readers, so the call is a maintainer's.Offer
@liudong-geek asked for
NtQueryObject(ObjectBasicInformation)on the creation handle at the point of failure, and several people here (@xiaojianghoo-sys, @liudong-geek) have no MSVC to build with. I have a working cross-build lane and can produce an instrumentedrea-windows-x64.nodethat dumps the granted access mask and the kernel's handle/pointer counts for the probe object immediately before the disposition call, plus a one-command repro, so an affected host can return that measurement. Say the word and the shape you want and I will build it — I cannot reproduce the failure here, so the decisive data has to come from one of the failing hosts.🤖 Posted by Claude Code
@Rinkia commented on GitHub (Oct 12, 2026):
8160 chars
k @xiaojianghoo-sys — here is the instrumented build, as offered. It answers the
NtQueryObjectquestion directly and adds the handle/pointer counts, because my passing-host result suggests a second unobserved handle rather than the create-time share mode.It applies to
mainat5190843, compiles clean with the documented MinGW lane, and I verified the resulting addon loads and passes 10/10 on my (non-reproducing) host, so the instrumentation itself does not break the self-test.What it reports
On the failure path only, one JSON line on stderr immediately before the existing error is raised:
grantedAccessDELETE(0x00010000) — the mask you could not extract through the opaque wrapperhandleCount/pointerCounthandleCount > 1means something else holds the object and the share mode is the mechanism;handleCount == 1means a sole handle is blocking its own transition, which is not the documented rule and points elsewhere (filter driver / minifilter behaviour)deletePendingchildrenposixDispositionWin32FileDispositionInfoEx+FILE_DISPOSITION_FLAG_POSIX_SEMANTICSsucceeds where the classic call fails —0here would make that a candidate fixCaveat, please read: the POSIX probe is not read-only. Where it reports
0the object is unlinked then and there, so this build leaks no probe directory in that case. The thrown error keeps the same constraint text and Win32 code as the stock build, sorea doctoroutput is otherwise unchanged.Build it yourself (no MSVC needed)
The artifact lane refuses to run outside Linux, but a container satisfies it — this is how I built it on a Windows host with no C++ toolchain at all:
That writes
native/windows/build/rea-windows-x64.node(+manifest.json). Point your installed REA at it, or run from the source tree, then:and paste the
REA_DIAG_1701line.node -e "require('./native/windows/build/rea-windows-x64.node').call('runtime_create',[require('os').tmpdir(),'replay-'])"plusruntime_closeworks too, per @liudong-geek's replay.My build for reference: SHA-256
391273937535f6d03bb20a44b27d78629de49c86d930d2dea52a03836de4b08d, 844,998 bytes,abiVersion: 1,nodeApiVersion: 8. I would rather you build from the patch than trust a binary from a stranger, but if a prebuilt.nodeis genuinely more useful than a container, say so and I will attach one.1701-instrumented.patch
🤖 Posted by Claude Code
@WraithFallen commented on GitHub (Oct 13, 2026):
Another passing host, this time Windows 10 using the published npm artifact rather than a source build. Posting it as a contrast point for the matrix.
rea-agents@6.4.0from npm (global install, prebuiltrea-windows-x64.node)%TEMP%on the local NTFS system driverea doctor --json:ghidra-native_authorityok: true, "Verified Windows native Job Object, private DACL, and reparse-safe handle controls; local NTFS only." All nine Ghidra checks are healthy. A real target, an x64 SKSE plugin DLL, then ranrea inspectandrea searchto completion. Norea-native-probe-*directories were left in%TEMP%.Defender being off may matter for the "second unobserved handle" theory above, since a real-time scanner opening the new directory would be one candidate for it. I haven't toggled it to test that.
@chemsily commented on GitHub (Oct 13, 2026):
<html>Another failing host — and on a newer build than the reports so far (26300 vs 26100), so this is not a single-servicing-build artifact.
Environment
| -- | -- REA | rea-agents 6.4.0 (npm). Bundled addon rea-windows-x64.node, 848,252 B, SHA-256 c4fd9f377e567bcf15ba3fec3e0b0ed965d82b765a2adcdac49e46f14524b6d5; manifest.json reports abiVersion: 1, nodeApiVersion: 8 Host | Windows 11 Pro 26300 (10.0.26300), x64, medium integrity (S-1-16-8192), not elevated — the account is a member of BUILTIN\Administrators, it just is not elevated here Node | v22.22.2 Ghidra | 12.1.4 PUBLIC JDK | Microsoft OpenJDK 21.0.12.1+1 LTS (64-bit full JDK, javac present)Reproduction
rea doctor --provider ghidrafails 5/5 runs (100%, not intermittent), and each run leaves area-native-probe-*directory behind — 6 accumulated across the session.Ghidra itself is detected perfectly: 8 of 9 provider checks are
healthy(release, platform, architecture,application.properties, version 12.1.4,analyzeHeadless.bat, native decompiler matchingpe x86_64, JDK 21). Onlynative_authorityfails, and it hard-gates every provider-backed operation.Two controlled experiments: this is addon-internal, not a host constraint
Both run in the same medium-IL non-elevated process.
1. The probe object's own security descriptor is correct. Dumping the SD of a probe directory REA had just left behind:
So the private-DACL installation itself works, and the DACL is not what denies the delete — the acting process is both owner and a
FILE_ALL_ACCESSgrantee.2. Deleting that same probe object by handle succeeds when done directly. Against the exact directory REA failed to remove:
The OS permits precisely the transition the addon needs. Note this also requires
FILE_FLAG_BACKUP_SEMANTICS— opening a directory for delete/write without it returns Win32 5 on its own, which is easy to misread as the bug; it is not the bug here.Temp location is not a factor. Pointing
TMP/TEMP/TMPDIRatD:\analysis\tmpreproduces identically — only the reported path moves (D:\analysis\tmp\rea-native-probe-…). Both TEMP roots are ordinary directories (FILE_ATTRIBUTE_DIRECTORY, no reparse tag) on fixed local NTFS volumes.On the mechanism
The #2445 diagnosis matches what is observable from outside. The addon documents that it retains handles for the runtime's lifetime ("Descriptor and snapshot handles remain held until runtime cleanup"), and a retained handle that never granted
FILE_SHARE_DELETEwould block the delete-pending transition on the very object it still holds. That is consistent with both experiments above: the delete succeeds the moment no non-DELETE-sharing handle is outstanding on the object.I could not instrument the addon myself (no MinGW lane on this machine), so I cannot speak directly to the "second unobserved handle" hypothesis — though a second retained handle is exactly what the retained-lease design predicts, so the two framings may be the same defect seen from different sides.
For anyone arriving here looking for a workaround
There isn't one, and two dead ends are worth recording:
REA_WORKSPACE_ROOTdoes not help — the self-test probe path is not derived from it.native/windows/README.mdstates the loader verifies the artifact SHA-256 and that "there is no environment override for loading an arbitrary native module."So on Windows today, native binary analysis is reachable only by driving Ghidra headless directly and bypassing REA's provider layer. The engine itself is fine — verified end-to-end on this host:
</html>analyzeHeadless.batimported a PE, auto-analysis found 198 functions, andDecompInterfaceproduced C pseudocode for 5/5 sampled functions.@ranceil commented on GitHub (Oct 14, 2026):
Independent reproduction on a second host — the self-test gate is a false negative:
the MCP tool surface works while the CLI is still rejected
Reporting a dimension I don't see covered above, because it changes the practical impact.
Environment
The self-test still fails, deterministically, on this host
rea doctor --provider ghidra --jsonreportsnative_authorityasok:false/unsupported_host, with the sameDelete owned object by handle failed … (Win32 5)and the same leaked
rea-native-probe-<32hex>directory.I ran it 12 times back to back: 12 failures, 0 passes. So on this host it is not
currently exhibiting the transient behaviour described in a comment above.
But the native analysis itself works — through the MCP tool surface
rea doctor --provider ghidra --jsonnative_authorityfails (12/12)rea analyze <pe>(provider auto-selection)provider_unavailablerea analyze <pe> --provider ghidra(explicit, too)provider_unavailableopen_binarywithprovider_id: "ghidra"binary_overviewTarget: a 2004 32-bit PE application (x86). Verified twice on this host. Downstream
tools (
search_strings,xrefs,procedure_pseudo_code) also work in the same MCPsession.
Interpretation (hypothesis, not a finding)
This is consistent with
systemWindowsNativeAuthority()caching its probe resultprocess-wide (
cached ??= …, one probe per process). The long-running MCP host processevidently probed during a passing window and cached
available: true; each new CLIprocess re-probes and fails. That also fits the transient behaviour reported earlier:
the probe is unreliable, but the capability it probes for is present.
Two consequences worth acting on
The Impact section above is too pessimistic, and the current behaviour costs users
real work. A host in this state looks completely blocked —
rea doctorsaysunavailable and the CLI refuses to run — while the MCP surface can perform the full
analysis. The reasonable conclusion for a user is "native analysis on Windows doesn't
work", and they stop. I nearly did.
Suggestion: don't hard-gate a capability on a probe. A failed self-test should
degrade to a warning (and be recorded), not disable the provider for every surface.
If the probe cannot be made reliable, then at minimum the CLI and the MCP surface
should not disagree about whether the same capability exists.
Concretely, alongside the retry-with-backoff suggestion already made:
native_authorityprobe failure asdegradedrather thanunavailable, andlet each operation decide whether it actually needs native authority.
one is not invisible in the other.
REA package and a writable local NTFS temporary directory", neither of which is the
constraint here. Something like "the native self-test failed; MCP tool calls may still
work" would have saved days of investigation.
Additional data points from this host (all measured)
rea-agents5.0.0, 6.3.0 and 6.4.0 allreport
providerInspections.ghidra.available: false. In 5.0.0 the check is notsurfaced under the
native_authorityname, but the outcome is identical — not a6.3.x regression.
with kernel drivers loaded; after fully removing it and confirming services and
drivers were gone, the self-test failed identically. The original report's host has no
third-party AV registered at all.
rea-native-probe-*, I also find leftoverrea-ghidra-*directories in%TEMP%from failed Ghidra sessions (3 accumulatedduring this investigation, alongside 3 probe directories).
icacls:current user + SYSTEM full control, protected/non-inherited, no deny ACEs) and carries
no Mandatory Label (default Medium) — so neither the DACL nor the integrity label
explains the
Win32 5.CreateFileW(dir, DELETE, FILE_SHARE_READ|WRITE|DELETE, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)followed bySetFileInformationByHandle(h, FileDispositionInfoEx, DELETE|POSIX)removes the directory. Same session, same user,same directory as the failing self-test.
Happy to run further diagnostics on this host. It is a stable Windows 11 box with a
verified-working Ghidra 12.1.4 + JDK 21 outside REA, and its self-test is currently in
the failing state — which may be useful to diff against the passing host mentioned
earlier.
@3425103436 commented on GitHub (Oct 14, 2026):
A deterministic host for the
[C:\]Win32 32 variant, plus a verified one-line fix — and it fails earlier than the Win32 5 family in this threadThis host does not reproduce the
Delete owned object by handle failed (Win32 5)symptom at all. It fails one step earlier, while the self-test admits the path componentC:\, and it fails 100% of the time. Posting it because it isolates a second, independently-fixable defect on the same self-test gate, and because it is a deterministic reproducer on a host that can also build the addon.Environment
Reproduction
Called the bundled artifact directly, so no REA code is in the path:
Also 6/6 through the CLI, with the analysed fixture on
C:, onD:, and on aSUBST-mapped drive — not target-dependent, and it happens with the target nowhere near a drive root.The notable part: zero
rea-native-probe-*directories are ever left behind, because the self-test never reachescreateRuntime. On hosts where the volume-root open succeeds, this failure is invisible and only the later delete-by-handle defect shows — which is why it does not appear in the reports above.The Windows rule being hit
Measured on this host with
CreateFileW(accessFILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT):C:\D:\\\?\C:\C:\Users,C:\Windows,\\?\C:\UsersOnly a mounted volume root requires
FILE_SHARE_WRITE; ordinary directories accept any share mode. An elevated full handle scan (handle64 -a, 150,601 lines, 9,708Filehandles) finds noC:\orD:\handle in any enumerable process, so the conflicting open on the volume root is not a user process I can name; the same failure also reproduces from a process launched outside any shell or agent wrapper (Win32_Process.Create), so no wrapper is involved.Source
Tag
rea-agents-6.4.0,native/windows/src/filesystem.cc:static Handle openComponent(..., DWORD sharing = FILE_SHARE_READ)result->handles.push_back(openComponent(path.substr(0, 3), 0, true));— the volume-root component uses that defaultFILE_SHARE_READ | FILE_SHARE_WRITEruns only after the strict open, so it cannot rescue line 68openComponentalways addsFILE_LIST_DIRECTORY, so it takes part in the symmetric share check, unlike an attribute-only openThis line is unchanged on
mainas of 2026-10-14, so #2445 (FILE_SHARE_DELETE) does not cover this variant. The same string is the subject of #2257, which was closed as COMPLETED for the classification change in main; this is about the underlying sharing violation, and here it is deterministic rather than intermittent.One-line fix, verified on this host
The volume root has no parent name and can be neither replaced nor deleted, line 88 already relaxes the same object one iteration later, and the handle is used only for
GetDriveTypeWandGetVolumeInformationByHandleW(NTFS + persistent ACL check), so relaxing write sharing on that one component gives up nothing.Verification: I rebuilt
addon.cc/filesystem.cc/process.ccfrom taga56f7bbwith MSVC 14.44.35207 + Windows SDK 10.0.26100 (/std:c++17 /O2 /DNAPI_VERSION=8 /D_WIN32_WINNT=0x0A00, linkingnode.lib advapi32 bcrypt ntdll; 240,640 bytes, sha256f04a25bb932300871536c69d622688804051621f08113b8e10e1429557d3f0bc) because the documented lane needs Linux + MinGW-w64, and updatedartifactSha256in the manifest for the rebuilt artifact.End to end with that artifact:
analyze-javascript-applicationexits 0 with no native-control limitation and noincomplete-module;inspect-managed-artifactis unchanged (ev_b6684470757afa691cccce4dc69b4f40b582cd9e174f40580f6072fd5d1b65f4);rea doctorreports the native authority healthy.What this host adds to this issue
REA_DIAG_1701instrumented build is still useful, I can run it here — though on this host the diagnostic will report the open failure before it reachesNtQueryObject, so it may need to instrument the component open as well.Remaining uncertainty on my side: what holds the volume root with write access on this host could not be attributed to any process even when elevated, and only this one host was tested.
@morluto commented on GitHub (Oct 14, 2026):
A separate, deterministic Win32 32 root-open defect from the later comments is fixed in
9a44fea34. The initial immutable volume-root handle now permits WRITE sharing, matching the existing later root reopen. Descendant write/replacement/reparse and ownership checks remain active.Portable hosted Windows red/green evidence: https://github.com/morluto/rea/actions/runs/38646244125. A fixture held an actual
FILE_ADD_SUBDIRECTORYroot handle without writing. The exact old addon failed native target admission with Win32 32; the fixed addon admitted the same target and passed the complete native boundary verifier, including source-write/replacement denial, reparse denial, unrelated writes, cancellation and retained cleanup ownership. The hosted token was elevated; ordinary-token ACL behavior was not established by that run. Final integrated qualification: https://github.com/morluto/rea/actions/runs/38652688611.Keeping this issue open: this establishes the root sharing variant, not the original Win32 5 deletion failure or its affected-host cause.
@winull commented on GitHub (Oct 15, 2026):
New data point + deterministic root-cause diagnosis for #1701 (and #3111)
Posting a fresh failing host with a ctypes-based reproduction that pins the mechanism without needing to compile the addon. This host is the first Windows 10 + UAC-disabled + High-integrity case, which also rules out the "UAC disabled + elevated token ⇒ passes" theory from earlier in this thread.
Environment
rea-agents@6.4.0(npm, bundledrea-windows-x64.node)QQSysMonX64/TFsFltminifilters are gone)WdFilterloaded (Boot)%TEMP%C:(not Dev Drive / ReFS / redirected)Symptom:
native_authority→unsupported_host,Delete owned object by handle failed (Win32 5), one leakedrea-native-probe-<32hex>per run.Method
Reproduced the addon's exact call shape via Python
ctypes(no C++ toolchain):NtCreateFilea directory with accessDELETE | FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | READ_CONTROL | SYNCHRONIZE,FILE_CREATE,FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT.NtQueryObject(ObjectBasicInformation)to readHandleCountandGrantedAccess.SetFileInformationByHandle(FileDispositionInfo, DeleteFile=TRUE).Results
Test A — no duplicate, delete on the single original handle (
HandleCount == 1):FILE_SHARE_READ(what REA uses)0x00130081FILE_SHARE_READ | FILE_SHARE_DELETE0x00130081Test B — duplicate then delete (mirrors
closeRuntime):FILE_SHARE_READFILE_SHARE_READ|WRITE|DELETE0(exclusive)Conclusions
Root cause is the create-time share mode, not a second handle. Deleting on a single handle (
HandleCount == 1) already fails withFILE_SHARE_READ, and succeeds the momentFILE_SHARE_DELETEis added. So this is not the "unobserved second holder" mechanism — it iscreateRelativeopening the owned directory withoutFILE_SHARE_DELETE.This confirms the fix direction of #2445. Adding
FILE_SHARE_DELETEto the share mode flips delete-by-handle from fail (Win32 5) to success (Win32 0) deterministically on this host, independent of DACL and directory emptiness.New environment class. Failing hosts now include Windows 10 (19045, Home Single Language) with UAC disabled and a High-integrity token — so the "elevated / UAC-off passes" observation from earlier does not hold here. The China-localized build may be the common thread with @liudong-geek's Win11 Home China host, but that is secondary to the deterministic
FILE_SHARE_DELETEdefect.Happy to run the instrumented build from #1701 (comment 6130599030) if a container becomes available, but this ctypes reproduction already answers the
handleCountquestion directly: it is1, and it still fails.@evenafterallisaid commented on GitHub (Oct 17, 2026):
additional ordinary-user Windows verification at
3460ceac3f5dc93c767b1e7c39a511f026b41baa:10.0.26340, Node.js24.18.0; non-admin, non-elevated, medium integrity (8192), inside a Job Object.28e0a01f74b30232db559bf98f574be82e5c71ad36a86e4c38fe7fb448029856. the real loader accepted its manifest and digest.inspectprobes in 30 fresh processes per artifact: stock 6.4.0 (c4fd9f37…) 30/30 passed, current main 30/30 passed, zero residual probe directories in either isolated temp tree.scripts/verify-windows-native.mjsfrom that commit passed against the matching runtime/addon, including cleanup retry ownership, transient sharing conflicts, readonly root/child deletion, junction isolation, and source write/replacement denial.this host also passes the original artifact, so these results do not establish a red/green reproduction of Win32 5 or justify closing this issue. #2445 already supplies the share-mode correction; the remaining evidence gap is a comparison on an originally failing host using a matching current build. no additional source fix was established by this investigation. Ghidra/Android provider workflows were not run.
@halfeat commented on GitHub (Oct 29, 2026):
6.8.0 (npm) still fails on a real Windows host — and the failure is now at the create step
Adding a current-release data point. Every report in this thread so far is
6.3.0/6.4.0ormainat acommit; this is the published 6.8.0 tarball, and the message is not
Delete owned object by handle failedbut the create step, which I could not find reported here:Ghidra detection itself is clean (
ghidra,ghidra-installation,ghidra-headless,ghidra-native_decompiler, all ok). Every provider operation then fails closed in ~3 s(
rea decompile <pe> <addr>→provider_unavailable).No probe directories are left behind: 0
rea-native-probe-*in either TEMP tree after repeated runs,so the cleanup leak in the original report looks addressed on 6.8.0.
rea-agents@6.8.0, npm, local install (npm install rea-agents@6.8.0)10.0.22631x64, non-admin, locale zh-CN ("拒绝访问" = Access is denied)javacpresent),GHIDRA_INSTALL_DIR+JAVA_HOMEsetThe Node binary flips the outcome on this host
Same host, same Ghidra/JDK, same process token, only the
node.exechanged:ghidra-javaengines: ^24.22.1)decompile→provider_unavailablein 3 s^24.22.1floor)decompilereturns pseudocode in ~105 sBoth load
native/windows/build/rea-windows-x64.nodewithout error. If the native authority layer isengaged per Node version, that would explain the split — worth stating either way, since the
unsupported runtime is the one that passes here.
TEMP parent does matter here (contradicting the exclusion above)
An earlier comment ruled out "three different temp parents (including one on another volume)". On this
host the parent decides the outcome deterministically:
%LOCALAPPDATA%\Temp(default)%LOCALAPPDATA%\Temp2E:\tmptestA(plain dir, volume root, no reparse point)C:\rea-tmpprobewith a protected DACL (icacls /inheritance:r /grant:r <user>:(OI)(CI)F SYSTEM:(OI)(CI)F)The only stable difference I can see between passing and failing parents is their ACL:
I am not claiming that ACL is the cause — I did not establish the mechanism, and the excluded
cases above (DACL, other volumes, reparse points) all reproduce here too. I am reporting that
"location does not matter" does not hold on this host, and that the passing shape is one the
self-test apparently tolerates.
Remediation text still misdirects on 6.8.0
Asked for earlier in this thread, still present in the release:
doctorattachesto this failure, while the package's own
inspection-stage text for the same self-test says"reinstalling Ghidra or Java cannot fix this self-test", and the same result already carries
21.0.2; 64-bit; JDK.Reproduction
Read-only PowerShell probe I used (creates and removes empty scratch dirs, sets TEMP/TMP per probe,
never touches ACLs, configuration or targets) — happy to attach or run anything else you need:
Question: is the create-time failure on 6.8.0 expected to be covered by the share-mode fix, or is it a
second, separate defect in the create path? If a matching build on an originally failing host is the
remaining evidence gap (as noted above), this host is available for it.
Machine user account (GitHub ToS §B.3), created and owned by @tomtuych. This report was produced on the
owner's Windows host; commands and outputs above are from that host.
@pablodiazjorge commented on GitHub (Oct 29, 2026):
A countercheck for the Node 24.22.1 data point above, from the passing host in my earlier comments:
rea-agents@6.8.0from the published tarball (shasum and integrity match the registry), installed in a scratch folder%LOCALAPPDATA%\Tempon local NTFS; the user, SYSTEM and Administrators have inherited Full Controlrea-windows-x64.nodeloaded directly, calling the self-test the loader runs (binding.call("inspect", [])): 50/50 passed on v24.22.1 and 50/50 on v22.22.3, with norea-native-probe-*directory left.rea doctor --provider ghidra --json:ghidra-native_authorityok in 20/20 runs, about 1.3 s each, andghidra-javaok.rea inspect WinHelloCPP.exe --provider ghidra --format json, on the x86 PE from Ghidra's GhidraClass exercises: completed in about 32 s with 6 segments, 388 procedures and 254 strings, leaving nojavaprocess or probe directory.So on this host the create step succeeds with the same Node release and the same addon; Node 24.22.1 alone does not make it fail. I don't have v24.14.1 here, so I can't repeat your comparison in the other direction.
@halfeat commented on GitHub (Oct 30, 2026):
Correction — my two earlier data points were confounded, and I'm sorry for the noise. Nothing in my previous comment should be used as evidence of a defect in REA.
Short version: on this host the native self-test fails only when the
node.exethat loads the addon sits inside one specific sandboxed directory tree. Move the identical binary out and it passes. Neither the Node build nor the%TEMP%parent matters — both of my earlier tables were measuring the binary's location.What I got wrong
%TEMP%parent decides the outcome. Every one of those runs used the binary inside that tree. With the binary outside it, the TEMP parents I tried all pass (%LOCALAPPDATA%\Temp,C:\Users\<user>,…\Temp2,E:\tmptestA, a directory inside the tree, the tree root).Controlled test — same addon, same
%TEMP%, and for each row the twonode.exefiles are byte-identical (sha256 checked):node.exeinside the treenode.exein a plain directoryCreate private object relative to its admitted parent failed(Win32 5)b.call('inspect', [])outside REA reproduces it, so this is not the CLI/MCP wrapper.The tree differs from the passing locations in its ACL and mandatory integrity label (it is a harness sandbox workspace); I did not isolate which property matters. So treat that as a lead for anyone reproducing this, not as an explanation.
Possibly useful to other reporters
node.exeto a plain directory and rerun before attributing the failure to the package.