Skip to content

Commit eaf06cd

Browse files
krukowCopilot
andauthored
fix: replace execSync with execFileSync in docs validation (#505)
* 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> * chore: remove unused spawn import Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent dea514d commit eaf06cd

File tree

1 file changed

+12
-13
lines changed

1 file changed

+12
-13
lines changed

scripts/docs-validation/validate.ts

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import * as fs from "fs";
77
import * as path from "path";
8-
import { execSync, spawn } from "child_process";
8+
import { execFileSync } from "child_process";
99
import { glob } from "glob";
1010

1111
const ROOT_DIR = path.resolve(import.meta.dirname, "../..");
@@ -76,7 +76,7 @@ async function validateTypeScript(): Promise<ValidationResult[]> {
7676
try {
7777
// Run tsc
7878
const tscPath = path.join(ROOT_DIR, "nodejs/node_modules/.bin/tsc");
79-
execSync(`${tscPath} --project ${tsconfigPath} 2>&1`, {
79+
execFileSync(tscPath, ["--project", tsconfigPath], {
8080
encoding: "utf-8",
8181
cwd: tsDir,
8282
});
@@ -98,10 +98,8 @@ async function validateTypeScript(): Promise<ValidationResult[]> {
9898
}
9999
} catch (err: any) {
100100
// Parse tsc output for errors
101-
const output = err.stdout || err.message || "";
101+
const output = err.stdout || err.stderr || err.message || "";
102102
const errorLines = output.split("\n");
103-
104-
// Group errors by file
105103
const fileErrors = new Map<string, string[]>();
106104
let currentFile = "";
107105

@@ -162,22 +160,23 @@ async function validatePython(): Promise<ValidationResult[]> {
162160

163161
// Syntax check with py_compile
164162
try {
165-
execSync(`python3 -m py_compile "${fullPath}" 2>&1`, {
163+
execFileSync("python3", ["-m", "py_compile", fullPath], {
166164
encoding: "utf-8",
167165
});
168166
} catch (err: any) {
169-
errors.push(err.stdout || err.message || "Syntax error");
167+
errors.push(err.stdout || err.stderr || err.message || "Syntax error");
170168
}
171169

172170
// Type check with mypy (if available)
173171
if (errors.length === 0) {
174172
try {
175-
execSync(
176-
`python3 -m mypy "${fullPath}" --ignore-missing-imports --no-error-summary 2>&1`,
173+
execFileSync(
174+
"python3",
175+
["-m", "mypy", fullPath, "--ignore-missing-imports", "--no-error-summary"],
177176
{ encoding: "utf-8" }
178177
);
179178
} catch (err: any) {
180-
const output = err.stdout || err.message || "";
179+
const output = err.stdout || err.stderr || err.message || "";
181180
// Filter out "Success" messages and notes
182181
const typeErrors = output
183182
.split("\n")
@@ -227,7 +226,7 @@ replace github.com/github/copilot-sdk/go => ${path.join(ROOT_DIR, "go")}
227226

228227
// Run go mod tidy to fetch dependencies
229228
try {
230-
execSync(`go mod tidy 2>&1`, {
229+
execFileSync("go", ["mod", "tidy"], {
231230
encoding: "utf-8",
232231
cwd: goDir,
233232
env: { ...process.env, GO111MODULE: "on" },
@@ -246,7 +245,7 @@ replace github.com/github/copilot-sdk/go => ${path.join(ROOT_DIR, "go")}
246245

247246
try {
248247
// Use go vet for syntax and basic checks
249-
execSync(`go build -o /dev/null "${fullPath}" 2>&1`, {
248+
execFileSync("go", ["build", "-o", "/dev/null", fullPath], {
250249
encoding: "utf-8",
251250
cwd: goDir,
252251
env: { ...process.env, GO111MODULE: "on" },
@@ -300,7 +299,7 @@ async function validateCSharp(): Promise<ValidationResult[]> {
300299

301300
// Compile all files together
302301
try {
303-
execSync(`dotnet build "${path.join(csDir, "DocsValidation.csproj")}" 2>&1`, {
302+
execFileSync("dotnet", ["build", path.join(csDir, "DocsValidation.csproj")], {
304303
encoding: "utf-8",
305304
cwd: csDir,
306305
});

0 commit comments

Comments
 (0)