Skip to content

Security: Skip config resolution in untrusted workspaces#3972

Merged
ntotten merged 2 commits intomainfrom
fix/untrusted-workspace-config-execution
Mar 16, 2026
Merged

Security: Skip config resolution in untrusted workspaces#3972
ntotten merged 2 commits intomainfrom
fix/untrusted-workspace-config-execution

Conversation

@ntotten
Copy link
Member

@ntotten ntotten commented Mar 16, 2026

Summary

  • Fixes a security vulnerability (CVSS 7.8) where Prettier's config resolution could execute JavaScript config files (.prettierrc.js, prettier.config.js, .prettierrc.cjs) in untrusted workspaces, bypassing workspace trust protections
  • Adds a workspace.isTrusted guard at the top of resolveConfig() in ModuleResolverNode.ts that returns null (use Prettier defaults) when the workspace is untrusted
  • This single guard covers both vulnerable call paths: the formatting path (format()getResolvedConfig()resolveConfig()) and the plugin discovery path (getSelectors()resolveConfig())

Security Details

When a workspace is untrusted, getPrettierInstance() correctly forces the bundled Prettier. However, resolveConfig() still called Prettier's resolveConfigFile()/resolveConfig(), which internally require()/import() JavaScript config files — allowing arbitrary code execution in the extension host with the user's privileges.

Reported by Hector Ruiz Ruiz (discovered 10/12/2025).

Test plan

  • Verify npm run compile succeeds
  • Verify npm test passes with no regressions
  • Manual test: create a workspace with a .prettierrc.cjs containing a side-effect (e.g., require('fs').writeFileSync('/tmp/test-vuln', 'executed')), open it as untrusted, format a file, confirm the side-effect does NOT occur
  • Verify formatting still works in trusted workspaces with JS config files

🤖 Generated with Claude Code

Prettier's resolveConfigFile/resolveConfig can require()/import()
JavaScript config files (.prettierrc.js, prettier.config.js, etc.),
allowing arbitrary code execution even when workspace trust restricted
module resolution to the bundled Prettier. Add a workspace.isTrusted
guard in resolveConfig() to skip config resolution entirely in
untrusted workspaces, returning null (Prettier defaults).

Reported by Hector Ruiz Ruiz.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 16, 2026 18:59
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens the Prettier VS Code extension against workspace trust bypasses by preventing Prettier config resolution from running in untrusted workspaces (avoiding execution of JavaScript-based config files during resolveConfig).

Changes:

  • Add an early workspace.isTrusted guard in ModuleResolverNode.resolveConfig() to skip config resolution and fall back to defaults.
  • Introduce a new log message constant explaining config resolution is skipped in untrusted workspaces.
  • Document the security fix in CHANGELOG.md.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/message.ts Adds a new message constant for logging when config resolution is skipped in untrusted workspaces.
src/ModuleResolverNode.ts Skips Prettier config resolution entirely when workspace.isTrusted is false to prevent JS config execution.
CHANGELOG.md Adds an Unreleased entry describing the security fix and its impact.

When requireConfig is true and the workspace is untrusted, return
"disabled" instead of null so formatting is correctly skipped rather
than proceeding with VS Code defaults.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ntotten ntotten merged commit a3f7317 into main Mar 16, 2026
13 checks passed
@ntotten ntotten deleted the fix/untrusted-workspace-config-execution branch March 16, 2026 19:09
@br3ndonland br3ndonland mentioned this pull request Mar 18, 2026
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants