feat: add Express API changelog generation#319
Conversation
Parameterize api-diff.js to accept custom input/output paths via CLI args. Update generate-release workflow to diff both Platform and Express specs and combine release descriptions under section headers. Ticket: DX-3144 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
||
| // Run the script with custom input/output paths | ||
| execSync( | ||
| `node scripts/api-diff.js ${path.join(scenarioDir, 'previous.json')} ${path.join(scenarioDir, 'current.json')} custom-output.md` |
Check warning
Code scanning / CodeQL
Shell command built from environment values Medium test
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 5 days ago
In general, the best way to fix this kind of issue is to avoid building a single shell command string that is interpreted by a shell. Instead, call the program directly and pass arguments as an array to execFileSync/spawn or use the argument-array form of execSync, so the Node runtime handles argument escaping and no shell interpretation occurs.
For this specific test, we should change the vulnerable execSync call on line 53 to use the options form: execSync(command, options) with shell: false and args represented explicitly. Since we already import execSync from child_process, and execSync supports an array via its args in child_process.execFileSync but not in execSync, the more direct and clearer fix here is to switch this one call to execFileSync, which takes (file, args[, options]) and does not invoke a shell. That keeps behavior the same (running node scripts/api-diff.js with three CLI arguments) while safely handling any special characters in paths.
Concretely:
- Add
execFileSyncto the destructured import fromchild_processat the top oftests/generate-release.test.js. - Replace the interpolated-string
execSynccall in the "supports custom file paths via CLI args" test with anexecFileSynccall:execFileSync('node', ['scripts/api-diff.js', path.join(...), path.join(...), 'custom-output.md']);. - Leave the earlier
execSync('node scripts/api-diff.js');alone, since it uses only hard-coded literals and is not part of the tainted flow.
No new helper methods are needed; just the additional import and the changed call.
| @@ -1,6 +1,6 @@ | ||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
| const { execSync } = require('child_process'); | ||
| const { execSync, execFileSync } = require('child_process'); | ||
| const { describe, it, beforeEach, afterEach } = require('node:test'); | ||
| const assert = require('node:assert'); | ||
|
|
||
| @@ -49,9 +49,12 @@ | ||
| const scenarioDir = path.join(FIXTURES_DIR, 'new-route-and-method'); | ||
|
|
||
| // Run the script with custom input/output paths | ||
| execSync( | ||
| `node scripts/api-diff.js ${path.join(scenarioDir, 'previous.json')} ${path.join(scenarioDir, 'current.json')} custom-output.md` | ||
| ); | ||
| execFileSync('node', [ | ||
| 'scripts/api-diff.js', | ||
| path.join(scenarioDir, 'previous.json'), | ||
| path.join(scenarioDir, 'current.json'), | ||
| 'custom-output.md', | ||
| ]); | ||
|
|
||
| const actual = fs.readFileSync('custom-output.md', 'utf8').trim(); | ||
| const expected = fs.readFileSync( |
Parameterize api-diff.js to accept custom input/output paths via CLI args. Update generate-release workflow to diff both Platform and Express specs and combine release descriptions under section headers.
Ticket: DX-3144