Arbitrary command injection in embano1/wip
Description
embano1/wip is a GitHub Action written in Bash. Prior to version 2, the embano1/wip action uses the github.event.pull_request.title parameter in an insecure way. The title parameter is used in a run statement - resulting in a command injection vulnerability due to string interpolation. This vulnerability can be triggered by any user on GitHub. They just need to create a pull request with a commit message containing an exploit. (Note that first-time PR requests will not be run - but the attacker can submit a valid PR before submitting an invalid PR). The commit can be genuine, but the commit message can be malicious. This can be used to execute code on the GitHub runners and can be used to exfiltrate any secrets used in the CI pipeline, including repository tokens. Version 2 has a fix for this issue.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
embano1/wipGitHub Actions | < 2 | 2 |
Affected products
1Patches
1c25450f77ed0fix: Shell escaping issue
3 files changed · +47 −15
action.yml+33 −5 modified@@ -13,23 +13,51 @@ inputs: required: true # starts with zero or more leading whitespace chars, WIP and zero or more colons default: "^[[:space:]]*(WIP)+(:)*" + debug: + description: "Enable verbose logging" + required: false + default: "false" runs: using: "composite" steps: - shell: bash + env: + TITLE: ${{ inputs.title }} + REGEX: ${{ inputs.regex }} + DEBUG: ${{ inputs.debug }} run: | - set -ex + set -e + if [[ ${DEBUG} == "true" ]]; then + echo "Enabling debug output" + set -x + fi + # TODO (@mgasch): make configurable # case-insensitive shopt -s nocasematch - - if [[ '${{ inputs.title }}' =~ ${{ inputs.regex }} ]]; then + + if [[ -z ${TITLE} ]]; then + echo "::error::title input must be set"; + exit 1 + fi + + if [[ -z ${REGEX} ]]; then + echo "::error::regex input must be set"; + exit 1 + fi + + if [[ ${TITLE} =~ ${REGEX} ]]; then echo "::error::Title marked as work in progress" exit 1 else - echo "::debug::Title not marked as work in progress" + echo "Title not marked as work in progress" fi - + # unset nocasematch option shopt -u nocasematch + + if [[ ${DEBUG} == "true" ]]; then + echo "Disabling debug output" + set +x + fi
.github/workflows/check-wip.yaml+3 −1 modified@@ -9,4 +9,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Check WIP in PR Title - uses: embano1/wip@v1 \ No newline at end of file + uses: embano1/wip@v2 + env: + TITLE: ${{ github.event.pull_request.title }} \ No newline at end of file
README.md+11 −9 modified@@ -7,6 +7,8 @@ work-in-progress ("WIP") patterns using regular expressions in `BASH`. ## Simple with Defaults +Uses `^[[:space:]]*(WIP)+(:)*` regex pattern to match against the PR title. + ```yaml name: Check "WIP" in PR Title @@ -19,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check WIP in PR Title - uses: embano1/wip@v1 + uses: embano1/wip@v2 ``` ## Custom Options @@ -36,22 +38,22 @@ jobs: runs-on: ubuntu-latest steps: - name: Check WIP in PR Title - uses: embano1/wip@v1 + uses: embano1/wip@v2 with: # this is also the default value title: "${{ github.event.pull_request.title }}" - # only matches PRs where title is "WIP" only + # only matches PRs where title is exactly "WIP" regex: "^WIP$" ``` ## Configuration Options -| Input | Type | Required | Default | Description | -|---------|----------|----------|------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `title` | `string` | yes | `${{ github.event.pull_request.title }}` | The title to perform regular expression pattern matching against. Typically a field from the Github [`context`](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) is used. | -| `regex` | `string` | yes | `^[[:space:]]*(WIP)+(:)*` | The regular expression to perform. The default value matches the word `WIP` (optionally followed by `:`) and ignores any whitespace character(s) at the beginning of the text | +| Input | Type | Required | Default | Description | +|---------|----------|----------|------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `title` | `string` | yes | `${{ github.event.pull_request.title }}` | The title to perform regular expression pattern matching against. Typically a field from the Github [`context`](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) is used. | +| `regex` | `string` | yes | `^[[:space:]]*(WIP)+(:)*` | The regular expression to perform. The default value matches the word `WIP` (optionally followed by `:`) and ignores any whitespace character(s) at the beginning of the text. | -⚠️ Currently regular expression pattern matching is **case-insensitive**, i.e. -`wip` would also match. \ No newline at end of file +> **Note** +> Currently regular expression pattern matching is **case-insensitive**, i.e., `wip` would also match. \ No newline at end of file
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-rg3q-prf8-qxmpghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-30623ghsaADVISORY
- github.com/embano1/wip/commit/c25450f77ed02c20d00b76ee3b33ff43838739a2ghsax_refsource_MISCWEB
- github.com/embano1/wip/security/advisories/GHSA-rg3q-prf8-qxmpghsax_refsource_CONFIRMWEB
- securitylab.github.com/research/github-actions-untrusted-inputghsaWEB
- securitylab.github.com/research/github-actions-untrusted-input/mitrex_refsource_MISC
News mentions
0No linked articles in our index yet.