Skip to content

fix(security): harden argument validation and risk detection in SecurityPolicy #6654

fix(security): harden argument validation and risk detection in SecurityPolicy

fix(security): harden argument validation and risk detection in SecurityPolicy #6654

Workflow file for this run

# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
# add this workflow to a repo to fix lock files for Renovate PRs
name: Fix Renovate
on:
issue_comment:
types: [created, edited]
concurrency:
group: ${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}
cancel-in-progress: true
jobs:
lock-update:
runs-on: ubuntu-latest
timeout-minutes: 45
permissions:
contents: read
if: >-
false &&
startsWith(github.event.comment.body, '/fix-lock') &&
github.event.issue.pull_request != null &&
(
github.event.comment.author_association == 'OWNER' ||
github.event.comment.author_association == 'MEMBER' ||
github.event.comment.author_association == 'COLLABORATOR'
)
env:
PR: ${{ github.event.issue.pull_request.html_url }}
steps:
- name: 📡 Get PR Data
if: github.event_name == 'issue_comment' && github.event.issue.pull_request != null
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
id: get-pr-data
with:
# language=javascript
script: |
console.log(`Get PR info: ${context.repo.owner}/${context.repo.repo}#${context.issue.number}`)
const {data: pr} = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
})
console.log(`PR info: ${JSON.stringify(pr)}`)
const prInfo = {
num: context.issue.number,
branchName: pr.head.ref,
commit: pr.head.sha,
committer: pr.head.user.login,
repo: pr.head.repo.full_name
}
const baseRepo = `${context.repo.owner}/${context.repo.repo}`
if (prInfo.repo !== baseRepo) {
core.setFailed(`PR must come from ${baseRepo}, got ${prInfo.repo}`)
return
}
if (prInfo.committer === 'github-actions[bot]' || prInfo.committer === 'dependabot[bot]' || prInfo.committer === 'renovate[bot]') {
console.log(`PR is from ${prInfo.committer}`)
} else {
console.log(`PR is not from ${prInfo.committer}`)
core.setFailed(`PR is from ${prInfo.committer} is not allowed`)
}
core.setOutput('head_repo', prInfo.repo)
core.setOutput('head_branch', prInfo.branchName)
core.setOutput('head_sha', prInfo.commit)
core.setOutput('committer', prInfo.committer)
- name: 📡 Use PR Branch
run: |
echo "The PR branch is ${{ steps.get-pr-data.outputs.head_branch }}"
echo "The PR commit is ${{ steps.get-pr-data.outputs.head_sha }}"
echo "The repository is ${{ steps.get-pr-data.outputs.head_repo }}"
- name: ✈ Checkout PR commit
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 1
repository: ${{ steps.get-pr-data.outputs.head_repo }}
ref: ${{ steps.get-pr-data.outputs.head_sha }}
- name: 🔍 Verify checked-out commit
run: |
EXPECTED_SHA="${{ steps.get-pr-data.outputs.head_sha }}"
ACTUAL_SHA="$(git rev-parse HEAD)"
echo "Expected SHA: ${EXPECTED_SHA}"
echo "Actual SHA: ${ACTUAL_SHA}"
if [[ "${ACTUAL_SHA}" != "${EXPECTED_SHA}" ]]; then
echo "Checked-out commit does not match expected PR SHA."
exit 1
fi
- name: 📦 Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4
with:
version: 10
- name: 📦 Setup Node
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: "24"
cache: "pnpm"
cache-dependency-path: |
pnpm-lock.yaml
clients/web/pnpm-lock.yaml
clients/web/apps/docs/pnpm-lock.yaml
clients/web/apps/marketing/pnpm-lock.yaml
- name: ☕ Setup Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
java-version: "25"
distribution: "corretto"
- name: 🦀 Setup Rust toolchain
run: rustup toolchain install 1.92 --profile minimal --component rustfmt --component clippy
- name: 🐘 Setup Gradle
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2
with:
gradle-version: wrapper
cache-read-only: false
- name: 🔧 Make Gradle wrapper executable
run: chmod +x ./gradlew
- name: 🔧 Show Gradle version
run: ./gradlew --version
- name: 🔐 Re-validate PR head SHA before write actions
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
EXPECTED_SHA: ${{ steps.get-pr-data.outputs.head_sha }}
EXPECTED_REPO: ${{ steps.get-pr-data.outputs.head_repo }}
with:
# language=javascript
script: |
const expectedSha = process.env.EXPECTED_SHA
const expectedRepo = process.env.EXPECTED_REPO
// Fetch the current PR head from the API to detect any changes on the remote branch
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
})
const currentRepo = pr.head.repo.full_name
const currentSha = pr.head.sha
core.info(`Expected repo/SHA: ${expectedRepo} @ ${expectedSha}`)
core.info(`Current repo/SHA (remote): ${currentRepo} @ ${currentSha}`)
// Also ensure that the locally checked-out commit matches the expected SHA
const { execSync } = require('node:child_process')
const localSha = execSync('git rev-parse HEAD', { encoding: 'utf8' }).trim()
core.info(`Current repo/SHA (local HEAD): ${expectedRepo} @ ${localSha}`)
const remoteChanged = currentRepo !== expectedRepo || currentSha !== expectedSha
const localChanged = localSha !== expectedSha
if (remoteChanged || localChanged) {
core.setFailed(
`PR head changed after approval/check (expected ${expectedRepo}@${expectedSha}, got remote ${currentRepo}@${currentSha}, local HEAD ${expectedRepo}@${localSha}). Re-run /fix-lock.`
)
}
- name: 🔒 Write all Gradle locks
run: ./gradlew writeLocksAll --no-parallel
- name: 📝 Get Commit Message
run: |
COMMIT_MSG=$(git log --format=%s -n 1 "${{ steps.get-pr-data.outputs.head_sha }}")
echo "COMMIT_MSG=${COMMIT_MSG}" >> "$GITHUB_ENV"
- name: 💾 Commit file changes (only for bots)
env:
SKIP_GIT_HOOKS: "1"
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add -A
git diff --cached --quiet || git commit -m "${COMMIT_MSG}"
- name: 🔐 Re-validate PR head SHA before push
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
EXPECTED_SHA: ${{ steps.get-pr-data.outputs.head_sha }}
EXPECTED_REPO: ${{ steps.get-pr-data.outputs.head_repo }}
with:
# language=javascript
script: |
const expectedSha = process.env.EXPECTED_SHA
const expectedRepo = process.env.EXPECTED_REPO
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
})
const currentRepo = pr.head.repo.full_name
const currentSha = pr.head.sha
core.info(`Expected repo/SHA: ${expectedRepo} @ ${expectedSha}`)
core.info(`Current repo/SHA (remote): ${currentRepo} @ ${currentSha}`)
// Local HEAD intentionally not checked: it now includes our lock-file
// commit and will differ from expectedSha. Only remote ref matters.
const { execSync } = require('node:child_process')
const localSha = execSync('git rev-parse HEAD', { encoding: 'utf8' }).trim()
core.info(`Current repo/SHA (local HEAD): ${expectedRepo} @ ${localSha}`)
if (currentRepo !== expectedRepo || currentSha !== expectedSha) {
core.setFailed(
`PR head changed after approval/check (expected ${expectedRepo}@${expectedSha}, got remote ${currentRepo}@${currentSha}). Re-run /fix-lock.`
)
}
- name: 🚀 Push lockfile updates
env:
SKIP_GIT_HOOKS: "1"
run: git push --force-with-lease=refs/heads/${{ steps.get-pr-data.outputs.head_branch }}:${{ steps.get-pr-data.outputs.head_sha }} origin HEAD:${{ steps.get-pr-data.outputs.head_branch }}
- name: 💬 Add reaction to trigger comment
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
comment-id: ${{ github.event.comment.id }}
reactions: hooray