SRE-901: Install Renovate from the lockfile - #93
Conversation
… actions Install Renovate locally with --ignore-scripts instead of globally, scope the App token to the calling repo, and drop contents: write.
PR SummaryMedium Risk Overview
Reviewed by Cursor Bugbot for commit db91559. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Pull request overview
This PR hardens the centralized Renovate reusable workflow to reduce blast radius if a compromised dependency or action enters CI, by tightening permissions, narrowing GitHub App token scope, and disabling install-time scripts.
Changes:
- Drops workflow
permissions.contentsfromwritetoread. - Scopes the GitHub App token to the calling repository using
owner+repositoriesderived from$GITHUB_REPOSITORY. - Installs Renovate into
$RUNNER_TEMPwithnpm install --ignore-scriptsand runs it via an explicit binary path; explicitly setsRENOVATE_ALLOW_SCRIPTS=falseandRENOVATE_IGNORE_SCRIPTS=true.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…untime npm ci cannot pull a package published after the lockfile was written, which is what let the malicious cacheable-request into the tree. This also removes the renovate@<spec> string, so a package.json value can no longer redirect the install.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (3)
.github/workflows/housekeeping-dependencies.yml:175
- Even after adding the install dir to
PATH, invoking Renovate via the resolved binary path avoids any accidental PATH shadowing and matches the PR’s stated approach ("invoked through the resolved binary path").
run: renovate
.github/workflows/housekeeping-dependencies.yml:6
- The workflow now treats the Renovate version as coming from
package-lock.json, but thepull_request.pathsfilter still only watchespackage.json. A PR that only updatespackage-lock.json(e.g., a Renovate bump) would not trigger this workflow’s PR dry-run, reducing coverage for the new install path.
# The Renovate version is locked in /package-lock.json and managed by Renovate itself.
#
# Uses OIDC token to resolve the correct checkout ref for the lockfile.
.github/workflows/housekeeping-dependencies.yml:143
- PR description says Renovate is installed under
$RUNNER_TEMP/renovate, but the workflow currently installs into the workspace ($PWD/node_modules). Installing into$RUNNER_TEMPbetter matches the stated hardening goal and avoids mixing the tool install with the checked-out repo content.
- name: Install Renovate
run: |
npm ci --ignore-scripts --no-audit --no-fund
echo "$PWD/node_modules/.bin" >> "$GITHUB_PATH"
🌟 What is the purpose of this PR?
Install Renovate from the lockfile this repo already ships, instead of a bare
npm install --global renovate@<version>that resolves fresh at run time.🔗 Related links
🚫 Blocked by
None.
🔍 What does this change?
housekeeping-dependencies.yml:npm install --global "renovate@$VERSION"→npm ci --ignore-scripts --no-audit --no-fundagainst the committedpackage-lock.json.npm ciresolves nothing at run timepackage-lock.jsonadded to the checkout'ssparse-checkout, which is why the lockfile was previously invisible to the workflowRENOVATE_VERSIONare deleted — with norenovate@<spec>string left, apackage.jsonvalue cannot redirect the installnode_modules/.bingoes on$GITHUB_PATH, soRun Renovatekeeps its barerun: renovateowner+repositoriesto the calling repo, resolved from$GITHUB_REPOSITORYcontents: write→read. Renovate commits through the API with the App tokenRENOVATE_ALLOW_SCRIPTSandRENOVATE_IGNORE_SCRIPTSset explicitly, restating Renovate's defaultslint.yml: theValidate renovate configstep had the same bare global install and now usesnpm ci --ignore-scripts.Pre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
📜 Does this require a change to the docs?
The changes in this PR:
🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
--ignore-scriptsskips the optionalre2native build. Renovate falls back to native RegExp and logs it; it was already being skipped in practice. Reversible with an explicitnpm rebuild re2.workflow_dispatchin a consumer repo after merge.🐾 Next steps
🛡 What tests cover this?
lint.ymlruns on this PR and exercises its own changed step.housekeeping-dependencies.ymlis in its ownpull_requesttrigger'spaths, and a PR run forcesRENOVATE_DRY_RUN=extract, so the install and startup are exercised without any write.lockfileVersion: 3, and agrees withpackage.json, sonpm ciwill not fail its consistency check.❓ How to test this?
Lintrun on this PR covers thelint.ymlchangeUpdate dependenciesrun on this PR (dry-runextract) covers the installHousekeepingmanually in a consumer repo📹 Demo
Not applicable, CI-only change.