mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-08-14 23:07:29 +00:00
Block prototype keys in config paths
This commit is contained in:
parent
8f4691584c
commit
cdba848866
2 changed files with 25 additions and 5 deletions
10
packages/cli/src/config.test.ts
Normal file
10
packages/cli/src/config.test.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { getConfigValue, setConfigValue } from "./config.js";
|
||||
|
||||
describe("CLI config", () => {
|
||||
it("rejects prototype-polluting path segments", () => {
|
||||
expect(() => setConfigValue("__proto__.polluted", "true", {})).toThrow(/prototype keys/);
|
||||
expect(() => getConfigValue("constructor.prototype.polluted", {})).toThrow(/prototype keys/);
|
||||
expect(({} as Record<string, unknown>).polluted).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -40,14 +40,12 @@ export function writeConfig(config: JsonObject) {
|
|||
}
|
||||
|
||||
export function getConfigValue(path: string, config = readConfig()) {
|
||||
return path.split(".").reduce<unknown>((current, key) => (isObject(current) ? current[key] : undefined), config);
|
||||
const parts = splitConfigPath(path);
|
||||
return parts.reduce<unknown>((current, key) => (isObject(current) ? current[key] : undefined), config);
|
||||
}
|
||||
|
||||
export function setConfigValue(path: string, rawValue: string, config = readConfig()) {
|
||||
const parts = path.split(".").filter(Boolean);
|
||||
if (parts.length === 0) {
|
||||
throw new Error("Config path cannot be empty.");
|
||||
}
|
||||
const parts = splitConfigPath(path);
|
||||
let current: JsonObject = config;
|
||||
for (const part of parts.slice(0, -1)) {
|
||||
if (!isObject(current[part])) {
|
||||
|
|
@ -59,6 +57,18 @@ export function setConfigValue(path: string, rawValue: string, config = readConf
|
|||
return config;
|
||||
}
|
||||
|
||||
function splitConfigPath(path: string) {
|
||||
const parts = path.split(".");
|
||||
const blocked = new Set(["__proto__", "constructor", "prototype"]);
|
||||
if (parts.length === 0 || parts.some((part) => part.length === 0)) {
|
||||
throw new Error("Config path cannot contain empty segments.");
|
||||
}
|
||||
if (parts.some((part) => blocked.has(part))) {
|
||||
throw new Error("Config path cannot contain prototype keys.");
|
||||
}
|
||||
return parts;
|
||||
}
|
||||
|
||||
export function parseConfigValue(value: string): unknown {
|
||||
if (value === "true") return true;
|
||||
if (value === "false") return false;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue