Skip to content

🐛 [Bounty] - Vulnerable interpolation in IntersectMBO/govtool #4146

@Hornan7

Description

@Hornan7

Context

Received via the security mailbox. I’m logging it here so we have proper tracking in place.

The workflows label-bug-report.yml and label-feature-issue.yml of the
repo IntersectMBO/govtool have insecure interpolation of an attacker
controlled value on line 19.

Steps to reproduce

run:
echo "Hello, the path to this workflow is ${{ github.action_path }}"

If run, this code prints the path of the workflow's yaml file.
This is not always safe because the replacement is NOT language aware,
if action_path contains a quote it's allowed to break out of the string.
If action_path were to be file";touch "pwned.yml (yes, that is a valid
file name), the code would become

echo "Hello, the path to this workflow is file";touch "pwned.yml"

This would execute code controlled by whoever controls action_path: if
the attacker controls the value of any expression being interpolated
within code, they can run arbitrary code inside the workflow.

In this case the attacker controlled value is the issue title, the
attacker could create an issue with a title similar to:

this is the issue $(echo "pwned") title

and their code (in this case just an harmless echo) would execute in the
context of the action worker.

Actual behavior

The impact of this is minor since you have correctly given the
GITHUB_TOKEN a narrow scope (otherwise an attacker would have write
access to the entire repo).
Do note that "lateral" exploitation is possible too: if the workflow
exploited lacks a specific permission the attacker is after then they
can try to exploit other workflows by using the permissions they gained.
As an example if the vulnerable workflow doesn't have content:write but
has issue:write, the attacker can exploit a second workflow (that has a
token with content:write) that can be triggered by issue: labeled (since
they can now label issues using issue:write).
Such "lateral" exploitation is almost possible on IntersectMBO/govtool
too since update-govtool-version.yml is vulnerable to the same type of
interpolation (line 28 and 58).
Alas this isn't possible since you used narrow enough permissions to not
allow a call to workflow_dispatch (however fixing update-govtool-version
would be wise to prevent mishaps from future configuration changes).

Expected behavior

The fix for this is to use env variables instead, going back to the
example workflow that prints its path:

env:
action_path: "${{ github.action_path }}"
run:
echo "Hello, the path of this workflow is $action_path"

this is safe because the interpolation inside the code is being done by
bash (which, obviously, is aware of its own language).

You can find her a patch that fixes these
vulnerabilities:

diff --git a/.github/workflows/label-bug-report.yml
b/.github/workflows/label-bug-report.yml
index 230ffefc..82532b5c 100644
--- a/.github/workflows/label-bug-report.yml
+++ b/.github/workflows/label-bug-report.yml
@@ -14,9 +14,11 @@ jobs:
steps:
- name: Check if issue is a "🐛 Bug report"
id: check_is_bug_report
+ env:
+ issue_title: "${{ github.event.issue.title }}"
run: |
echo "## Checking if issue is a 'Feature idea'..."
- if [[ "${{ github.event.issue.title }}" == "🐛 "* ]]; then
+ if [[ "$issue_title" == "🐛 "* ]]; then
echo "is_bug_report=true" >> $GITHUB_ENV
else
echo "is_bug_report=false" >> $GITHUB_ENV
diff --git a/.github/workflows/label-feature-issue.yml
b/.github/workflows/label-feature-issue.yml
index 9ef4d6c8..e7c205d7 100644
--- a/.github/workflows/label-feature-issue.yml
+++ b/.github/workflows/label-feature-issue.yml
@@ -14,9 +14,11 @@ jobs:
steps:
- name: Check if issue is a "💡 Feature idea"
id: check_is_feature_idea
+ env:
+ issue_title: "${{ github.event.issue.title }}"
run: |
echo "## Checking if issue is a 'Feature idea'..."
- if [[ "${{ github.event.issue.title }}" == "💡 "* ]]; then
+ if [[ "$issue_title" == "💡 "* ]]; then
echo "is_feature_idea=true" >> $GITHUB_ENV
else
echo "is_feature_idea=false" >> $GITHUB_ENV
@@ -89,4 +91,4 @@ jobs:
repo: context.repo.repo,
labels: ["User Story Needed"],
});
- }
\ No newline at end of file
+ }
diff --git a/.github/workflows/update-govtool-version.yml
b/.github/workflows/update-govtool-version.yml
index c7156e26..35e127d3 100644
--- a/.github/workflows/update-govtool-version.yml
+++ b/.github/workflows/update-govtool-version.yml
@@ -10,6 +10,8 @@ on:
jobs:
update-version:
runs-on: ubuntu-latest
+ env:
+ VERSION: "${{ github.event.inputs.version }}"
...skipping...
+ issue_title: "${{ github.event.issue.title }}"
run: |
echo "## Checking if issue is a 'Feature idea'..."
- if [[ "${{ github.event.issue.title }}" == "💡 "* ]]; then
+ if [[ "$issue_title" == "💡 "* ]]; then
echo "is_feature_idea=true" >> $GITHUB_ENV
else
echo "is_feature_idea=false" >> $GITHUB_ENV
@@ -89,4 +91,4 @@ jobs:
repo: context.repo.repo,
labels: ["User Story Needed"],
});
- }
\ No newline at end of file
+ }
diff --git a/.github/workflows/update-govtool-version.yml
b/.github/workflows/update-govtool-version.yml
index c7156e26..35e127d3 100644
--- a/.github/workflows/update-govtool-version.yml
+++ b/.github/workflows/update-govtool-version.yml
@@ -10,6 +10,8 @@ on:
jobs:
update-version:
runs-on: ubuntu-latest
+ env:
+ VERSION: "${{ github.event.inputs.version }}"

steps:
- name: Checkout Repository
@@ -24,9 +26,6 @@ jobs:
node-version-file: "./govtool/frontend/.nvmrc"
scope: "@intersect.mbo"

- - name: Set Version Variable
- run: echo "VERSION=${{ github.event.inputs.version }}" >>
$GITHUB_ENV
-
- name: Update package.json files and install dependencies
run: |
jq --arg v "$VERSION" '.version = $v'
govtool/frontend/package.json > temp.json && mv temp.json
govtool/frontend/package.json
@@ -55,7 +54,7 @@ jobs:
- name: Update CHANGELOG.md
run: |
#!/bin/bash
- VERSION="${{ github.event.inputs.version }}"
+ VERSION="$VERSION"
TODAY=$(date +%Y-%m-%d)
RELEASE_TAG="v$VERSION"

RELEASE_LINK="[v$VERSION](https://github.com/IntersectMBO/govtool/releases/tag/$RELEASE_TAG)"

Metadata

Metadata

Assignees

Type

No type

Projects

Status

No status

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions