From d04f2a42daff7e2ad483e4e8ef0009dcf8ceb8ac Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Thu, 22 Oct 2026 11:40:30 -0400 Subject: [PATCH] security(release): keep app-title and version metadata out of shell source (#47) draft-release and resolve-version interpolated caller-provided metadata directly into Bash source (CWE-78): - draft-release embedded app-title into the `title=` assignment in the step that has GH_TOKEN available. - resolve-version embedded input-version into a `v=` assignment before it was validated, and app-title into the job-summary `echo`. Both inputs now travel through the step `env:` and are read with quoted variable expansions; the version is validated before it is used to produce outputs, and the summary is written with a fixed `printf` format. No change to outputs or release behavior. --- actions/draft-release/action.yml | 3 ++- actions/resolve-version/action.yml | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/actions/draft-release/action.yml b/actions/draft-release/action.yml index 190a2dc..0dd090a 100644 --- a/actions/draft-release/action.yml +++ b/actions/draft-release/action.yml @@ -37,12 +37,13 @@ runs: working-directory: artifacts env: VERSION: ${{ inputs.version }} + APP_TITLE: ${{ inputs.app-title }} PRERELEASE: ${{ inputs.prerelease }} GH_TOKEN: ${{ inputs.github-token }} GH_REPO: ${{ github.repository }} run: | tag="v$VERSION" - title="${{ inputs.app-title }} v$VERSION" + title="$APP_TITLE v$VERSION" pre=() if [ "$PRERELEASE" = "true" ]; then pre=(--prerelease); fi if draft="$(gh release view "$tag" --json isDraft --jq .isDraft 2>/dev/null)"; then diff --git a/actions/resolve-version/action.yml b/actions/resolve-version/action.yml index 98b4b65..0b2a663 100644 --- a/actions/resolve-version/action.yml +++ b/actions/resolve-version/action.yml @@ -28,13 +28,16 @@ runs: - id: resolve name: Resolve version shell: bash + env: + INPUT_VERSION: ${{ inputs.input-version }} + APP_TITLE: ${{ inputs.app-title }} run: | if [ -f packaging/env.sh ]; then . packaging/env.sh elif [ -f packaging/common.sh ]; then . packaging/common.sh fi - v="${{ inputs.input-version }}" + v="$INPUT_VERSION" v="${v#v}" v="${v:-$VERSION}" if ! printf '%s' "$v" | grep -Eq '^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$'; then @@ -47,4 +50,4 @@ runs: echo "date=$(date -u +%Y-%m-%d)" echo "prerelease=$pre" } >>"$GITHUB_OUTPUT" - echo "### ${{ inputs.app-title }} v$v (\`${GITHUB_SHA::9}\`)" >>"$GITHUB_STEP_SUMMARY" + printf '### %s v%s (`%s`)\n' "$APP_TITLE" "$v" "${GITHUB_SHA::9}" >>"$GITHUB_STEP_SUMMARY"