Conversation
|
|
||
| console.log(textContent); | ||
|
|
||
| fs.writeFileSync("/tmp/version-bump-summary.json", jsonContent + "\n"); |
Check failure
Code scanning / CodeQL
Insecure temporary file High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 1 day ago
In general, to fix insecure temporary file usage, avoid hard-coded filenames in shared temp directories and instead use a library or API that (a) creates the file atomically, (b) ensures it does not already exist, and (c) sets secure permissions. For Node.js, the recommended approach is to use a library like tmp that handles these details safely.
For this specific file, we should replace the direct writes to /tmp/version-bump-summary.json and /tmp/version-bump-summary.txt with secure temporary files created using tmp. Since the rest of the script appears to assume only that the files exist and contain the expected content (and does not depend on specific paths), we can (1) create two secure temporary files with stable prefixes (for debugging clarity) using tmp.fileSync, (2) write the JSON and text content into those file descriptors or paths, and (3) optionally print the generated file paths to stdout so any downstream step can discover them if needed. This preserves functionality (files are written to a temp location) while making the file creation safe.
Concretely:
- Add
const tmp = require("tmp");near the top alongside otherrequirecalls. - Replace
fs.writeFileSync("/tmp/version-bump-summary.json", ...)with code that callstmp.fileSync({ prefix: "version-bump-summary-", postfix: ".json" }), then writes to the resulting.namepath. - Similarly, create a secure temp file for the text output with a
.txtpostfix. - Optionally, log the temp file paths so other tooling can read them, without changing core behavior.
All changes must be confined to .github/actions/version-bump-summary/index.js within the provided snippet.
| @@ -1,5 +1,6 @@ | ||
| const { execSync } = require("child_process"); | ||
| const fs = require("fs"); | ||
| const tmp = require("tmp"); | ||
|
|
||
| const ref = process.argv[2] || "HEAD"; | ||
|
|
||
| @@ -40,5 +41,17 @@ | ||
|
|
||
| console.log(textContent); | ||
|
|
||
| fs.writeFileSync("/tmp/version-bump-summary.json", jsonContent + "\n"); | ||
| fs.writeFileSync("/tmp/version-bump-summary.txt", textContent + "\n"); | ||
| const jsonTempFile = tmp.fileSync({ | ||
| prefix: "version-bump-summary-", | ||
| postfix: ".json", | ||
| }); | ||
| const textTempFile = tmp.fileSync({ | ||
| prefix: "version-bump-summary-", | ||
| postfix: ".txt", | ||
| }); | ||
|
|
||
| fs.writeFileSync(jsonTempFile.name, jsonContent + "\n"); | ||
| fs.writeFileSync(textTempFile.name, textContent + "\n"); | ||
|
|
||
| console.log(`JSON summary written to: ${jsonTempFile.name}`); | ||
| console.log(`Text summary written to: ${textTempFile.name}`); |
| console.log(textContent); | ||
|
|
||
| fs.writeFileSync("/tmp/version-bump-summary.json", jsonContent + "\n"); | ||
| fs.writeFileSync("/tmp/version-bump-summary.txt", textContent + "\n"); |
Check failure
Code scanning / CodeQL
Insecure temporary file High
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 1 day ago
In general, to fix insecure temp file issues, avoid writing to fixed filenames in shared temp directories. Instead, use a library such as tmp to create securely randomized temporary files/directories with appropriate permissions, or derive your own filenames inside a securely created temporary directory.
For this script, the best minimal-impact fix is to create a secure temporary directory using the tmp library and write these two output files into that directory, keeping the filenames (version-bump-summary.json / .txt) so any existing consumers that just care about file names within a known directory can still work, but now under a unique, private temp directory. Concretely:
- Add an import for
tmp. - Call
tmp.dirSync()once, capturing the generated directory path. - Use
path.join(tempDir, "version-bump-summary.json")andpath.join(tempDir, "version-bump-summary.txt")instead of the hard-coded/tmp/...paths.
We should also importpathsince it is not currently imported in this file and is a standard Node module.
All required changes are within .github/actions/version-bump-summary/index.js:
- Add
const tmp = require("tmp");andconst path = require("path");at the top. - After computing
jsonContentandtextContent, create a secure temp directory:const tempDir = tmp.dirSync({ unsafeCleanup: true }).name;. - Replace the two
fs.writeFileSync("/tmp/...")calls with calls that write intotempDirusingpath.join.
| @@ -1,5 +1,7 @@ | ||
| const { execSync } = require("child_process"); | ||
| const fs = require("fs"); | ||
| const path = require("path"); | ||
| const tmp = require("tmp"); | ||
|
|
||
| const ref = process.argv[2] || "HEAD"; | ||
|
|
||
| @@ -38,7 +40,9 @@ | ||
| }) | ||
| .join("\n"); | ||
|
|
||
| const tempDir = tmp.dirSync({ unsafeCleanup: true }).name; | ||
|
|
||
| console.log(textContent); | ||
|
|
||
| fs.writeFileSync("/tmp/version-bump-summary.json", jsonContent + "\n"); | ||
| fs.writeFileSync("/tmp/version-bump-summary.txt", textContent + "\n"); | ||
| fs.writeFileSync(path.join(tempDir, "version-bump-summary.json"), jsonContent + "\n"); | ||
| fs.writeFileSync(path.join(tempDir, "version-bump-summary.txt"), textContent + "\n"); |
|
|
||
| const ref = process.argv[2] || "HEAD"; | ||
|
|
||
| const newTags = execSync(`git tag --points-at ${ref}`) |
Check warning
Code scanning / CodeQL
Indirect uncontrolled command line Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 1 day ago
In general, the safest fix is to avoid passing concatenated strings to child_process.exec/execSync and instead use spawn/spawnSync/execFile/execFileSync with an argument array, which bypasses the shell and prevents shell metacharacters from being interpreted. Where input is already an array of arguments, pass it directly; where you receive a single string of arguments, parse it safely rather than simple string concatenation.
For this specific script, the best fix without changing functionality is:
- Replace the
execSynccall on line 6 that builds a single string`git tag --points-at ${ref}`with anexecFileSync(or equivalent) call that invokesgitdirectly and passes["tag", "--points-at", ref]as an argument array. This preserves the intendedgit tagbehavior while preventing shell interpretation ofref. - Since there is already a
require("child_process")destructuring import on line 1, either:- extend it to also pull in
execFileSync, or - refactor slightly to import the module and destructure both functions.
To minimize change, just addexecFileSyncto the existing destructuring.
- extend it to also pull in
- The other
execSyncon line 17 already quotespackageNameinside the command and is not using tainted input fromprocess.argv; CodeQL did not flag it, so we leave it unchanged per the instructions to avoid altering behavior unnecessarily.
Concretely, in .github/actions/version-bump-summary/index.js:
- Update line 1 to
const { execSync, execFileSync } = require("child_process");. - Replace the
execSynccall on line 6 withexecFileSync("git", ["tag", "--points-at", ref]).
No additional helper methods are needed beyond importing execFileSync.
| @@ -1,9 +1,9 @@ | ||
| const { execSync } = require("child_process"); | ||
| const { execSync, execFileSync } = require("child_process"); | ||
| const fs = require("fs"); | ||
|
|
||
| const ref = process.argv[2] || "HEAD"; | ||
|
|
||
| const newTags = execSync(`git tag --points-at ${ref}`) | ||
| const newTags = execFileSync("git", ["tag", "--points-at", ref]) | ||
| .toString() | ||
| .trim() | ||
| .split("\n") |
TICKET: VL-4566