Skip to content

Commit 95bcc33

Browse files
varzagerclaude
andcommitted
fix: drop cpx and child-process-promise to clear vulnerable transitive deps
Both packages were only used by build/test tooling but pulled vulnerable transitive dependencies into the published package's runtime tree, which Dependabot flags for consumers: - cpx@1 -> chokidar@2 -> micromatch@3 -> braces@1.x/2.x (GHSA-grv7-fg5c-xmjg, no patch on the 1.x/2.x line) - child-process-promise@2 -> cross-spawn@4.0.2 (GHSA-3xgq-45jj-v275) Replace them with Node built-ins so both advisories are resolved at the source with zero new dependencies: - copy-templates: swap `cpx` for scripts/copy-templates.js, a small fs-based recursive copy of src/**/*.template.* into dist/. - generateReadme.ts / tests/driver.ts: swap child-process-promise for the built-in child_process module (util.promisify(exec) and a small spawn->Promise wrapper). - Remove cpx, child-process-promise, and @types/child-process-promise from package.json and regenerate yarn.lock. The only remaining braces/cross-spawn copies now come exclusively from devDependencies (eslint, lint-staged), are already patched (braces@3.0.3, cross-spawn@7.0.3), and are never installed by consumers of the published package. Surfaced by Dependabot in a downstream project consuming this package. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 59d0d0f commit 95bcc33

6 files changed

Lines changed: 60 additions & 1093 deletions

File tree

.eslintignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
__generated__
1+
__generated__
2+
scripts/copy-templates.js

package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@
1212
"pretest": "yarn run clean-generated && yarn run generate-for-type-tests && yarn run lint && yarn run typecheck && yarn run build",
1313
"test": "jest -i",
1414
"build": "tsc -p tsconfig.build.json && yarn copy-templates",
15-
"copy-templates": "cpx 'src/**/*.template.*' dist/",
15+
"copy-templates": "node scripts/copy-templates.js",
1616
"generate-readme": "ts-node scripts/generateReadme.ts"
1717
},
1818
"dependencies": {
1919
"@types/flat": "^5.0.2",
20-
"child-process-promise": "^2.2.1",
2120
"cosmiconfig": "^7.0.1",
22-
"cpx": "^1.5.0",
2321
"flat": "^5.0.2",
2422
"format-message-parse": "^6.2.4",
2523
"handlebars": "^4.7.7",
@@ -38,7 +36,6 @@
3836
},
3937
"devDependencies": {
4038
"@testing-library/react": "^12.1.0",
41-
"@types/child-process-promise": "^2.2.2",
4239
"@types/jest": "^27.0.1",
4340
"@types/react": "^17.0.21",
4441
"@typescript-eslint/eslint-plugin": "^4.32.0",

scripts/copy-templates.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env node
2+
// Copies template files (src/**/*.template.*) into dist/, preserving the
3+
// directory structure relative to src/. Replaces the previous `cpx` dependency,
4+
// which pulled in a vulnerable chokidar@2 -> micromatch@3 -> braces chain
5+
// (GHSA-grv7-fg5c-xmjg) with no patch available for the 1.x/2.x line.
6+
const fs = require('fs');
7+
const path = require('path');
8+
9+
const SRC_DIR = path.resolve(__dirname, '..', 'src');
10+
const DIST_DIR = path.resolve(__dirname, '..', 'dist');
11+
const TEMPLATE_RE = /\.template\.[^.]+$/;
12+
13+
function collectTemplates(dir) {
14+
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
15+
const fullPath = path.join(dir, entry.name);
16+
if (entry.isDirectory()) return collectTemplates(fullPath);
17+
return TEMPLATE_RE.test(entry.name) ? [fullPath] : [];
18+
});
19+
}
20+
21+
const templates = collectTemplates(SRC_DIR);
22+
23+
for (const srcPath of templates) {
24+
const relPath = path.relative(SRC_DIR, srcPath);
25+
const destPath = path.join(DIST_DIR, relPath);
26+
fs.mkdirSync(path.dirname(destPath), { recursive: true });
27+
fs.copyFileSync(srcPath, destPath);
28+
}
29+
30+
console.log(`copy-templates: ${templates.length} file(s) copied to dist/`);

scripts/generateReadme.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1+
import { exec as execCallback } from 'child_process';
12
import fs from 'fs';
23
import util from 'util';
34

4-
import { exec } from 'child-process-promise';
55
import Handlebars from 'handlebars';
66

77
import { Generator } from '../src/Generator';
88
import { DEFAULT_FN_NAME } from '../src/constants';
99

1010
const readFile = util.promisify(fs.readFile);
1111
const writeFile = util.promisify(fs.writeFile);
12+
const exec = util.promisify(execCallback);
1213

1314
void (async () => {
1415
const template = Handlebars.compile(

tests/driver.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
import { spawn as spawnProcess } from 'child_process';
12
import fs from 'fs';
23
import path from 'path';
34
import util from 'util';
4-
import { spawn } from 'child-process-promise';
55
import jsonStringify from 'fast-json-stable-stringify';
66
import { Generator } from '../src/Generator';
77
import { CliParams } from '../src/bin';
@@ -10,6 +10,26 @@ import { getFileExtension } from '../src/utils';
1010

1111
const readFile = util.promisify(fs.readFile);
1212

13+
const spawn = (
14+
command: string,
15+
args: string[],
16+
options: { cwd: string }
17+
): Promise<void> =>
18+
new Promise((resolve, reject) => {
19+
const child = spawnProcess(command, args, {
20+
...options,
21+
stdio: 'inherit',
22+
});
23+
child.on('error', reject);
24+
child.on('close', (code) => {
25+
if (code === 0) {
26+
resolve();
27+
} else {
28+
reject(new Error(`${command} exited with code ${code ?? 'null'}`));
29+
}
30+
});
31+
});
32+
1333
export class Driver {
1434
private cwd: string = process.cwd();
1535
private cliParams: Partial<CliParams> = {

0 commit comments

Comments
 (0)