fix(boundaries): reject unsafe local inputs
This commit is contained in:
parent
aee9cb8e4e
commit
15e8cf3234
|
|
@ -308,7 +308,7 @@ const objectValue = (value: unknown): Record<string, unknown> => {
|
|||
return parsed.success ? parsed.data : {};
|
||||
};
|
||||
const parseObject = (text: string): Record<string, unknown> =>
|
||||
objectValue(JSON.parse(text));
|
||||
objectSchema.parse(JSON.parse(text));
|
||||
const isMissing = (cause: unknown): boolean =>
|
||||
cause instanceof Error && "code" in cause && cause.code === "ENOENT";
|
||||
const restoreConfig = async (
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { constants } from "node:fs";
|
||||
import { access, open, realpath } from "node:fs/promises";
|
||||
import { access, open, realpath, stat } from "node:fs/promises";
|
||||
import { isAbsolute, resolve } from "node:path";
|
||||
|
||||
import { BinaryTargetError } from "./errors.js";
|
||||
|
|
@ -36,6 +36,8 @@ export const parseBinaryTarget = async (
|
|||
try {
|
||||
await access(candidate, constants.R_OK);
|
||||
const path = await realpath(candidate);
|
||||
if (!(await stat(path)).isFile())
|
||||
return err(new BinaryTargetError(path, "target is not a regular file"));
|
||||
if (
|
||||
targetKind === "database" ||
|
||||
(targetKind === undefined && path.toLowerCase().endsWith(".hop"))
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ describe("executable header parsing", () => {
|
|||
|
||||
describe("binary target I/O", () => {
|
||||
it("resolves relative Hopper databases and rejects unknown or unreadable paths", async () => {
|
||||
directory = await mkdtemp(join(tmpdir(), "bb-target-"));
|
||||
directory = await mkdtemp(join(tmpdir(), "rea-target-"));
|
||||
await writeFile(join(directory, "sample.hop"), "database");
|
||||
await writeFile(join(directory, "text"), "hello");
|
||||
expect((await parseBinaryTarget("sample.hop", directory)).ok).toBe(true);
|
||||
|
|
@ -75,6 +75,11 @@ describe("binary target I/O", () => {
|
|||
expect((await parseBinaryTarget("missing", directory)).ok).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects non-regular targets before reading them", async () => {
|
||||
directory = await mkdtemp(join(tmpdir(), "rea-target-"));
|
||||
expect((await parseBinaryTarget(directory)).ok).toBe(false);
|
||||
});
|
||||
|
||||
it("honors an explicit database kind without relying on the file suffix", async () => {
|
||||
directory = await mkdtemp(join(tmpdir(), "rea-target-"));
|
||||
await writeFile(join(directory, "saved-analysis"), "database");
|
||||
|
|
|
|||
|
|
@ -59,4 +59,20 @@ describe("JSON client configuration transaction", () => {
|
|||
});
|
||||
expect(await readFile(configPath, "utf8")).toBe("not-json");
|
||||
});
|
||||
|
||||
it.each(["null", "[]", '"value"'])(
|
||||
"refuses a non-object JSON root without overwriting %s",
|
||||
async (original) => {
|
||||
directory = await mkdtemp(join(tmpdir(), "rea-setup-"));
|
||||
const configPath = join(directory, "mcp.json");
|
||||
await writeFile(configPath, original);
|
||||
expect(await configureJsonClient({ name: "cursor", configPath })).toEqual(
|
||||
{ status: "failed", reason: "readback" },
|
||||
);
|
||||
expect(await readFile(configPath, "utf8")).toBe(original);
|
||||
await expect(
|
||||
readFile(`${configPath}.rea.backup`, "utf8"),
|
||||
).rejects.toThrow();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue