Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 43 additions & 4 deletions .github/workflows/docs-deploy-surge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ on:
- completed

jobs:
# [Optional] Restrict automatic dpeloyment to PRs from the upstream repo
# [Optional] Restrict automatic deployment to PRs from the upstream repo
# For fork PRs, requires manual approval via the "preview" environment.
# For PRs from the main repository this job is skipped and deploy-docs runs immediately.
# Setup: create a "preview" environment in Settings → Environments with required reviewers.
Expand Down Expand Up @@ -56,7 +56,7 @@ jobs:
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ env.RUN_ID }},
run_id: process.env.RUN_ID,
});

var matchArtifactDocs = artifacts.data.artifacts.filter((artifact) => {
Expand Down Expand Up @@ -86,13 +86,32 @@ jobs:

- id: suspicious-path-check
name: Suspicious paths check
shell: bash
env:
ARTIFACT_DIR: ${{ runner.temp }}/artifacts/docs
run: |
set -euo pipefail
cd "$ARTIFACT_DIR"
if unzip -l docs.zip | grep -q "\.\./"; then

mapfile -t ZIP_ENTRIES < <(zipinfo -1 docs.zip)
if [ "${#ZIP_ENTRIES[@]}" -eq 0 ]; then
echo "docs.zip is empty"
exit 1
fi
for entry in "${ZIP_ENTRIES[@]}"; do
if [[ "$entry" =~ ^/ ]]; then
echo "Blocked absolute path in artifact: $entry"
exit 1
fi
if [[ "$entry" =~ (^|/)\.\.(/|$) ]]; then
echo "Blocked path traversal in artifact: $entry"
exit 1
fi
if [[ "$entry" == *\\* ]]; then
echo "Blocked Windows-style path separator in artifact: $entry"
exit 1
fi
done

- id: hidden-files-check
name: Hidden files check
Expand Down Expand Up @@ -131,7 +150,27 @@ jobs:
run: |
cd "$ARTIFACT_DIR"
unzip changelog.zip


# The changelog file is built from untrusted PR content and its contents
# are posted to the PR as a comment. A malicious artifact could make
# `changelog` a symlink pointing at an arbitrary file the runner can read,
# turning the comment step into an arbitrary-file-read. Reject anything
# that isn't a plain regular file before we read it.
- id: validate-changelog
name: Validate changelog is a regular file
if: ${{ steps.find-changelog.outputs.has-changelog == 'true' }}
env:
CHANGELOG_FILE: ${{ runner.temp }}/artifacts/changelog/changelog
run: |
if [ -L "$CHANGELOG_FILE" ]; then
echo "Security Alert: changelog is a symlink — refusing!"
exit 1
fi
if [ ! -f "$CHANGELOG_FILE" ]; then
echo "changelog missing or not a regular file"
exit 1
fi

- id: get-deploy-id
name: Get deploy ID
env:
Expand Down