Share tagged readiness observations, retain partial provider facts, authenticate bridge identity, bound diagnostics, and preserve cancellation and lost-session reasons. Fail closed for unparsed MIPS ABI attributes and macOS saved Hopper databases without a script-capable bridge route. Reviewed fixes: #2010, #2108, #2513, #2695, #2731, #2771, #2828, #2867, #2868, #2870, #2880, #2919, #2945, #2961, #2981, #2998, #3000, #3002. Validation: 285 focused source/boundary tests passed. Real Ghidra, IDA, Linux Hopper, and Windows provider runs were not repeated. BREAKING CHANGE: MIPS targets with unresolved GNU ABI attributes and saved Hopper databases on macOS are refused rather than advertised as supported.
222 lines
6.7 KiB
TypeScript
222 lines
6.7 KiB
TypeScript
import { createHash } from "node:crypto";
|
|
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
loadWindowsNativeAuthority,
|
|
type WindowsNativeLoadHost,
|
|
} from "./WindowsNativeLoader.js";
|
|
|
|
const fixture = (
|
|
capabilities: {
|
|
protocolStdin?: boolean;
|
|
jobMemoryLimit?: unknown;
|
|
privateBridgeDescriptorAccess?: unknown;
|
|
} = {},
|
|
) => {
|
|
const bytes = Buffer.alloc(128);
|
|
bytes.write("MZ");
|
|
bytes.writeUInt32LE(64, 0x3c);
|
|
bytes.write("PE\0\0", 64, "ascii");
|
|
bytes.writeUInt16LE(0x8664, 68);
|
|
bytes.writeUInt16LE(0x20b, 88);
|
|
const manifest = {
|
|
packageVersion: "1.0.0",
|
|
platform: "win32",
|
|
architecture: "x64",
|
|
abiVersion: 1,
|
|
nodeApiVersion: 8,
|
|
artifact: "rea-windows-x64.node",
|
|
artifactSha256: createHash("sha256").update(bytes).digest("hex"),
|
|
};
|
|
const identity = {
|
|
requestedPath: "D:\\fixture\\runtime",
|
|
finalPath: "\\\\?\\D:\\fixture\\runtime",
|
|
filesystem: "NTFS",
|
|
volumeSerial: "0123456789abcdef",
|
|
fileId: "0123456789abcdef0123456789abcdef",
|
|
size: 0,
|
|
directory: true,
|
|
};
|
|
let loads = 0;
|
|
const host: WindowsNativeLoadHost = {
|
|
platform: "win32",
|
|
architecture: "x64",
|
|
nodeApiVersion: "8",
|
|
packageVersion: "1.0.0",
|
|
readManifest: () => manifest,
|
|
readArtifact: () => bytes,
|
|
loadArtifact: () => {
|
|
loads++;
|
|
return {
|
|
call: () => ({
|
|
abiVersion: 1,
|
|
nodeApiVersion: 8,
|
|
architecture: "x64",
|
|
filesystem: identity,
|
|
privateDacl: true,
|
|
privateBridgeDescriptorAccess: true,
|
|
atomicJobAssignment: true,
|
|
killOnOwnerClose: true,
|
|
...capabilities,
|
|
}),
|
|
};
|
|
},
|
|
};
|
|
return { host, manifest, bytes, loads: () => loads };
|
|
};
|
|
|
|
describe("packaged Windows native admission", () => {
|
|
it.each([true, false])(
|
|
"preserves protocol stdin capability %s alongside existing job controls",
|
|
(protocolStdin) => {
|
|
const value = fixture({ protocolStdin });
|
|
expect(loadWindowsNativeAuthority(value.host)).toMatchObject({
|
|
available: true,
|
|
authority: {
|
|
inspection: {
|
|
protocolStdin,
|
|
atomicJobAssignment: true,
|
|
killOnOwnerClose: true,
|
|
},
|
|
},
|
|
});
|
|
},
|
|
);
|
|
it("admits the Job Object memory limit control only as an affirmative observation", () => {
|
|
expect(
|
|
loadWindowsNativeAuthority(fixture({ jobMemoryLimit: true }).host),
|
|
).toMatchObject({
|
|
available: true,
|
|
authority: { inspection: { jobMemoryLimit: true } },
|
|
});
|
|
// Earlier artifacts omit the control; callers must refuse a limit then.
|
|
const earlier = loadWindowsNativeAuthority(fixture().host);
|
|
if (!earlier.available) throw new Error(earlier.reason);
|
|
expect(earlier.authority.inspection.jobMemoryLimit).toBeUndefined();
|
|
expect(
|
|
loadWindowsNativeAuthority(fixture({ jobMemoryLimit: false }).host)
|
|
.available,
|
|
).toBe(false);
|
|
});
|
|
it("loads only after compatibility and digest checks, preserving producer identity", () => {
|
|
const value = fixture();
|
|
expect(loadWindowsNativeAuthority(value.host)).toMatchObject({
|
|
available: true,
|
|
authority: {
|
|
inspection: { filesystem: { requestedPath: "D:\\fixture\\runtime" } },
|
|
},
|
|
});
|
|
expect(value.loads()).toBe(1);
|
|
});
|
|
|
|
it.each([
|
|
[{ platform: "linux" as const }, "host"],
|
|
[{ architecture: "arm64" }, "host"],
|
|
[{ nodeApiVersion: "7" }, "host"],
|
|
[{ nodeApiVersion: undefined }, "host"],
|
|
[{ packageVersion: "2.0.0" }, "artifact"],
|
|
] as const)(
|
|
"rejects incompatible host metadata before loading: %j",
|
|
(override, failureStage) => {
|
|
const value = fixture();
|
|
expect(
|
|
loadWindowsNativeAuthority({ ...value.host, ...override }),
|
|
).toMatchObject({ available: false, failureStage });
|
|
expect(value.loads()).toBe(0);
|
|
},
|
|
);
|
|
|
|
it("rejects tampering even when the original file was a valid PE image", () => {
|
|
const value = fixture();
|
|
value.bytes[127] = 1;
|
|
expect(loadWindowsNativeAuthority(value.host)).toMatchObject({
|
|
available: false,
|
|
failureStage: "artifact",
|
|
reason: expect.stringContaining("SHA-256"),
|
|
});
|
|
expect(value.loads()).toBe(0);
|
|
});
|
|
|
|
it.each(["abiVersion", "nodeApiVersion", "architecture", "artifact"])(
|
|
"rejects invalid manifest %s",
|
|
(key) => {
|
|
const value = fixture();
|
|
expect(
|
|
loadWindowsNativeAuthority({
|
|
...value.host,
|
|
readManifest: () => ({ ...value.manifest, [key]: "invalid" }),
|
|
}).available,
|
|
).toBe(false);
|
|
expect(value.loads()).toBe(0);
|
|
},
|
|
);
|
|
|
|
it.each([
|
|
{ signature: "MZ", offset: 0 },
|
|
{ signature: "PE", offset: 64 },
|
|
])(
|
|
"rejects digest-valid high-bit $signature lookalikes before loading",
|
|
({ offset }) => {
|
|
const value = fixture();
|
|
value.bytes[offset] = (value.bytes[offset] ?? 0) | 0x80;
|
|
value.manifest.artifactSha256 = createHash("sha256")
|
|
.update(value.bytes)
|
|
.digest("hex");
|
|
expect(loadWindowsNativeAuthority(value.host).available).toBe(false);
|
|
expect(value.loads()).toBe(0);
|
|
},
|
|
);
|
|
|
|
it("rejects a digest-valid artifact for another machine", () => {
|
|
const value = fixture();
|
|
value.bytes.writeUInt16LE(0xaa64, 68);
|
|
value.manifest.artifactSha256 = createHash("sha256")
|
|
.update(value.bytes)
|
|
.digest("hex");
|
|
expect(loadWindowsNativeAuthority(value.host)).toMatchObject({
|
|
available: false,
|
|
reason: expect.stringContaining("PE32+"),
|
|
});
|
|
expect(value.loads()).toBe(0);
|
|
});
|
|
|
|
it("preserves host permission failure rather than promoting a partial probe", () => {
|
|
const value = fixture();
|
|
expect(
|
|
loadWindowsNativeAuthority({
|
|
...value.host,
|
|
loadArtifact: () => ({
|
|
call: () => {
|
|
throw new Error("private DACL: access denied");
|
|
},
|
|
}),
|
|
}),
|
|
).toMatchObject({
|
|
available: false,
|
|
failureStage: "self-test",
|
|
retryable: true,
|
|
reason: expect.stringContaining("private DACL: access denied"),
|
|
});
|
|
});
|
|
|
|
it("requires every inspected native fact", () => {
|
|
const value = fixture();
|
|
const loaded = loadWindowsNativeAuthority({
|
|
...value.host,
|
|
loadArtifact: () => ({ call: () => ({ privateDacl: true }) }),
|
|
});
|
|
expect(loaded.available).toBe(false);
|
|
expect(loaded).toMatchObject({ failureStage: "inspection" });
|
|
expect(loaded).not.toHaveProperty("retryable");
|
|
});
|
|
|
|
it("rejects Windows controls without handle-bound Cutter descriptor access", () => {
|
|
const value = fixture({ privateBridgeDescriptorAccess: undefined });
|
|
expect(loadWindowsNativeAuthority(value.host)).toMatchObject({
|
|
available: false,
|
|
reason: expect.stringContaining("privateBridgeDescriptorAccess"),
|
|
});
|
|
});
|
|
});
|