mirror of
https://github.com/bombsquad-community/plugin-manager.git
synced 2026-08-15 13:03:08 +00:00
pull_request_target checked out fork PR branches with the repo's
write-scoped GITHUB_TOKEN and ran autopep8/metadata scripts/tests
against that fork content, letting a malicious PR rewrite test/*.py
for arbitrary code execution with push access and secrets. It's also
been failing outright for weeks since actions/checkout now blocks
unsafe fork checkouts here without explicit opt-in.
Split into ci-check.yml (plain pull_request, GitHub's read-only
no-secrets token, safe to run fork code) which uploads a diff
artifact, and ci-apply.yml (workflow_run, privileged) which only
applies that diff via `git apply`, never executing fork content.
ci.yml keeps just the push-to-main job as the strict integrity check.
Because GitHub runs the PR's own copy of ci-check.yml for
pull_request events, that artifact is attacker-authored: ci-apply.yml
therefore resolves PR identity from the workflow_run payload plus the
API rather than the artifact, passes every dynamic value through env:
instead of ${{ }} in run: blocks (which the runner substitutes before
the shell parses, so quotes don't contain it), and validates branch,
repo, sha and PR-number shapes before use. The patch itself stays
untrusted input: allowlist-validated and applied only to the fork's
own branch.
test_checks.py adds an env-gated lenient mode so ci-check.yml's
preview run doesn't fail on a brand-new plugin's not-yet-existing
commit sha, while history and push-to-main stay strict.
58 lines
1.6 KiB
YAML
58 lines
1.6 KiB
YAML
name: CI
|
|
|
|
# Runs only on pushes to main - i.e. after a PR has been merged, or on a
|
|
# direct maintainer push. This is fully trusted, same-repo content, so it's
|
|
# safe for it to execute the tree and push directly. This is also the
|
|
# AUTHORITATIVE integrity check: test/test_checks.py's test_versions runs
|
|
# here unmodified/strict against real, permanent git history (unlike
|
|
# ci-check.yml, which can't yet resolve a commit sha for a brand-new plugin
|
|
# version and runs leniently instead).
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
jobs:
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v6
|
|
with:
|
|
python-version: "3.12"
|
|
|
|
- name: Install Dependencies
|
|
run: |
|
|
python -m pip install -U pip
|
|
python -m pip install -U pycodestyle==2.12.1 autopep8
|
|
python -m pip install -U -r test/pip_reqs.txt
|
|
|
|
- name: Apply AutoPEP8
|
|
run: |
|
|
autopep8 --in-place --recursive --max-line-length=100 .
|
|
|
|
- name: Commit AutoPEP8 formatting
|
|
uses: stefanzweifel/git-auto-commit-action@v7
|
|
with:
|
|
commit_message: "[ci] apply-formatting"
|
|
|
|
- name: Apply Version Metadata
|
|
run: |
|
|
python test/auto_apply_version_metadata.py $(git log --pretty=format:'%h' -n 1)
|
|
|
|
- name: Commit Version Metadata
|
|
uses: stefanzweifel/git-auto-commit-action@v7
|
|
with:
|
|
commit_message: "[ci] apply-version-metadata"
|
|
|
|
- name: Execute Tests
|
|
run: |
|
|
python -m unittest discover -v
|