chore(structure): Remove redundant projectRoot arg#1386
Conversation
✅ Deploy Preview for cedarjs canceled.
|
| '--root', | ||
| getPaths().base, | ||
| ] | ||
| const scriptArgs = [path.join(__dirname, 'scripts', 'invoke.js'), ...args] |
Check warning
Code scanning / CodeQL
Unsafe shell command constructed from library input Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 1 day ago
In general, the fix is to avoid passing untrusted or library-controlled input through the shell. With Node’s child_process.spawn, this means not combining user-controlled strings into a single command string when shell: true. Instead, either (a) disable shell: true and pass a command plus an array of arguments, or (b) if shell: true is truly required (for pipes, redirects, etc.), then robustly escape any dynamic segments before interpolation.
Here, we don’t actually need shell features: we just want to execute node <invoke.js> ...args. The clean fix is:
- Use the same safe
spawn(process.execPath, scriptArgs, spawnOptions)call path on all platforms, including Windows. - Remove
shell: truefrom the WindowsspawnOptions. That eliminates shell interpretation entirely, making special characters in telemetry payloads harmless. - Keep the rest of the behavior (stdio, detached/windowsHide flags) unchanged as far as possible.
Concretely, in packages/telemetry/src/telemetry.ts:
- In the Windows branch of
spawnOptions, setshell: false(or just remove the property; by default it isfalse). - Remove the special Windows handling that builds a command string:
- Delete
const execPath = .... - Remove the
if (isWindows) { ... } else { ... }conditional. - Replace it with a single
spawn(process.execPath, scriptArgs, spawnOptions).unref()call that runs on all platforms.
- Delete
No other files need modification, since the issue arises only from this use of spawn with shell: true and a concatenated command string.
| @@ -7,7 +7,6 @@ | ||
| // "os.type()" returns 'Windows_NT' on Windows. | ||
| // See https://nodejs.org/docs/latest-v12.x/api/os.html#os_os_type. | ||
| const isWindows = os.type() === 'Windows_NT' | ||
| const execPath = isWindows ? `"${process.execPath}"` : process.execPath | ||
|
|
||
| const spawnOptions: Partial<SpawnOptions> = isWindows | ||
| ? { | ||
| @@ -18,7 +17,6 @@ | ||
| // See https://github.com/nodejs/node/issues/21825#issuecomment-503766781 for information | ||
| detached: false, | ||
| windowsHide: false, | ||
| shell: true, | ||
| } | ||
| : { | ||
| stdio: process.env.REDWOOD_VERBOSE_TELEMETRY | ||
| @@ -30,14 +28,8 @@ | ||
|
|
||
| const scriptArgs = [path.join(__dirname, 'scripts', 'invoke.js'), ...args] | ||
|
|
||
| if (isWindows) { | ||
| // Use command string with empty args array to avoid DEP0190 warning when | ||
| // `shell: true` | ||
| spawn([execPath, ...scriptArgs].join(' '), [], spawnOptions).unref() | ||
| } else { | ||
| // Use proper args array when no shell needed | ||
| spawn(process.execPath, scriptArgs, spawnOptions).unref() | ||
| } | ||
| // Use proper args array so no shell interpretation occurs on any platform | ||
| spawn(process.execPath, scriptArgs, spawnOptions).unref() | ||
| } | ||
|
|
||
| // wrap a function in this call to get a telemetry hit including how long it took |
|
| Command | Status | Duration | Result |
|---|---|---|---|
nx run-many -t build:pack --exclude create-ceda... |
✅ Succeeded | 8s | View ↗ |
nx run-many -t test --minWorkers=1 --maxWorkers=4 |
✅ Succeeded | 1m 35s | View ↗ |
nx run-many -t build |
✅ Succeeded | 7s | View ↗ |
nx run-many -t test:types |
✅ Succeeded | 11s | View ↗ |
☁️ Nx Cloud last updated this comment at 2026-03-17 14:44:46 UTC
Greptile SummaryThis PR removes the redundant Key changes:
Confidence Score: 3/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["Callers\n(routes.ts, entries.ts,\ndetection.ts, sendTelemetry.ts)"] -->|"getProject()\nno args"| B["getProject()\npackages/structure/src/index.ts"]
B --> C["new RWProject()"]
C --> D["RWProject.pathHelper\n@lazy getPaths()"]
D --> E["CEDAR_CWD env var\n/ process.cwd()"]
F["CLI check.ts"] -->|"printDiagnostics(getPaths().base, opts)\nOLD signature ❌"| G["printDiagnostics(opts?)\nNEW signature"]
G --> D
style F fill:#ff9999
style G fill:#ffe599
|
|
@greptileai please do a full review again |
|
@greptileai do a full review again please |
|
The changes in this PR are now available on npm. Try them out by running |

We only ever passed
getPaths().baseas the argument, which is exactly what the default is. So no need to keep it.This also simplified the implementation for #1337 because it can also rely on just the default .base dir