NEW @W-23906075@ SF CLI - Automatic ESLint config import leads to RCE during code analyzer process - #501
Conversation
…tive config to prevent RCE
Auto-discovering an executable ESLint config (eslint.config.{js,cjs,mjs} or
legacy .eslintrc.{js,cjs}) caused its top-level JavaScript to execute during
analysis, an arbitrary code execution vector reachable from an untrusted
workspace when auto_discover_eslint_config is enabled.
Auto-discovery now applies only declarative config (.json/.yaml/.yml). An
executable config found by auto-discovery is skipped with a Warn. An explicitly
configured eslint_config_file may still be executable (trusted operator opt-in)
but emits a Warn that its top-level code will run.
Additive only: no exported symbols were removed or renamed.
…ative config to prevent RCE
Mirrors the eslint (flat) engine fix for the legacy ESLint v8 engine. Auto-
discovering an executable legacy config (.eslintrc.{js,cjs}) executed its top-
level JavaScript during analysis via ESLint's own .eslintrc tree-walk
(useEslintrc) and via overrideConfigFile.
Auto-discovery now applies only declarative legacy config (.json/.yaml/.yml):
an auto-discovered executable config is skipped, useEslintrc is disabled so
ESLint will not walk to it either, and a Warn is emitted. An explicitly
configured executable eslint_config_file is still applied (trusted operator
opt-in) but emits a Warn that its top-level code will run.
Additive only: no exported symbols were removed or renamed.
…os to satisfy ConfigValue type
|
Git2Gus App is installed but the |
aruntyagiTutu
left a comment
There was a problem hiding this comment.
Reviewed against the W-23906075 bug-bounty RCE finding (automatic ESLint config discovery executing attacker-controlled JS). Traced the fix beyond the diff to confirm the actual execution paths in both engines:
eslint-engine (ESLint 9 / flat config)
isExecutableConfigFile()classifies.js/.cjs/.mjsas executable (config.ts).UserConfigInfo.initIfNeeded()refuses to setuserConfigFilewhen an auto-discovered file is executable, emittingSkippedAutoDiscoveredExecutableConfigFileinstead.- Verified in
eslint-wrapper.tsthatcreateESLintOptionsalways setsoverrideConfigFile: true(disabling ESLint's own auto-detection) and only reachesdynamicallyImport()→await import(...)(the actual execution point) whenuserConfigFileis truthy. SinceuserConfigFileis leftundefinedfor skipped executable files, there's no path left that would execute them. Explicit opt-in (eslint_config_file) still works and now warns viaExplicitExecutableConfigFileWillExecute.
eslint8-engine (ESLint 8 / legacy config)
- Same executable/declarative split, correctly scoped to
.js/.cjsonly (no.mjs, sinceLEGACY_ESLINT_CONFIG_FILEShas no mjs variant — confirmed in config.ts). - The subtler risk here is that ESLint 8 does its own internal cascading
.eslintrc.*discovery viauseEslintrc, independent of this codebase's manual discovery — so just withholding the file path isn't enough. Confirmedstrategy.ts'sshouldUseEslintrc()correctly forcesuseEslintrc: falsewhenever agetSkippedExecutableConfigFile()is present, closing that secondary path. This is the right fix and it's easy to miss.
Tests: sentinel-file-based regression tests (writes a marker file only if the malicious config's top-level code runs) assert absence on auto-discovery and presence on explicit opt-in for both engines — a solid way to prove non-execution rather than just asserting on returned config shape. Existing tests were correctly rewired from relying on auto-discovery executing a config to requiring explicit opt-in, and new coverage for declarative auto-discovered configs (.eslintrc.yml etc.) confirms those still apply with no warning.
Architecture is sound in both engines, the ESLint-8-specific useEslintrc gap is correctly closed, and tests substantiate the fix with actual execution proof rather than config-shape assertions alone. No issues found.
Summary
Restricts ESLint's auto-discovery mechanism to declarative configuration only, preventing arbitrary executable config files from being automatically discovered and executed, thus eliminating RCE vector during code analyzer process.
GUS Ticket W-23906075 — [Bug Bounty / H1] SF CLI - Automatic ESLint config import leads to RCE during code analyzer process
Changes
Test Evidence
Dependencies
None