From 9f48eb909df82d055011c376ebc450a1bed29927 Mon Sep 17 00:00:00 2001 From: Dinesh Yadav <13635627+HumbleBee14@users.noreply.github.com> Date: Sun, 19 Apr 2026 15:18:45 -0400 Subject: [PATCH 1/2] fix: pass commit message via env var to prevent shell injection Direct ${{ github.event.head_commit.message }} substitution in a run block can break bash when the message contains colons, hash signs, or command-like lines (e.g. 'RELEASE_PAT' from a squash-merge body). Pass it via env and also take only the subject line for type detection. --- .github/workflows/release.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0e59f11..3130d26 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,6 +53,12 @@ jobs: # 5. Writes the new values back into app/build.gradle.kts via sed - name: Bump version id: bump + # Pass untrusted values (commit message, workflow inputs) via env vars + # instead of `${{ }}` substitution so bash doesn't try to execute + # anything that looks like a shell command inside them. + env: + COMMIT_MSG: ${{ github.event.head_commit.message }} + MANUAL_BUMP_INPUT: ${{ github.event.inputs.bump_type }} run: | set -e GRADLE_FILE="app/build.gradle.kts" @@ -63,8 +69,9 @@ jobs: IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_NAME" - MANUAL_BUMP="${{ github.event.inputs.bump_type }}" - MSG="${{ github.event.head_commit.message }}" + MANUAL_BUMP="$MANUAL_BUMP_INPUT" + # Use only the first line (subject) of the commit message for type detection + MSG=$(printf '%s' "$COMMIT_MSG" | head -n 1) if [ "$MANUAL_BUMP" = "major" ]; then MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 From 8de2d1cf2eb26c7bc30e632a398aa1375e207d64 Mon Sep 17 00:00:00 2001 From: Dinesh Yadav <13635627+HumbleBee14@users.noreply.github.com> Date: Sun, 19 Apr 2026 15:19:43 -0400 Subject: [PATCH 2/2] test: add dry-run release and build checks to PR validation Simulates the version-bump step on every PR using the PR title as the commit message, catching shell injection and version parsing bugs before merge. Also adds a debug build to catch compile breaks early. --- .github/workflows/pr-validation.yml | 66 +++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index ff41068..a963f13 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -49,3 +49,69 @@ jobs: exit 1 fi echo "PR description OK" + + dry-run-release: + # Simulates the version-bump step from release.yml using the PR title as the + # commit message. Catches shell injection, version parsing bugs, or anything + # that would break the real release workflow on merge. + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Dry-run version bump + env: + # PR title becomes the squash-merge commit subject, so simulate with it. + COMMIT_MSG: ${{ github.event.pull_request.title }} + run: | + set -e + GRADLE_FILE="app/build.gradle.kts" + CURRENT_CODE=$(grep -E "^\s*versionCode\s*=" "$GRADLE_FILE" | grep -oE "[0-9]+") + CURRENT_NAME=$(grep -E "^\s*versionName\s*=" "$GRADLE_FILE" | grep -oE '"[^"]+"' | tr -d '"') + + if [ -z "$CURRENT_CODE" ] || [ -z "$CURRENT_NAME" ]; then + echo "::error::Could not read versionCode or versionName from $GRADLE_FILE" + exit 1 + fi + + IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_NAME" + if [ -z "$MAJOR" ] || [ -z "$MINOR" ] || [ -z "$PATCH" ]; then + echo "::error::versionName '$CURRENT_NAME' is not in MAJOR.MINOR.PATCH format" + exit 1 + fi + + MSG=$(printf '%s' "$COMMIT_MSG" | head -n 1) + + if echo "$MSG" | grep -qE "^(BREAKING|.*BREAKING CHANGE)"; then + MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 + BUMP_TYPE="major" + elif echo "$MSG" | grep -qE "^feat(\(.+\))?:"; then + MINOR=$((MINOR + 1)); PATCH=0 + BUMP_TYPE="minor" + else + PATCH=$((PATCH + 1)) + BUMP_TYPE="patch" + fi + + NEW_NAME="$MAJOR.$MINOR.$PATCH" + NEW_CODE=$((CURRENT_CODE + 1)) + + echo "Current: code=$CURRENT_CODE name=$CURRENT_NAME" + echo "On merge, this PR would bump to: code=$NEW_CODE name=$NEW_NAME ($BUMP_TYPE)" + + build: + # Compiles a debug APK to catch build breaks before merge. + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Set up JDK 17 + uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: "17" + + - name: Make gradlew executable + run: chmod +x ./gradlew + + - name: Build debug APK + run: ./gradlew assembleDebug -x lint