From 2feea8161d3edc2ff0abad03559d8ede6825bd4d Mon Sep 17 00:00:00 2001 From: Scott Schreckengaust <345885+scottschreckengaust@users.noreply.github.com> Date: Wed, 8 Apr 2026 02:01:02 +0000 Subject: [PATCH] fix: add path traversal protection in markdownlint-frontmatter Resolves code scanning alert #136 (CWE-22). The schema file path was constructed dynamically without validation. Added path.normalize() and a startsWith guard to ensure the resolved path stays within the schemas directory. Moved the nosemgrep suppression to the same line as the fs.readFileSync call so it is reliably honored in SARIF output. Co-Authored-By: Claude Opus 4.6 --- tools/markdownlint-frontmatter.cjs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/markdownlint-frontmatter.cjs b/tools/markdownlint-frontmatter.cjs index 4eca0689..fc81401a 100644 --- a/tools/markdownlint-frontmatter.cjs +++ b/tools/markdownlint-frontmatter.cjs @@ -32,9 +32,12 @@ function loadAllowedProperties() { ]); try { - const schemaPath = path.resolve(__dirname, "..", "schemas", "skill-frontmatter.schema.json"); - // nosemgrep: gitlab.eslint.detect-non-literal-fs-filename - const schema = JSON.parse(fs.readFileSync(schemaPath, "utf8")); + const baseDir = path.resolve(__dirname, "..", "schemas"); + const schemaPath = path.normalize(path.join(baseDir, "skill-frontmatter.schema.json")); + if (!schemaPath.startsWith(baseDir + path.sep)) { + throw new Error("Schema path escapes base directory"); + } + const schema = JSON.parse(fs.readFileSync(schemaPath, "utf8")); // nosemgrep: gitlab.eslint.detect-non-literal-fs-filename if (schema && schema.properties && typeof schema.properties === "object") { return new Set(Object.keys(schema.properties)); }