Repository navigation
Conversation
Define the restricted repair result contract and collect structured PR, patch, and failed-job evidence with explicit UTF-8 log truncation. Add focused artifact tests and run the automation suite in CI. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d63bcb34-3969-4d14-b422-33728176ec03
Run Copilot with scoped local tools and curated documentation access. Collect and validate actual checkout changes, while discarding edits when the worker hands the problem to a maintainer. Export a Markdown session transcript separately from the structured repair response. Cover unattended execution, repair collection, and failure handling. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d63bcb34-3969-4d14-b422-33728176ec03
Merge only pristine updates after configured CI passes. Retry eligible failures once before a permanent Copilot handoff to human review. Include path-filtered CLI workflow runs when present at the PR head. Revalidate PR identity and head before mutations, publish restricted repairs with an atomic head guard, and log merge refusals without blocking later reconciliation. Cover lifecycle and race guards. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d63bcb34-3969-4d14-b422-33728176ec03
Connect discovery, retry, merge, isolated investigation, publication, and failure reporting with scoped credentials and per-PR concurrency. Serialize main-branch merge jobs with a shared pending queue. Reconcile standard and path-filtered PR workflow completions. Load trusted automation from main, transfer evidence and repair artifacts across jobs, and document the lifecycle and trust boundaries. Preserve session transcripts and event logs as diagnostic artifacts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d63bcb34-3969-4d14-b422-33728176ec03
Select up to 32 eligible PRs per run with a partial Fisher-Yates shuffle. Skip held PRs unless native auto-merge needs disarming. Document probabilistic fairness and cover filtering, empty sets, and sampling without replacement. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d63bcb34-3969-4d14-b422-33728176ec03
Explain how trusted discovery selects PR heads independently of workflow_run events, and document the restricted worker and separate publisher boundaries. Add foreign-repository eligibility and lifecycle regression tests, including failed CI with an exhausted retry budget. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d63bcb34-3969-4d14-b422-33728176ec03
Save Git metadata outside the inference container and restore it only after the container exits. Finalize repairs from the trusted checkout on the runner instead of launching Git in the credential-bearing worker. Keep the raw response separate from the final artifact and reject nonregular response files before reading them. Preserve the existing Git commands, publication checks, and human-review boundary. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d63bcb34-3969-4d14-b422-33728176ec03
Use the job token instead of an App token for publication, suppressing push workflows and requiring approval for resulting PR workflows. Tell maintainers to review repairs before approving CI. Retain the permanent review hold and expected-head publication check. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d63bcb34-3969-4d14-b422-33728176ec03
4bde1b4 to
a89166f
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical vulnerabilities allow dependency scripts to steal the GitHub token and expose runner-only files through symlinked diagnostic uploads.
5 open issues
Dependency scripts can steal the inference token from the container · New Symlinked diagnostics can expose runner files during upload · New Stale-head retries incorrectly place eligible PRs on hold · New Dangling symlinks are mistaken for deleted files · New Dependabot workflow PRs lack the required workflow write permission · New
What changed in this PR
Adds a Dependabot maintenance pipeline that merges pristine updates after CI passes and sends persistent failures to a containerized Copilot investigation. Once investigation begins, the PR requires human review and merging.
Changes:
- Discover eligible PRs after CI completion, hourly, or manually; retry failed jobs once before investigation.
- Collect failure evidence, prepare repairs or explanations, and publish validated results while retaining a review hold.
- Add automation tests, lifecycle documentation, and seven-day retention for Copilot session artifacts.
| File | Description |
|---|---|
.github/workflows/main.yml |
Runs the automation’s test suite in CI. |
.github/workflows/dependabot-pr.yml |
Coordinates per-PR evaluation, retries, merging, investigation, and publication. |
.github/workflows/dependabot-automation.yml |
Defines discovery triggers and dispatches eligible PRs. |
.github/dependabot-automation/worker.cjs |
Invokes Copilot and collects checkout changes for validation. |
.github/dependabot-automation/repair-protocol.cjs |
Validates repair outcomes, allowed paths, and size limits. |
.github/dependabot-automation/README.md |
Documents lifecycle, trust boundaries, artifacts, and local checks. |
.github/dependabot-automation/prompt.txt |
Defines investigation, migration, and escalation instructions. |
.github/dependabot-automation/evidence.cjs |
Collects PR patches, failed-job logs, and an evidence index. |
.github/dependabot-automation/controller.test.cjs |
Tests lifecycle decisions, provenance checks, and repair safeguards. |
.github/dependabot-automation/controller.cjs |
Implements discovery, CI decisions, GitHub writes, and review holds. |
Review effort: Max (auto)
| docker run --rm --init --cpus=2 --memory=6g \ | ||
| --user "$(id -u):$(id -g)" \ | ||
| --cap-drop=ALL --security-opt=no-new-privileges \ | ||
| -e GITHUB_TOKEN -e HOME=/tmp -e COPILOT_HOME=/diagnostics/copilot \ |
There was a problem hiding this comment.
I think we should fix this one.
There was a problem hiding this comment.
On the one hand, I agree that the current docker setting cannot completely prevent a malicious dependency from obtaining GITHUB_TOKEN. On the other hand, I do not see how this limitation weakens our security posture in practice.
A dependency, by practical necessity, effectively has arbitrary code execution privileges within Action workflows for this repository. If the dependency under investigation is malicious, before we get to this point, we have already executed its install scripts (and much more) during the initial CI checks for the original Dependabot PR. If it wants to steal GITHUB_TOKEN, it would have done so already, so I don't really see the point of further hardening this part of the workflow, which already provides greater isolation than our other Actions workflows.
| diagnostics/transcript.md | ||
| diagnostics/copilot/session-state/**/events.jsonl |
There was a problem hiding this comment.
I'm having a hard time understanding this vulnerability despite multiple rounds with copilot. My sense is that the attack vector is very narrow and we can probably fix the problem by not following symlinks. I don't know if that's a viable fix though.
There was a problem hiding this comment.
As I noted in the earlier finding, a dependency effectively has arbitrary code execution privileges within Action workflows for this repository. If it wants to, it can already read everything in the workflow runtime environment and upload it to wherever it wishes—the upload job does not have any special privilege that a dependency does not already have. There is no need for a malicious dependency to perform such a convoluted attack, and closing this gap does not really help us in practice.
| } | ||
|
|
||
| async function retry() { | ||
| const pr = await requireExpectedPr(); |
There was a problem hiding this comment.
I'm not particularly worried about this one, but it looks like an easy fix so it's probably worth it.
There was a problem hiding this comment.
The automation is not intended to be concurrency-safe, especially in the presence of a non-cooperative mutator. I agree that this particular fix is not too bad. But it also does not serve any real purpose—we probably still have similar race conditions in half a dozen other places. I would just leave it be.
| if (!fs.existsSync(filename)) return { path: name, content: null }; | ||
| if (!fs.lstatSync(filename).isFile()) { | ||
| throw new Error(`Non-regular repair file rejected: ${name}`); | ||
| } |
There was a problem hiding this comment.
I don't see a situation where a dependency version migration would legitimately require introducing a broken symlink. Treating it as a file deletion is a bit strange, but not really a significant problem. I am not against fixing the detection, but I don't want to add more code just to address this rare and relatively harmless edge case.
| permission-contents: write | ||
| permission-pull-requests: read | ||
| permission-actions: read |
There was a problem hiding this comment.
The automation is supposed to perform the merge only when all CI checks already pass, so I don't see why workflow write permission is needed here.


This PR adds automation for open, non-draft Dependabot PRs that originate in this repository and target
main. The automation discovers eligible PRs after configured CI workflows finish, on an hourly schedule, or through manual dispatch.When CI passes, the automation approves and merges the PR. When CI fails, it retries the failed jobs once. If the rerun succeeds, the automation approves and merges the PR.
If the rerun fails, the automation invokes an isolated Copilot worker to investigate. Copilot either prepares a small migration or explains why a maintainer must intervene. The automation publishes the repair or explanation and requires a human to review and merge the PR, even if subsequent CI passes. It also retains the Copilot transcript and session events for seven days.
The first 5 commits form the main implementation. The remaining commits include additional documentation and code change to address security concerns.