Skip to content

CVE-2026-25244: Verified Repro With Script Download

CVE-2026-25244: @wdio/browserstack-service: OS command injection via crafted git branch name

CVE-2026-25244 is verified against @wdio/browserstack-service · npm. Affected versions: <= 9.23.2. Fixed in 9.24.0. Vulnerability class: RCE. This critical reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00143.

REPRO-2026-00143 @wdio/browserstack-service · npm RCE May 22, 2026 CVE entry ↗ .txt
Severity
CRITICAL
CVSS
9.8
Reproduced in
59m 49s
Tool calls
274
Spend
$2.75
01 · Overview

What Is CVE-2026-25244?

CVE-2026-25244 (GHSA-5c46-x3qw-q7j7) is a critical OS command injection vulnerability (CWE-78) in @wdio/browserstack-service, the BrowserStack integration for WebdriverIO, that allows arbitrary command execution via a crafted git branch name. Pruva reproduced it (reproduction REPRO-2026-00143).

02 · Severity & CVSS

CVE-2026-25244 Severity & CVSS Score

CVE-2026-25244 is rated critical severity, with a CVSS base score of 9.8 out of 10.

CRITICAL threat level
9.8 / 10 CVSS base
Weakness CWE-78 (OS Command Injection) — Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')

Critical — the most severe class — typically remotely exploitable with severe impact. Treat as an emergency.

03 · Affected Versions

Affected @wdio/browserstack-service Versions

@wdio/browserstack-service · npm versions <= 9.23.2 are affected.

How to Reproduce CVE-2026-25244

$ pruva-verify REPRO-2026-00143
or curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00143/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-25244

Reproduced by Pruva's autonomous agents — 274 tool calls over 1h 0m. Full root-cause analysis and the complete transcript are below.

How the agent worked 981 events · 274 tool calls · 1h 0m
1h 0mDuration
274Tool calls
235Reasoning steps
981Events
Agent activity over 1h 0m
Support
28
Repro
545
Variant
404
0:0059:49

Root Cause and Exploit Chain for CVE-2026-25244

Summary

CVE-2026-25244 is an OS command injection vulnerability (CWE-78) in @wdio/browserstack-service versions <= 9.23.2. The getGitMetadataForAISelection() function in packages/wdio-browserstack-service/src/testorchestration/helpers.ts interpolates git branch names and commit hashes directly into shell command strings passed to child_process.execSync(). Because git branch names can contain shell metacharacters (backticks, $(), ;, |, &), an attacker who controls a branch name (e.g., via a malicious pull request branch in CI/CD) can cause arbitrary OS command execution when the BrowserStack service runs the metadata helper.

Impact

  • Package: @wdio/browserstack-service (webdriverio monorepo)
  • Affected versions: <= 9.23.2
  • Fixed version: 9.24.0
  • Risk level: Critical (CVSS 9.8)
  • Consequences: Remote Code Execution (RCE) in CI/CD runners. Any pipeline that checks out an attacker-controlled branch and runs WebdriverIO with the BrowserStack service can be compromised.

Root Cause

The vulnerable code in getGitMetadataForAISelection() (v9.23.2) uses child_process.execSync() with JavaScript template literals to build git commands:

const changedFilesOutput = execSync(`git diff --name-only ${baseBranch}..${currentBranch}`).toString().trim()
const commitsOutput = execSync(`git log ${baseBranch}..${currentBranch} --pretty=%H`).toString().trim()

When currentBranch (or baseBranch / commit) contains shell metacharacters, execSync() passes the entire string to /bin/sh, which interprets the metacharacters and executes the embedded commands.

The fix (commit 0e6748ecd, v9.24.0) replaces execSync() with spawnSync('git', [args...]), which passes arguments directly to the git executable without shell interpretation. It also adds isValidGitRef() validation using a SAFE_GIT_REF_PATTERN regex (^[a-zA-Z0-9_./-]+$) to reject any ref containing dangerous characters before it reaches the command execution layer.

Reproduction Steps

The reproduction script is repro/reproduction_steps.sh. It performs the following:

  1. Clones the webdriverio repository and extracts helpers.ts from tags v9.23.2 (vulnerable) and v9.24.0 (fixed).
  2. Creates a mock @wdio/logger module so the TypeScript source compiles with tsx.
  3. Creates a dummy git repository for the test.
  4. Creates a fake git binary that returns a malicious branch name (master; touch <marker>) when asked for the current branch.
  5. Runs getGitMetadataForAISelection() from the vulnerable source with the fake git in PATH. The shell interprets the ; in the branch name and executes the injected touch command, creating the marker file.
  6. Runs getGitMetadataForAISelection() from the fixed source with the same fake git. The isValidGitRef() check rejects the malicious branch name and the function skips the folder, leaving the marker file absent.
  7. Prints a summary of code differences and test results.

Expected evidence:

  • Vulnerable run: marker file created (VULNERABLE: marker file was created by injected command!)
  • Fixed run: marker file NOT created (FIXED: marker file was NOT created.)

Evidence

Log files:

  • logs/vulnerable_output.log — output of running the vulnerable getGitMetadataForAISelection()
  • logs/fixed_output.log — output of running the fixed getGitMetadataForAISelection()

Key excerpts from vulnerable run (logs/vulnerable_output.log):

VULNERABLE: marker file was created by injected command!
  The shell interpreted metacharacters in the branch name
  and executed the embedded touch command.

Key excerpts from fixed run (logs/fixed_output.log):

[WARN] Invalid current branch name detected: master; touch /tmp/.../marker_fixed. Skipping this folder for security reasons.
Result: []

FIXED: marker file was NOT created.
  The sanitization (isValidGitRef + spawnSync) prevented
  shell metacharacters from being evaluated.

Code diff highlights (from repro/reproduction_steps.sh output):

Vulnerable (v9.23.2) - uses execSync with string interpolation:
204:  execSync(`git diff --name-only ${baseBranch}..${currentBranch}`)
209:  execSync(`git log ${baseBranch}..${currentBranch} --pretty=%H`)

Fixed (v9.24.0) - uses spawnSync with array arguments:
3:    import { spawnSync } from 'node:child_process'
29:   spawnSync('git', args, { ... })

Fixed (v9.24.0) - adds isValidGitRef validation:
15:   const SAFE_GIT_REF_PATTERN = /^[a-zA-Z0-9_./-]+$/
17:   function isValidGitRef(ref: string): boolean { ... }

Recommendations / Next Steps

  1. Upgrade immediately to @wdio/browserstack-service >= 9.24.0 (or webdriverio >= 9.24.0).
  2. Defense in depth: CI/CD pipelines should validate branch names before checking them out, especially for fork/PR builds.
  3. Code review: Audit any other execSync() usages in the webdriverio monorepo that interpolate user-controlled data into shell commands.
  4. Regression testing: Add unit tests that pass malicious branch names and commit hashes to getGitMetadataForAISelection() to ensure the validation regex catches future bypasses.

Additional Notes

  • Idempotency: The reproduction script was run twice consecutively and produced identical results both times.
  • No live BrowserStack account needed: The vulnerability is entirely in local git-metadata collection. The reproduction uses only Node.js, git, and tsx.
  • Edge case: The isValidGitRef() regex (^[a-zA-Z0-9_./-]+$) is restrictive but safe. It may reject unusual but legitimate branch names in rare cases (e.g., names containing @ or #), but this is an acceptable trade-off for preventing command injection.
  • Fix commit: https://github.com/webdriverio/webdriverio/commit/0e6748ecdb116f80495449a758d430201106dbcc

CVE-2026-25244 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:002:13
0:00
session startedaccounts/fireworks/models/kimi-k2p6 · cve-2026-25244 · cve-2026
0:04
0:05
0:08
0:09
web search
0:13
0:14
0:21
0:22
web search
0:25
0:29
1:23
1:23
extract_facts
no facts extracted
1:24
1:24
1:24
supportrepro
1:49
1:49
1:49
2:13
2:13

Artifacts and Evidence for CVE-2026-25244

Scripts, logs, diffs, and output captured during the reproduction.

No artifacts available

08 · How to Fix

How to Fix CVE-2026-25244

Upgrade @wdio/browserstack-service · npm to 9.24.0 or later.

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-25244 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-25244

How does the CVE-2026-25244 command injection exploit work?

Because git branch names can legally contain shell metacharacters (backticks, $(...), ;, |, &), an attacker who controls the checked-out branch name — such as a pull-request branch in CI — embeds a shell payload in the branch name. When getGitMetadataForAISelection() builds and runs its execSync() git commands, /bin/sh executes the embedded payload in the context of the process running the WebdriverIO test session, typically a CI runner.

Which @wdio/browserstack-service versions are affected by CVE-2026-25244, and where is it fixed?

Versions up to and including 9.23.2 are affected. It is fixed in 9.24.0.

How severe is CVE-2026-25244?

It is rated critical severity: any CI/CD pipeline that checks out an attacker-controlled branch and runs WebdriverIO with the BrowserStack service can have its runner compromised via remote code execution.

How can I reproduce CVE-2026-25244?

Download the verified script from this page and run it in an isolated environment against @wdio/browserstack-service <= 9.23.2. It checks out a git branch whose name contains shell metacharacters, runs the WebdriverIO test session with the BrowserStack service enabled, and shows the embedded payload executing via getGitMetadataForAISelection()'s execSync() calls.
11 · References

References for CVE-2026-25244

Authoritative sources for CVE-2026-25244 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.