CVE-2026-44723
Description
Vowpal Wabbit is a machine learning system. The workflow .github/workflows/python_checks.yml embeds ${{ github.event.pull_request.title }} directly inside double-quoted bash strings in four separate steps across four jobs, each passing it as a CLI argument to the Python test script run_tests_model_gen_and_load.py. The shell interprets the expanded string before invoking Python, allowing an attacker to break out of the quotes and execute arbitrary commands on the runner. The pull_request trigger fires on PRs targeting any branch (branches: ['*']), with no additional access gate. This vulnerability is fixed by the 998e390e80a7e8192d7849b7784bc113dbd190ad commit.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Shell injection in Vowpal Wabbit's CI workflow allows arbitrary command execution via crafted PR title; fixed by commit 998e390.
Vulnerability
The vulnerability exists in the .github/workflows/python_checks.yml file of the Vowpal Wabbit repository. The workflow uses ${{ github.event.pull_request.title }} directly inside double-quoted bash strings in four separate steps across four jobs, allowing shell injection. The pull_request trigger fires on PRs targeting any branch (branches: ['*']) with no additional access gate. Affected versions include all before the fix commit 998e390e80a7e8192d7849b7784bc113dbd190ad [1][2].
Exploitation
An attacker can create a pull request with a crafted title containing shell metacharacters (e.g., ", $(...), ` `) to break out of the double-quoted string and execute arbitrary commands on the GitHub Actions runner. The injection occurs when the value is passed as a CLI argument to run_tests_model_gen_and_load.py`. No special permissions are required; any user who can create a PR targeting any branch can trigger the workflow [1].
Impact
Successful exploitation allows arbitrary command execution on the CI runner. An attacker could exfiltrate secrets (e.g., repository tokens, credentials) stored in the CI environment, modify repository contents, or perform other malicious actions within the context of the GitHub Actions workflow. However, this vulnerability has no runtime effect on consumers of Vowpal Wabbit artifacts (PyPI, NuGet, etc.) [1].
Mitigation
The vulnerability is fixed by commit 998e390e80a7e8192d7849b7784bc113dbd190ad, which binds the PR title to an environment variable PR_TITLE and references it as "$PR_TITLE" in the script, preventing shell injection [2]. No workaround is available except applying the fix. The advisory notes that this is only a CI configuration issue and does not affect released artifacts [1].
AI Insight generated on May 26, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2(expand)+ 1 more
- (no CPE)
- (no CPE)
Patches
1998e390e80a7Merge commit from fork
1 file changed · +12 −4
.github/workflows/python_checks.yml+12 −4 modified@@ -111,6 +111,8 @@ jobs: sudo apt-get install -y python3-pip - name: Generate models shell: bash + env: + PR_TITLE: ${{ github.event.pull_request.title }} run: | set -x python3 -m pip install setuptools wheel @@ -119,7 +121,7 @@ jobs: echo "=== Verifying vowpalwabbit import ===" python3 -c "import vowpalwabbit; print('vowpalwabbit imported successfully')" echo "=== Running model generation script ===" - python3 ./test/run_tests_model_gen_and_load.py --generate_models --skip_pr_tests "${{ github.event.pull_request.title }}" || (echo "Model generation failed with exit code $?" && exit 1) + python3 ./test/run_tests_model_gen_and_load.py --generate_models --skip_pr_tests "$PR_TITLE" || (echo "Model generation failed with exit code $?" && exit 1) echo "=== Checking generated files ===" ls -la ~/.vw_runtests_model_gen_working_dir/ || echo "Working directory not found" - name: Copy generated files to workspace @@ -172,11 +174,13 @@ jobs: path: master_wheel - name: Test loading models with master shell: bash + env: + PR_TITLE: ${{ github.event.pull_request.title }} run: | mv .vw_runtests_model_gen_working_dir ~ python3 -m pip install setuptools wheel python3 -m pip install master_wheel/*.whl - python3 ./test/run_tests_model_gen_and_load.py --load_models --skip_missing_args --skip_pr_tests "${{ github.event.pull_request.title }}" + python3 ./test/run_tests_model_gen_and_load.py --load_models --skip_missing_args --skip_pr_tests "$PR_TITLE" backward-generate: name: Generate models from master code @@ -198,6 +202,8 @@ jobs: sudo apt-get install -y libboost-test-dev - name: Generate models shell: bash + env: + PR_TITLE: ${{ github.event.pull_request.title }} run: | set -x pip install setuptools wheel @@ -206,7 +212,7 @@ jobs: echo "=== Verifying vowpalwabbit import ===" python -c "import vowpalwabbit; print('vowpalwabbit imported successfully')" echo "=== Running model generation script ===" - python ./test/run_tests_model_gen_and_load.py --generate_models --skip_missing_args --skip_pr_tests "${{ github.event.pull_request.title }}" || (echo "Model generation failed with exit code $?" && exit 1) + python ./test/run_tests_model_gen_and_load.py --generate_models --skip_missing_args --skip_pr_tests "$PR_TITLE" || (echo "Model generation failed with exit code $?" && exit 1) echo "=== Checking generated files ===" ls -la ~/.vw_runtests_model_gen_working_dir/ || echo "Working directory not found" - name: Copy generated files to workspace @@ -255,11 +261,13 @@ jobs: path: current_wheel - name: Test loading models with current code shell: bash + env: + PR_TITLE: ${{ github.event.pull_request.title }} run: | mv .vw_runtests_model_gen_working_dir ~ python3 -m pip install setuptools wheel python3 -m pip install current_wheel/*.whl - python3 ./test/run_tests_model_gen_and_load.py --load_models --skip_pr_tests "${{ github.event.pull_request.title }}" + python3 ./test/run_tests_model_gen_and_load.py --load_models --skip_pr_tests "$PR_TITLE" # --- Type checking ---
Vulnerability mechanics
Synthesis attempt was rejected by the grounding validator. Re-run pending.
References
2News mentions
0No linked articles in our index yet.