3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-05-10 12:25:02 +00:00

Disallow anchors/aliases to objects when loading config YAML

This commit is contained in:
Dragory 2021-08-14 18:22:29 +03:00
parent e8e764c3b7
commit cb8d914fef
No known key found for this signature in database
GPG key ID: 5F387BA66DF8AAC1
5 changed files with 96 additions and 3 deletions

View file

@ -0,0 +1,11 @@
import yaml from "js-yaml";
import { validateNoObjectAliases } from "./validateNoObjectAliases";
/**
* Loads a YAML file safely while removing object anchors/aliases (including arrays)
*/
export function loadYamlSafely(yamlStr: string): any {
const loaded = yaml.safeLoad(yamlStr);
validateNoObjectAliases(loaded);
return loaded;
}

View file

@ -0,0 +1,43 @@
import test from "ava";
import { ObjectAliasError, validateNoObjectAliases } from "./validateNoObjectAliases";
test("validateNoObjectAliases() disallows object aliases at top level", t => {
const obj: any = {
objectRef: {
foo: "bar",
},
};
obj.otherProp = obj.objectRef;
t.throws(() => validateNoObjectAliases(obj), { instanceOf: ObjectAliasError });
});
test("validateNoObjectAliases() disallows aliases to nested objects", t => {
const obj: any = {
nested: {
objectRef: {
foo: "bar",
},
},
};
obj.otherProp = obj.nested.objectRef;
t.throws(() => validateNoObjectAliases(obj), { instanceOf: ObjectAliasError });
});
test("validateNoObjectAliases() disallows nested object aliases", t => {
const obj: any = {
nested: {
objectRef: {
foo: "bar",
},
},
};
obj.otherProp = {
alsoNested: {
ref: obj.nested.objectRef,
},
};
t.throws(() => validateNoObjectAliases(obj), { instanceOf: ObjectAliasError });
});

View file

@ -0,0 +1,27 @@
import { Not } from "../utils";
const scalarTypes = ["string", "number", "boolean", "bigint"];
export class ObjectAliasError extends Error {}
/**
* Removes object aliases/anchors from a loaded YAML object
*/
export function validateNoObjectAliases<T extends {}>(obj: T, seen?: WeakSet<any>): void {
if (!seen) {
seen = new WeakSet();
}
for (const [key, value] of Object.entries(obj)) {
if (value == null || scalarTypes.includes(typeof value)) {
continue;
}
if (seen.has(value)) {
throw new ObjectAliasError("Object aliases are not allowed");
}
validateNoObjectAliases(value as {}, seen);
seen.add(value);
}
}