Skip to content

fix(codeRefs): replace exec() with execFile() to prevent command injection - #174

Merged
unwakuche-ld merged 4 commits into
mainfrom
fix/coderefs-command-injection
Sep 29, 2026
Merged

unwakuche-ld merged 4 commits into
mainfrom
fix/coderefs-command-injection

Conversation

@unwakuche-ld

@unwakuche-ld unwakuche-ld commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Here is a PR description that matches what the branch now ships. I have not applied it to the PR, since that is a remote action.

Summary

Fixes a command injection vulnerability in Code References alias generation (bug bounty report).

Vector: FlagAliases.generateCsv and FlagAliases.codeRefsVersionCheck in src/providers/codeRefs.ts built a single command string and ran it through child_process.exec, which spawns a shell. The string interpolated workspace-controlled values inside double quotes:

  • intConfig.project, from launchdarkly.project in a repo's .vscode/settings.json
  • directory, the workspace folder path (cloned folder name or a .code-workspace path)

A repository could therefore run arbitrary commands when opened, and the child process received the developer's LaunchDarkly session token via LD_ACCESS_TOKEN. Affects Linux, macOS ($(...)) and Windows (" + &)

Fix: invoke `ld-find-code-refsrgument array. No shell is
involved, so shell metacharacters in any argument are inert.

// before
exec(`${bin} --dir="${directory}" --projKey="${project}" ...`, options)
// after
execFile(bin, ['--dir', directory, '--projKey', project, ...], options)

IFlagAliases.exec in src/models.ts gets the same signature. --contextLines=-1 stays in = form
so the negative value is not parse

Release

Version bumped to 6.2.2 with a Security entry in the CHANGELOG.

Verification

- tsc, eslint and prettier pass.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> Fixes a **command injection** vulnerability in Code References alias generation by stopping use of shell-based `child_process.exec` when invoking `ld-find-code-refs`.
> 
> `FlagAliases` now uses **`execFile`** with a discrete argument array for `generateCsv` and `codeRefsVersionCheck`, so workspace-controlled values (`launchdarkly.project`, folder paths, etc.) are passed as argv and cannot inject shell metacharacters or exfiltrate `LD_ACCESS_TOKEN` from the child environment. **`IFlagAliases.exec`** is updated to match the new `(file, args, options)` signature.
> 
> Release **6.2.2** documents the security fix in the CHANGELOG.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit f356deb8551adc9b8289efb72a56f7ae3a78d258. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

…ction

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread package.json Outdated
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread src/providers/codeRefs.ts Outdated
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6bbadcf. Configure here.

Comment thread src/generalUtils.ts Outdated
await config.getAliases().start();
if (!workspace.isTrusted) {
config.getCtx().subscriptions.push(workspace.onDidGrantWorkspaceTrust(() => config.getAliases()?.start()));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trust handler gated on version check

Medium Severity

The onDidGrantWorkspaceTrust listener is nested under codeRefsVersionCheck(), which returns false when the workspace is untrusted. That call is not awaited, so the Promise is always truthy and the listener still registers. Awaiting the check would skip this recovery and show a false version error instead.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6bbadcf. Configure here.

Comment thread src/generalUtils.ts Outdated
await config.getAliases().start();
if (!workspace.isTrusted) {
config.getCtx().subscriptions.push(workspace.onDidGrantWorkspaceTrust(() => config.getAliases()?.start()));
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trust listener registered multiple times

Low Severity

setupComponents can run again while the workspace is still untrusted, for example after a session change or configure. Each run pushes another onDidGrantWorkspaceTrust listener. Granting trust then calls start() multiple times on the same FlagAliases instance and starts overlapping refresh intervals.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6bbadcf. Configure here.

@unwakuche-ld unwakuche-ld changed the title fix(codeRefs): replace exec() with execFile() to prevent command injection (CVE candidate) fix(codeRefs): replace exec() with execFile() to prevent command injection Sep 29, 2026
@unwakuche-ld unwakuche-ld changed the title fix(codeRefs): replace exec() with execFile() to prevent command injection fix(codeRefs): replace exec() with execFile() to prevent command injection Sep 29, 2026
The execFile() change fully remediates the reported command injection.
The Workspace Trust additions are removed because:

- Declaring untrustedWorkspaces "limited" widened exposure. Without a
  declaration VS Code disables the extension entirely in Restricted
  Mode. With "limited" the whole extension (auth session, API client,
  flag store, sign-in flow) activated in untrusted workspaces, with only
  the Code References paths gated.
- restrictedConfigurations was inert. VS Code only applies it to
  settings registered under contributes.configuration, and neither
  launchdarkly.project nor launchdarkly.codeRefsPath is registered.
- The workspace.isTrusted guards and onDidGrantWorkspaceTrust handler
  are dead code without the declaration: the extension never runs in an
  untrusted workspace, and VS Code activates it itself when trust is
  granted.

Also restores the unrelated CHANGELOG whitespace normalization and
narrows the 6.2.2 entry to the execFile fix.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@unwakuche-ld unwakuche-ld reopened this Sep 29, 2026
@unwakuche-ld
unwakuche-ld merged commit 6db2f02 into main Sep 29, 2026
7 checks passed
@unwakuche-ld
unwakuche-ld deleted the fix/coderefs-command-injection branch September 29, 2026 17:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants