Skip to content

Commit f05129b

Browse files
chrfalchclaude
andcommitted
fix(spm): harden shell usage + hashing flagged by CodeQL
- download-spm-artifacts.js: the tar/cp invocations interpolated URL/env-derived paths into shell strings (js/shell-command-injection, incl. one new critical on the companion backfill path). All four now use execFileSync argv form — no shell involved. - spm-pbxproj.js: generateUUID used md5 (js/weak-cryptographic-algorithm). Not a security use — the hash only derives deterministic pbxproj UUIDs — but sha256 (truncated to the same 24 hex chars) is just as deterministic and keeps the scanner green. Affects only not-yet- released injections; the marker records actual UUIDs so deinit of md5-era injections is unaffected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 19609e1 commit f05129b

2 files changed

Lines changed: 9 additions & 7 deletions

File tree

packages/react-native/scripts/spm/download-spm-artifacts.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const {
5858
makeLogger,
5959
sharedCacheDir,
6060
} = require('./spm-utils');
61-
const {execSync} = require('child_process');
61+
const {execFileSync} = require('child_process');
6262
const fs = require('fs');
6363
const path = require('path');
6464
const stream = require('stream');
@@ -595,7 +595,7 @@ function extractXCFramework(
595595
) /*: string */ {
596596
fs.mkdirSync(extractDir, {recursive: true});
597597
log(` Extracting ${path.basename(tarPath)}...`);
598-
execSync(`tar -xzf "${tarPath}" -C "${extractDir}"`, {stdio: 'pipe'});
598+
execFileSync('tar', ['-xzf', tarPath, '-C', extractDir], {stdio: 'pipe'});
599599

600600
const found = findFirst(extractDir, name => name.endsWith('.xcframework'), 8);
601601
if (found == null) {
@@ -660,7 +660,7 @@ function stageHermesHeaders(
660660
const dest = path.join(destRoot, 'hermes');
661661
fs.rmSync(dest, {recursive: true, force: true});
662662
fs.mkdirSync(destRoot, {recursive: true});
663-
execSync(`/bin/cp -R "${src}" "${dest}"`, {stdio: 'pipe'});
663+
execFileSync('/bin/cp', ['-R', src, dest], {stdio: 'pipe'});
664664
log(' Staged Hermes public headers → hermes-headers/hermes');
665665
}
666666

@@ -738,7 +738,7 @@ async function ensureCompanionStaged(
738738
fs.rmSync(tmp, {recursive: true, force: true});
739739
fs.mkdirSync(tmp, {recursive: true});
740740
try {
741-
execSync(`tar -xzf "${tarPath}" -C "${tmp}"`, {stdio: 'pipe'});
741+
execFileSync('tar', ['-xzf', tarPath, '-C', tmp], {stdio: 'pipe'});
742742
stageCompanionXcframework(tmp, outputDir, name);
743743
} finally {
744744
fs.rmSync(tmp, {recursive: true, force: true});
@@ -784,7 +784,7 @@ async function ensureHermesHeadersStaged(
784784
fs.rmSync(tmp, {recursive: true, force: true});
785785
fs.mkdirSync(tmp, {recursive: true});
786786
try {
787-
execSync(`tar -xzf "${tarPath}" -C "${tmp}"`, {stdio: 'pipe'});
787+
execFileSync('tar', ['-xzf', tarPath, '-C', tmp], {stdio: 'pipe'});
788788
stageHermesHeaders(tmp, outputDir);
789789
} finally {
790790
fs.rmSync(tmp, {recursive: true, force: true});

packages/react-native/scripts/spm/spm-pbxproj.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ const crypto = require('crypto');
1414

1515
/**
1616
* Generate a deterministic 24-hex-character UUID from a seed string.
17-
* Uses MD5 hash truncated to 24 chars (standard Xcode pbxproj UUID length).
17+
* SHA-256 truncated to 24 chars (standard Xcode pbxproj UUID length). Not a
18+
* security use — the hash only provides stable, collision-unlikely IDs — but
19+
* sha256 keeps static analysis (CodeQL weak-crypto) quiet.
1820
*/
1921
function generateUUID(seed /*: string */) /*: string */ {
2022
return crypto
21-
.createHash('md5')
23+
.createHash('sha256')
2224
.update(seed)
2325
.digest('hex')
2426
.substring(0, 24)

0 commit comments

Comments
 (0)