Skip to content

fix(security): prevent OS command injection in os-dependentLibraries (VULN-87310)#2066

Merged
kkedziak-splunk merged 14 commits into
developfrom
user/kkedziak/fix-vuln-87310
Jul 1, 2026
Merged

fix(security): prevent OS command injection in os-dependentLibraries (VULN-87310)#2066
kkedziak-splunk merged 14 commits into
developfrom
user/kkedziak/fix-vuln-87310

Conversation

@kkedziak-splunk

Copy link
Copy Markdown
Contributor

Issue number: VULN-87310

PR Type

What kind of change does this PR introduce?

  • Feature
  • Bug Fix
  • Refactoring (no functional or API changes)
  • Documentation Update
  • Maintenance (dependency updates, CI, etc.)

Summary

Changes

Fixes the OS command injection vulnerability reported through the Splunk Bug
Bounty Program (VULN-87310, CVSS 8.8 / SEC_HIGH).

install_python_libraries.install_os_dependent_libraries interpolated the
os-dependentLibraries[] fields (platform, python_version, name,
version, target) from globalConfig.json directly into a single pip
command string, which was then executed via subprocess.run(..., shell=True).
The reporter demonstrated arbitrary command execution on the build host by
injecting $(id > /tmp/UCC_PWNED) via globalConfig.json on ucc-gen 6.5.0.

This PR removes shell=True everywhere in install_python_libraries.py and
refactors every caller to pass subprocess.run an argv list[str]:

  • _subprocess_run now requires list[str]; the shell=True argument is
    gone. Values that originate from globalConfig.json are passed as discrete
    argv tokens, so shell metacharacters in any of them cannot break out of the
    intended command.
  • _pip_install, _pip_is_lib_installed, install_libraries, and
    install_os_dependent_libraries build the pip invocation as a list. The
    user-supplied pip_custom_flag is split with shlex.split so it still
    accepts multi-flag strings from ucc-gen build.
  • Existing tests updated for the new argv contract. A new parametrised
    regression test (test_install_os_dependent_libraries_does_not_invoke_shell)
    iterates over every injectable field and a representative set of shell
    metacharacter payloads — including the reporter's $(id > /tmp/UCC_PWNED)
    — and asserts that (1) no call uses shell=True and (2) the injected
    payload survives intact as a single literal argv token, proving the sink
    no longer interprets it.

User experience

No user-visible change for valid globalConfig.json inputs. Building an
add-on with values containing shell metacharacters used to execute arbitrary
commands on the build host; pip now simply receives those values as literal
arguments and fails with a normal "no matching distribution" style error.

Checklist

Review

  • self-review - I have performed a self-review of this change according to the development guidelines
  • Changes are documented. The documentation is understandable, examples work (more info)
  • PR title and description follows the contributing principles
  • meeting - I have scheduled a meeting or recorded a demo to explain these changes (if there is a video, put a link below and in the ticket)

Tests

See the testing doc.

  • Unit - tests have been added/modified to cover the changes
  • Smoke - tests have been added/modified to cover the changes
  • UI - tests have been added/modified to cover the changes
  • coverage - I have checked the code coverage of my changes (see more)

Demo/meeting:

Reviewers are encouraged to request meetings or demos if any part of the change is unclear

…(VULN-87310)

`install_python_libraries.py` interpolated `os-dependentLibraries[]` fields
(`platform`, `python_version`, `name`, `version`, `target`) from
`globalConfig.json` directly into a `pip` command string that was then run with
`subprocess.run(..., shell=True)`. An attacker who could influence
`globalConfig.json` (e.g. via a pull request to an add-on repo whose CI runs
`ucc-gen build`, or via a malicious third-party add-on) could execute arbitrary
commands on the build host.

Refactor every helper that invokes `subprocess.run` to pass an argv `list[str]`
without `shell=True`. Values from `globalConfig.json` are now passed as
discrete argv tokens, so shell metacharacters in any of them cannot break out
of the intended command. A parametrised regression test asserts that no call
uses `shell=True` and that injected payloads survive as literal argv tokens
for every injectable field and a representative set of shell metacharacters.

Co-Authored-By: Claude <noreply@anthropic.com>
@kkedziak-splunk
kkedziak-splunk marked this pull request as ready for review June 30, 2026 11:08
@kkedziak-splunk
kkedziak-splunk requested review from a team as code owners June 30, 2026 11:08
@kkedziak-splunk
kkedziak-splunk enabled auto-merge (squash) June 30, 2026 13:32
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

Code Coverage 🎉

Type PR Develop Change Status
Line Coverage 94.37% 94.35% 0.01% 🟢 Increased
Branch Coverage 90.71% 90.66% 0.05% 🟢 Increased

@kkedziak-splunk
kkedziak-splunk merged commit fc869e9 into develop Jul 1, 2026
91 of 92 checks passed
@kkedziak-splunk
kkedziak-splunk deleted the user/kkedziak/fix-vuln-87310 branch July 1, 2026 09:41
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 1, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants