fix(electron): reject non-directory scenario roots before launch (#8967)

This commit is contained in:
ShuaixinHuang authored and GitHub committed 2026-11-05 15:33:04 +08:00
1 parent 970969cb53
commit 97fe4535f6
3 files changed
+94 -9

No files matched your search

@@ -172,25 +172,58 @@ it.skipIf(SKIP_PERMISSIONS).each([
},
);
it("admits readable selections and hands canonical paths to the provider", async () => {
it("rejects a regular-file application root before provider capture", async () => {
const { readable } = await fixture();
const { provider, capture } = recordingProvider();
const application = join(readable, "main.js");
await captureElectronScenario(
const result = await captureElectronScenario(
provider,
electronActiveObservationInputSchema.parse({
executable_path: process.execPath,
application_path: application,
application_path: join(readable, "main.js"),
application_root: join(readable, "main.js"),
actions: [],
}),
);
expect(capture).toHaveBeenCalledOnce();
expect(capture.mock.calls[0]?.[0]).toMatchObject({
application_path: application,
application_root: readable,
expect(result.ok).toBe(false);
if (result.ok) return;
expect(projectAnalysisError(result.error)).toMatchObject({
code: "invalid_request",
details: {
issues: [
{
path: ["application_root"],
reason: "invalid_value",
message: expect.stringContaining("not a directory"),
},
],
},
});
expect(capture).not.toHaveBeenCalled();
});
it.each([false, true])(
"admits readable selections with explicit root %s and hands canonical paths to the provider",
async (explicitRoot) => {
const { readable } = await fixture();
const { provider, capture } = recordingProvider();
const application = join(readable, "main.js");
await captureElectronScenario(
provider,
electronActiveObservationInputSchema.parse({
executable_path: process.execPath,
application_path: application,
...(explicitRoot ? { application_root: readable } : {}),
actions: [],
}),
);
expect(capture).toHaveBeenCalledOnce();
expect(capture.mock.calls[0]?.[0]).toMatchObject({
application_path: application,
application_root: readable,
});
},
);
it.skipIf(process.platform === "win32")(
"records selected scenario paths and omission while executing canonical paths",
async () => {
@@ -62,7 +62,19 @@ const resolveInputPath = async (
try {
// Darwin realpath can collapse file/.. even though native lookup rejects
// that traversal. Admit the selected path before canonicalizing it.
await stat(selected);
const metadata = await stat(selected);
if (field === "application_root" && !metadata.isDirectory()) {
const cause = new Error("not a directory");
return err({
kind: "invalid",
issue: {
path: [field],
reason: "invalid_value",
message: `application_root ${selected} is not a directory`,
},
cause,
});
}
return ok(await realpath(selected));
} catch (cause: unknown) {
return err(