Files

98 lines
3.0 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { validateYaml } from "./yaml";
// The Scan Configuration editor (like the Mutelist editor) validates only YAML
// *syntax* on the client; the API validates the configuration values
// (ranges/enums) on create/update. These cover the syntax check the editor and
// `scanConfigurationFormSchema` rely on.
describe("validateYaml", () => {
it("accepts a mapping with provider sections", () => {
// When
const result = validateYaml("aws:\n max_unused_access_keys_days: 45");
// Then
expect(result.isValid).toBe(true);
});
it("accepts a key with no value yet (the `aws:` typing state)", () => {
// When — `aws:` parses to { aws: null }, still a mapping
const result = validateYaml("aws:");
// Then
expect(result.isValid).toBe(true);
});
it("rejects malformed YAML with a syntax error", () => {
// When — unmatched bracket is invalid flow syntax
const result = validateYaml("aws: [1, 2");
// Then
expect(result.isValid).toBe(false);
expect(result.error).toBeTruthy();
});
it("rejects a top-level list (config must be a mapping)", () => {
// When
const result = validateYaml("- aws\n- azure");
// Then
expect(result.isValid).toBe(false);
});
it("rejects empty content", () => {
// When
const result = validateYaml("");
// Then
expect(result.isValid).toBe(false);
});
it("rejects a scalar (not a mapping)", () => {
// When — a bare word parses to the string "aws", not a mapping
const result = validateYaml("aws");
// Then
expect(result.isValid).toBe(false);
});
// Users author these documents by hand in the Mutelist and Scan Configuration
// editors, so anchors, aliases and merge keys are legitimate input the syntax
// check must keep accepting across js-yaml upgrades (4.3.0 rewrote merge-key
// handling for CVE-2026-59869).
it("accepts anchors, aliases and merge keys", () => {
// When
const result = validateYaml(
[
"defaults: &defaults",
" max_unused_access_keys_days: 45",
"aws:",
" <<: *defaults",
" max_console_access_days: 45",
].join("\n"),
);
// Then
expect(result.isValid).toBe(true);
});
it("rejects a merge-key amplification document (CVE-2026-59869 shape)", () => {
// Given — each mapping merges the previous one and adds a distinct key, so
// merged-key copies grow quadratically (~45k total here). js-yaml 4.3.0
// fixes the CVE by capping that work (maxTotalMergeKeys) and rejecting the
// document; a vulnerable parser accepts it instead, turning the assertion
// below red without relying on timing or suite timeouts.
const chain = ["a0: &a0 { k0: 0 }"];
for (let i = 1; i < 300; i++) {
chain.push(`a${i}: &a${i} { <<: *a${i - 1}, k${i}: ${i} }`);
}
// When
const result = validateYaml(chain.join("\n"));
// Then
expect(result.isValid).toBe(false);
expect(result.error).toMatch(/merge keys/i);
});
});