{
  "ticket_id": "CVE-2026-25244",
  "code_root": "external/webdriverio",
  "source": {
    "type": "cve",
    "cve_id": "CVE-2026-25244",
    "advisory_id": "GHSA-5c46-x3qw-q7j7",
    "advisory_url": "https://github.com/advisories/GHSA-5c46-x3qw-q7j7",
    "vendor": "webdriverio",
    "product": "@wdio/browserstack-service",
    "repo": "https://github.com/webdriverio/webdriverio"
  },
  "facts": {
    "cve_id": "CVE-2026-25244",
    "advisory_id": "GHSA-5c46-x3qw-q7j7",
    "issue_summary": "OS command injection in @wdio/browserstack-service (part of the webdriverio monorepo). The helper getGitMetadataForAISelection() collects git metadata for BrowserStack AI test selection. It interpolates the current git branch name directly into a shell command string passed to child_process.execSync() without sanitization or argument escaping. A repository whose checked-out branch name contains shell metacharacters (backticks, $(), ;, |, &) causes the embedded payload to be executed by the shell when the service runs the helper, yielding arbitrary OS command execution.",
    "vulnerability_type": "OS Command Injection (CWE-78) leading to Remote Code Execution",
    "suspected_cwe": ["CWE-78"],
    "affected_versions": "@wdio/browserstack-service <= 9.23.2 (webdriverio < 9.24.0)",
    "fixed_versions": ["9.24.0"],
    "reproduce_version": "9.23.2",
    "verify_fixed_version": "9.24.0",
    "repo_url": "https://github.com/webdriverio/webdriverio.git",
    "code_root": "external/webdriverio",
    "ecosystem": "npm",
    "package": "@wdio/browserstack-service",
    "affected_functions": ["getGitMetadataForAISelection"],
    "install_recipe": "In a scratch directory run `npm install @wdio/browserstack-service@9.23.2` (vulnerable) or `npm install @wdio/browserstack-service@9.24.0` (fixed). The published npm tarballs are the canonical artifacts; the webdriverio monorepo git tags v9.23.2 / v9.24.0 are equivalent (the package lives under packages/wdio-browserstack-service/).",
    "attacker_access": "An attacker who controls the name of the git branch checked out in the working directory where the BrowserStack service runs. This is realistic in CI when a pull request branch name (attacker-controlled) is checked out, or when a malicious repository / branch is cloned by an automation pipeline.",
    "exploit_outline": "1. Create a git repository. 2. Create and check out a branch whose name embeds a shell payload, e.g. a branch name containing `$(touch /tmp/pwned)` or `;touch /tmp/pwned;`. 3. From inside that repository, invoke the code path that calls getGitMetadataForAISelection(). The branch name is interpolated into the execSync() command string; the shell evaluates the metacharacters and runs the payload.",
    "vulnerable_indicator": "On @wdio/browserstack-service@9.23.2 the injected command runs as a side effect: the marker file /tmp/pwned is created (the payload executed).",
    "fixed_indicator": "On @wdio/browserstack-service@9.24.0 the branch name is sanitized / passed safely so the shell metacharacters are not evaluated: no marker file is created, the payload does not execute.",
    "reproduction_requirements": "Node.js (any maintained LTS), git, and the @wdio/browserstack-service package at the specified version. No live BrowserStack account, network service, or browser is required - the command-injection sink is reached locally when the git-metadata helper runs against a malicious branch name. The difference is observable purely on the local filesystem (marker file created vs not).",
    "notes": "The vulnerable sink is the git branch name interpolated into an execSync() shell command inside getGitMetadataForAISelection(). The repro agent should read `git diff` between the v9.23.2 and v9.24.0 tags (or compare the two npm tarballs) under packages/wdio-browserstack-service/ to confirm the exact sink and the sanitization added in 9.24.0. The PoC must use a branch name containing shell metacharacters so the payload runs on 9.23.2 and is neutralized on 9.24.0."
  }
}
