Auto-rebuild & auto-merge theme-asset Dependabot PRs (+ verify check) - #1265
Auto-rebuild & auto-merge theme-asset Dependabot PRs (+ verify check)#1265CybotTM wants to merge 5 commits into
Conversation
c0de53a to
35f1f45
Compare
|
I will check failing "Main / Validate monorepo structure (pull_request)Failing after 36s" |
35f1f45 to
396fdcf
Compare
1d089a0 to
482c8fb
Compare
482c8fb to
e3f71cb
Compare
Adds a `github-actions` package ecosystem to `dependabot.yml`, using the same schedule and conventions as the existing composer and npm entries (daily 16:00 Europe/Berlin, `[TASK]` prefix, `dependencies` + ecosystem label — the `github-actions` label has been created). ## Why Action versions in the workflows have only ever been updated by hand — `dependabot.yml` has covered composer and npm exclusively since it was created in #236, and the pins were last refreshed manually (#1194, then the #1184 → #1328/#1329 split). With this entry, Dependabot takes that over: it bumps SHA pins **and keeps the trailing `# vX.Y.Z` comments in sync** (see e.g. the actions bumps in TYPO3-Documentation/.github#19, same org). Minor/patch action bumps then flow through the existing auto-approve/auto-merge workflows like composer/npm updates already do; majors wait for review. ## Coordination - Trivial textual conflict with #1265, which also edits `dependabot.yml` (composer `ignore` key fix) — whichever lands second rebases. - Best merged after #1328/#1329 so Dependabot starts from current, annotated pins rather than re-proposing the same bumps. Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
e3f71cb to
f8a1fcd
Compare
|
Rebased onto The Two gaps the branch had, both from things that happened after it was opened in May: Advisory merges bypassed it. Fixes from a temporary private fork arrive on The merge queue would have stalled. Both triggers are added. The base sha now comes out of the event payload via Checked locally: |
The three advisory fixes are merged and tagged in 0.40.0, but the published assets do not contain them. `assets/js/search.js` and `resources/public/js/theme.min.js` are committed build artifacts and were never rebuilt. Re-rendering a manual does not help — the theme version is pinned in the asset URL, so a re-render fetches the same vulnerable file. This is why https://docs.typo3.org/m/typo3/tutorial-getting-started/13.4/en-us/?q=%3Cimg%20src=x%20onerror=alert(document.domain)%3E still fires after a fresh render. ## Evidence The CDN serves exactly the artifact committed at tag 0.40.0: ``` CDN 0.40.0/js/theme.min.js md5 67ee48dc0483752ddbcbe68b64639efb 239212 bytes repo @ 0.40.0, theme.min.js md5 67ee48dc0483752ddbcbe68b64639efb 239212 bytes ``` That artifact was last changed in f795385 on 14 July — eleven days before ab24ff7, db881fd and a22f55b. Markers that survive minification, old versus rebuilt: | marker | origin | search.js | theme.min.js | |---|---|---|---| | `MARK` | `sanitizeHtml.js`, a22f55b | 0 → 1 | 0 → 1 | | `'` | `attrEscape()`, ab24ff7 | — | 0 → 2 | | `https:` | `safeUrl()` allowlist, ab24ff7 | — | 3 → 5 | Executed, not just read: loading each bundle in jsdom against a real rendered page and opening the info modal with `data-details="<img src=x onerror=…>"` - deployed bundle: `<img src="x" onerror="window.__xss = true">` lands in the DOM as a live element, `[onerror]` present - rebuilt bundle: rendered as inert text, no `img`, no `[onerror]` The build is reproducible — two consecutive `npm run build` runs produced identical hashes, and the committed files match both. ## Scope Only the two JS artifacts. `npm run build` also regenerates `resources/public/css/theme.css` and the FontAwesome woff2 files, which have drifted since #1333; that drift is older than this incident and is reverted here so the security release carries nothing else. It needs its own PR. ## Verification ``` npm test 5 files, 23 tests passed ``` No source file changes, so the diff is the artifacts only. ## After merge 0.40.1 needs to be tagged and the manuals re-rendered — the version is part of the asset URL, so the release is what actually ships the fix. ## How this got through There is no CI job that builds the assets or compares them to the committed ones. #1265 adds exactly that check (`.github/workflows/check-built-assets.yaml`) and has been open since 24 May with all checks green. It triggers on `pull_request` only, so as written it would not have caught these three commits either — advisory merges land as direct pushes to `main`, without a PR. Worth merging with a `push` trigger on `main` added. Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
packages/typo3-docs-theme/ commits generated frontend assets (Vite output in assets/js/, Grunt output in resources/public/). If a change edits the theme sources but does not regenerate those assets, stale assets reach the rendered docs. This adds a status-check workflow that rebuilds the theme on a pull request and fails if the committed assets differ from a fresh build — catching both modified tracked files and new untracked output, with a single actionable annotation. It runs on every pull request (no paths filter) and short-circuits to success when the theme package is untouched, so it can safely be a required status check: a path-filtered required check never reports on unrelated PRs and would leave them un-mergeable. Least privilege: empty top-level permissions, job-level contents:read; harden-runner egress in block mode. Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
A Dependabot bump of a theme dependency changes the build output but Dependabot cannot regenerate the committed assets, so the bump alone fails the check-built-assets gate. This adds a workflow that, on those Dependabot PRs, rebuilds the assets, commits them back, and enables auto-merge. * pull_request_target + 'if: github.actor == dependabot[bot]' (matches the existing pr-auto-merge.yaml convention). * PR head pinned by SHA; a lockfile-only diff guard; npm ci --ignore-scripts; harden-runner egress in block mode. * The App token is minted AFTER the build so a compromised build dependency cannot read it; the GITHUB_TOKEN stays read-only. * The rebuilt files are committed through the GitHub API (createCommitOnBranch) with the App token, not git push, so the commit is GitHub-signed (Verified) and re-triggers the asset check on the new commit. Requires a GitHub App (Contents + Pull requests: write) and APP_ID / APP_PRIVATE_KEY secrets. * Auto-merge is enabled here, after the rebuild commit is in place, so pr-auto-merge.yaml is updated to skip PRs that update the theme package's dependencies (otherwise it squashes the bump before the rebuild lands). Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Point the theme-customization developer docs at the asset check and the Dependabot auto-rebuild, and state the local rebuild command contributors run before committing. Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
The check only triggered on pull_request. Two paths past it: Security advisory fixes are merged out of a temporary private fork and land on "main" as direct commits, never as a pull request in this repo, so the gate could not see them. That is how 0.40.0 shipped assets built before the fixes it was tagged for. "main" gained a merge queue in TYPO3-Documentation#1326 after this branch was opened. A required status check without a merge_group trigger never reports on a queued merge, which times the merge out. Add both triggers. The base sha now comes from the event payload, and an event without one, a push, is verified in full rather than skipped. Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
Both new workflows opened with step-security/harden-runner. The repository restricts Actions to an allowlist and harden-runner is not on it, so the run ended in startup_failure before any step executed. This never showed while the branch was conflicting, because a pull request that cannot be merged produces no runs. Remove the step from both workflows. Every remaining action matches the allowlist. Getting harden-runner added to it would be the better fix and is noted in the workflow header. Signed-off-by: Sebastian Mendel <github@sebastianmendel.de>
92e5fae to
3d91b7b
Compare


Problem
packages/typo3-docs-theme/commits its built frontend assets (assets/js/,resources/public/). They drift out of sync when a contributor forgets to rebuild, or when Dependabot bumps a build dependency — Dependabot can't rebuild the assets (this is what made the manual follow-up #1264 necessary).Changes
check-built-assets.yaml— required checkverify: on every PR, rebuilds the theme and fails if the committed assets don't match a fresh build. PRs not touching the theme short-circuit to success, so the check can be required without blocking unrelated PRs. Also runs on push tomainand in the merge queue.dependabot-rebuild-assets.yaml— on a Dependabot theme bump: rebuilds the assets, commits them back as a GitHub-signed (Verified) commit via a GitHub App, then enables auto-merge for patch/minor updates.pr-auto-merge.yaml— excludes theme PRs from the generic Dependabot auto-merge; the workflow above handles them after the rebuild commit lands.Documentation/Developer/ThemeCustomization.rst.Required repository settings
APP_ID/APP_PRIVATE_KEY(same names asreusable-backport.yml).verifycheck.Security
dependabot-rebuild-assets.yamlusespull_request_target(same convention aspr-auto-merge.yaml). Guards: actor gated todependabot[bot]; checkout pinned to the PR head SHA; lockfile-only diff guard;npm ci --ignore-scripts; read-onlyGITHUB_TOKEN; App token minted only after the build; commit created viacreateCommitOnBranch, so it is Verified and re-triggersverify.Residual risk (accepted): patch/minor theme bumps merge without a human in the loop, so a compromised dependency's build-time code runs and its output merges. For a manual checkpoint, drop the "Enable auto-merge" step.
Validation
Proven end-to-end on a fork: non-theme PR →
verifyskips green; stale assets →verifyblocks; Dependabot bump → Verified rebuild commit →verifyre-runs → auto-merge with correct assets onmain.