mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-08 17:10:50 -10:00
fix(windows): tolerate LPAC EPERM from realpathSync.native on directories
f0080cd2e stopped JS realpathSync from walking to C:\ under LPAC by using
realpathSync.native and comparing canonical-to-canonical. Hosted Windows on
#6846 still failed the six native_mcp activations with
`EPERM: operation not permitted, realpath '...\source'`: admitReviewedClosure
canonicalizes the reviewed source directory, and native realpath opens it with
FILE_FLAG_BACKUP_SEMANTICS, which AppContainers refuse.
On win32 EPERM/EACCES, keep stripVerbatim(normalize(path)) instead of
throwing. Core already refused links while granting that tree. File checks
still prefer native when it succeeds. Bundles rebuilt.
Evidence (Linux box, node 20): node --test test/canonical-path.test.mjs
passes. Windows LPAC proof is hosted Test (windows-latest).
Signed-off-by: CodeWhale Bot <[email protected]>
This commit is contained in:
1 parent
6958ca6dd7
commit
5d110e82fd
5 files changed
+60
-5
No files matched your search
+10
-1
@@ -6106,7 +6106,16 @@ var init_skill_filesystem = __esm({
|
||||
import { realpathSync } from "node:fs";
|
||||
import { posix, win32 } from "node:path";
|
||||
function canonicalPath(path, platform = process.platform) {
|
||||
return stripVerbatim(platform === "win32" ? realpathSync.native(path) : realpathSync(path), platform);
|
||||
if (platform !== "win32") return realpathSync(path);
|
||||
try {
|
||||
return stripVerbatim(realpathSync.native(path), platform);
|
||||
} catch (error) {
|
||||
const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
|
||||
if (code === "EPERM" || code === "EACCES") {
|
||||
return stripVerbatim(win32.normalize(path), platform);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
function stripVerbatim(path, platform = process.platform) {
|
||||
if (platform !== "win32") return path;
|
||||
|
||||
+10
-1
@@ -6482,7 +6482,16 @@ var init_skill_filesystem = __esm({
|
||||
import { realpathSync } from "node:fs";
|
||||
import { posix, win32 } from "node:path";
|
||||
function canonicalPath(path, platform = process.platform) {
|
||||
return stripVerbatim(platform === "win32" ? realpathSync.native(path) : realpathSync(path), platform);
|
||||
if (platform !== "win32") return realpathSync(path);
|
||||
try {
|
||||
return stripVerbatim(realpathSync.native(path), platform);
|
||||
} catch (error) {
|
||||
const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
|
||||
if (code === "EPERM" || code === "EACCES") {
|
||||
return stripVerbatim(win32.normalize(path), platform);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
function stripVerbatim(path, platform = process.platform) {
|
||||
if (platform !== "win32") return path;
|
||||
|
||||
+10
-1
@@ -6057,7 +6057,16 @@ var init_skill_filesystem = __esm({
|
||||
import { realpathSync } from "node:fs";
|
||||
import { posix, win32 } from "node:path";
|
||||
function canonicalPath(path, platform = process.platform) {
|
||||
return stripVerbatim(platform === "win32" ? realpathSync.native(path) : realpathSync(path), platform);
|
||||
if (platform !== "win32") return realpathSync(path);
|
||||
try {
|
||||
return stripVerbatim(realpathSync.native(path), platform);
|
||||
} catch (error) {
|
||||
const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
|
||||
if (code === "EPERM" || code === "EACCES") {
|
||||
return stripVerbatim(win32.normalize(path), platform);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
function stripVerbatim(path, platform = process.platform) {
|
||||
if (platform !== "win32") return path;
|
||||
|
||||
+10
-1
@@ -7,7 +7,16 @@ import { resolve, relative, isAbsolute, sep } from "node:path";
|
||||
import { realpathSync } from "node:fs";
|
||||
import { posix, win32 } from "node:path";
|
||||
function canonicalPath(path, platform = process.platform) {
|
||||
return stripVerbatim(platform === "win32" ? realpathSync.native(path) : realpathSync(path), platform);
|
||||
if (platform !== "win32") return realpathSync(path);
|
||||
try {
|
||||
return stripVerbatim(realpathSync.native(path), platform);
|
||||
} catch (error) {
|
||||
const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
|
||||
if (code === "EPERM" || code === "EACCES") {
|
||||
return stripVerbatim(win32.normalize(path), platform);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
function stripVerbatim(path, platform = process.platform) {
|
||||
if (platform !== "win32") return path;
|
||||
|
||||
@@ -10,6 +10,13 @@
|
||||
* never compared with a raw one. Both sides go through `canonicalPath`, then
|
||||
* `pathKey`, and containment is `relative(canonical root, canonical target)`.
|
||||
*
|
||||
* Under LPAC, `realpathSync.native` still fails with EPERM on some paths —
|
||||
* especially directories such as the reviewed `source/` root — because the
|
||||
* open uses FILE_FLAG_BACKUP_SEMANTICS. Core already refused links while
|
||||
* granting that tree, so on EPERM/EACCES we keep a stable stripped spelling
|
||||
* instead of throwing and aborting admitReviewedClosure. Link refusal for
|
||||
* files still goes through the same helper when native succeeds.
|
||||
*
|
||||
* Elsewhere `realpathSync` is unchanged.
|
||||
*/
|
||||
import { realpathSync } from 'node:fs'
|
||||
@@ -18,7 +25,19 @@ import { posix, win32 } from 'node:path'
|
||||
type Platform = NodeJS.Platform
|
||||
|
||||
export function canonicalPath(path: string, platform: Platform = process.platform): string {
|
||||
return stripVerbatim(platform === 'win32' ? realpathSync.native(path) : realpathSync(path), platform)
|
||||
if (platform !== 'win32') return realpathSync(path)
|
||||
try {
|
||||
return stripVerbatim(realpathSync.native(path), platform)
|
||||
} catch (error) {
|
||||
const code = error && typeof error === 'object' && 'code' in error ? (error as { code?: string }).code : undefined
|
||||
// LPAC cannot open some granted paths the way native realpath requires
|
||||
// (notably directories). Fall back to a stable spelling; Core's grant
|
||||
// already refused links/reparse points in the admitted tree.
|
||||
if (code === 'EPERM' || code === 'EACCES') {
|
||||
return stripVerbatim(win32.normalize(path), platform)
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/** Drop the Win32 verbatim prefix: `\\?\C:\x` → `C:\x`, `\\?\UNC\h\s` → `\\h\s`. Case is kept. */
|
||||
|
||||
Reference in new issue
Block a user