master publishes the project site from .github/workflows/ci.yml. That job installs a Python package from a mutable git ref on a personal fork, then force-deploys Pages with a write-capable GITHUB_TOKEN. The same ref is installed in Dockerfile so CI and local/preview image builds share one untrusted dependency.
# .github/workflows/ci.yml
permissions:
contents: write
# …
- run: pip install git+https://github.com/PauloASilva/mkdocs-monorepo-plugin@feat/i18n
- run: mkdocs gh-deploy --force
Dockerfile
ENV MKDOCS_MONOREPO_REPO=https://github.com/PauloASilva/mkdocs-monorepo-plugin
ENV MKDOCS_MONOREPO_BRANCH="feat/i18n"
RUN python -m pip install git+$MKDOCS_MONOREPO_REPO@$MKDOCS_MONOREPO_BRANCH
@feat/i18n is not a tag or a release or a commit SHA. Thus, each pip install (Actions and docker build) resolves whatever commit is currently at that branch tip, and package installation executes the distribution’s build backend. In CI, the next step can rewrite gh-pages
The official plugin is backstage/mkdocs-monorepo-plugin / PyPI mkdocs-monorepo-plugin. Neither the workflow nor the Dockerfile uses that artifact.
actions/checkout@v3, actions/setup-python@v4, and actions/cache@v3 are unpinned by SHA and are not current majors. Secondary to the git-ref install.
In scope of SECURITY.md (CI/CD / repository automation)
Steps to reproduce
- Open
.github/workflows/ci.yml and Dockerfile on master.
- Confirm both install
git+https://github.com/PauloASilva/mkdocs-monorepo-plugin@feat/i18n with no commit SHA.
- Confirm the workflow has
permissions: contents: write and runs mkdocs gh-deploy --force.
- Resolve
https://github.com/PauloASilva/mkdocs-monorepo-plugin @ feat/i18n and note it is a moving branch tip.
No exploit payload included.
Expected behavior
Third-party Python used to publish this site is a pinned PyPI release with hashes or git+https://…@<full commit SHA>. Pages deploy does not use repo-wide contents: write plus force push.
Actual behavior
CI and Docker install a floating feat/* branch from a personal fork then CI force-deploys the site.
Impact
Compromise or unilateral update of PauloASilva/mkdocs-monorepo-plugin@feat/i18n yields:
- arbitrary code execution in
OWASP/API-Security GitHub Actions on the next push to master and in any docker build of this tree
- integrity failure of the published API Security Top 10 site via
mkdocs gh-deploy --force
No application runtime or user data is involved. The asset is the official documentation origin.
Suggested remediation
- Pin one artifact in both the workflow and the Dockerfile (lockfile with hashes, or an immutable commit SHA)
- Build with
contents: read. Deploy via actions/upload-pages-artifact + actions/deploy-pages (pages: write, id-token: write only on the deploy job)
- Remove
--force unless a documented recovery case requires it
- Pin Actions by commit SHA
Happy to send a PR that pins the SHA and splits the deploy job.
masterpublishes the project site from.github/workflows/ci.yml. That job installs a Python package from a mutable git ref on a personal fork, then force-deploys Pages with a write-capableGITHUB_TOKEN. The same ref is installed inDockerfileso CI and local/preview image builds share one untrusted dependency.Dockerfile
@feat/i18nis not a tag or a release or a commit SHA. Thus, eachpip install(Actions anddocker build) resolves whatever commit is currently at that branch tip, and package installation executes the distribution’s build backend. In CI, the next step can rewritegh-pagesThe official plugin is
backstage/mkdocs-monorepo-plugin/ PyPImkdocs-monorepo-plugin. Neither the workflow nor the Dockerfile uses that artifact.actions/checkout@v3,actions/setup-python@v4, andactions/cache@v3are unpinned by SHA and are not current majors. Secondary to the git-ref install.In scope of
SECURITY.md(CI/CD / repository automation)Steps to reproduce
.github/workflows/ci.ymlandDockerfileonmaster.git+https://github.com/PauloASilva/mkdocs-monorepo-plugin@feat/i18nwith no commit SHA.permissions: contents: writeand runsmkdocs gh-deploy --force.https://github.com/PauloASilva/mkdocs-monorepo-plugin@feat/i18nand note it is a moving branch tip.No exploit payload included.
Expected behavior
Third-party Python used to publish this site is a pinned PyPI release with hashes or
git+https://…@<full commit SHA>. Pages deploy does not use repo-widecontents: writeplus force push.Actual behavior
CI and Docker install a floating
feat/*branch from a personal fork then CI force-deploys the site.Impact
Compromise or unilateral update of
PauloASilva/mkdocs-monorepo-plugin@feat/i18nyields:OWASP/API-SecurityGitHub Actions on the next push tomasterand in anydocker buildof this treemkdocs gh-deploy --forceNo application runtime or user data is involved. The asset is the official documentation origin.
Suggested remediation
contents: read. Deploy viaactions/upload-pages-artifact+actions/deploy-pages(pages: write,id-token: writeonly on the deploy job)--forceunless a documented recovery case requires itHappy to send a PR that pins the SHA and splits the deploy job.