From 6f30197f5ecc034ccc8dd20535ec95682aa23806 Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Wed, 18 Feb 2026 10:38:08 +0100 Subject: [PATCH 1/2] fix: replace execSync with execFileSync in docs validation Replace all execSync calls with execFileSync to avoid shell interpretation of interpolated paths. This resolves a CodeQL alert about shell command injection via uncontrolled absolute paths (scripts/docs-validation/validate.ts:79). execFileSync passes arguments as an array, bypassing the shell entirely, which eliminates the risk of path characters being misinterpreted. Also updated catch blocks to check err.stderr in addition to err.stdout, since 2>&1 shell redirection is no longer used. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- scripts/docs-validation/validate.ts | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/scripts/docs-validation/validate.ts b/scripts/docs-validation/validate.ts index 109430c81..61952b644 100644 --- a/scripts/docs-validation/validate.ts +++ b/scripts/docs-validation/validate.ts @@ -5,7 +5,7 @@ import * as fs from "fs"; import * as path from "path"; -import { execSync, spawn } from "child_process"; +import { execFileSync, spawn } from "child_process"; import { glob } from "glob"; const ROOT_DIR = path.resolve(import.meta.dirname, "../.."); @@ -76,7 +76,7 @@ async function validateTypeScript(): Promise { try { // Run tsc const tscPath = path.join(ROOT_DIR, "nodejs/node_modules/.bin/tsc"); - execSync(`${tscPath} --project ${tsconfigPath} 2>&1`, { + execFileSync(tscPath, ["--project", tsconfigPath], { encoding: "utf-8", cwd: tsDir, }); @@ -98,10 +98,8 @@ async function validateTypeScript(): Promise { } } catch (err: any) { // Parse tsc output for errors - const output = err.stdout || err.message || ""; + const output = err.stdout || err.stderr || err.message || ""; const errorLines = output.split("\n"); - - // Group errors by file const fileErrors = new Map(); let currentFile = ""; @@ -162,22 +160,23 @@ async function validatePython(): Promise { // Syntax check with py_compile try { - execSync(`python3 -m py_compile "${fullPath}" 2>&1`, { + execFileSync("python3", ["-m", "py_compile", fullPath], { encoding: "utf-8", }); } catch (err: any) { - errors.push(err.stdout || err.message || "Syntax error"); + errors.push(err.stdout || err.stderr || err.message || "Syntax error"); } // Type check with mypy (if available) if (errors.length === 0) { try { - execSync( - `python3 -m mypy "${fullPath}" --ignore-missing-imports --no-error-summary 2>&1`, + execFileSync( + "python3", + ["-m", "mypy", fullPath, "--ignore-missing-imports", "--no-error-summary"], { encoding: "utf-8" } ); } catch (err: any) { - const output = err.stdout || err.message || ""; + const output = err.stdout || err.stderr || err.message || ""; // Filter out "Success" messages and notes const typeErrors = output .split("\n") @@ -227,7 +226,7 @@ replace github.com/github/copilot-sdk/go => ${path.join(ROOT_DIR, "go")} // Run go mod tidy to fetch dependencies try { - execSync(`go mod tidy 2>&1`, { + execFileSync("go", ["mod", "tidy"], { encoding: "utf-8", cwd: goDir, env: { ...process.env, GO111MODULE: "on" }, @@ -246,7 +245,7 @@ replace github.com/github/copilot-sdk/go => ${path.join(ROOT_DIR, "go")} try { // Use go vet for syntax and basic checks - execSync(`go build -o /dev/null "${fullPath}" 2>&1`, { + execFileSync("go", ["build", "-o", "/dev/null", fullPath], { encoding: "utf-8", cwd: goDir, env: { ...process.env, GO111MODULE: "on" }, @@ -300,7 +299,7 @@ async function validateCSharp(): Promise { // Compile all files together try { - execSync(`dotnet build "${path.join(csDir, "DocsValidation.csproj")}" 2>&1`, { + execFileSync("dotnet", ["build", path.join(csDir, "DocsValidation.csproj")], { encoding: "utf-8", cwd: csDir, }); From 5f18ddcb9e0c04b94ccf75f4f83ec84285cff3ff Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Wed, 18 Feb 2026 10:40:54 +0100 Subject: [PATCH 2/2] chore: remove unused spawn import Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- scripts/docs-validation/validate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/docs-validation/validate.ts b/scripts/docs-validation/validate.ts index 61952b644..0d1919c39 100644 --- a/scripts/docs-validation/validate.ts +++ b/scripts/docs-validation/validate.ts @@ -5,7 +5,7 @@ import * as fs from "fs"; import * as path from "path"; -import { execFileSync, spawn } from "child_process"; +import { execFileSync } from "child_process"; import { glob } from "glob"; const ROOT_DIR = path.resolve(import.meta.dirname, "../..");