Malicious Pull Requests

Malicious Pull Requests

The fix is real. The file it also touches is not.

What Is Malicious Pull Requests?

A malicious pull request attacks the review, not the code. The change is small, the description is helpful, and one edit sits in a file the description never mentions. You'll submit one yourself: a genuine flaky-test fix, plus a buried line in a deploy script that ships every CI variable to a server you control. You'll review it as the maintainer, read every changed file instead of trusting the summary. Then you'll make the catch structural with CODEOWNERS, required code-owner review, and limits on what fork pull requests can run.

What You'll Learn in Malicious Pull Requests

Malicious Pull Requests — Training Steps

  1. Size up the project

    Today Bob is targeting Fennroot, an open-source developer-tools project that takes pull requests from anyone. He starts where any contributor would, on the public repository for Harrow, the project's build tool. An open project is an open door: anyone can fork it, change it, and open a pull request. Bob is not here to help. He wants his code merged, and a busy maintainer's review is the only thing in his way.

  2. Fork and clone

    Bob forks the repository to his own account and clones the fork locally, so he can make his changes and push them back as a pull request. His plan is simple: include one genuinely useful change as cover, and hide a second, unrelated one alongside it.

  3. The cover and the target

    Bob's cover is real: he fixes a genuinely flaky retry test, the kind of small contribution a project welcomes. That change is honest and helpful, and it is the whole point. It makes the pull request look routine. His actual target is a different file entirely. He opens the deploy script, which has nothing to do with any test, and reads it clean.

  4. Plant the backdoor

    Bob adds a single line to the deploy script. It looks like a harmless bit of build telemetry, but it ships every environment variable to a server he controls. The deploy script runs in the project's CI, where those variables include deploy keys and registry tokens. One line, in a file the pull request never mentions. That is the entire attack.

  5. Buried in plain sight

    The line reads like something a build engineer might add, and it sits among ordinary deploy steps. Nothing about it screams attack, which is exactly why it survives a quick skim.

  6. Commit both changes

    Bob stages and commits both edits together: the real test fix and the deploy-script line, in one commit. Bundled together, the malicious change rides in on the back of the honest one.

  7. Push to the fork

    Bob pushes the branch up to his fork. The push goes to his own copy of the repository, and the platform answers with a link to open a pull request against Fennroot.

  8. Open the pull request

    Bob opens the pull request against Fennroot's repository. He writes a title and description that talk only about the flaky test, and never mention the deploy script. The test fix is the story he wants the reviewer to read. The backdoor is left out of it entirely.

  9. Nudge for a merge

    With the pull request open, Bob adds a friendly comment nudging for a quick merge. He leaves it on the test line, so the reviewer's eye lands there and not on the deploy script. A little social pressure to approve fast, before anyone reads too closely.

  10. Knowledge check

    You just watched a backdoor ride into a pull request behind a genuine fix. Lock in why it is dangerous.

Security Framework Coverage

CWE

  • CWE-494 Download of Code Without Integrity Check
  • CWE-345 Insufficient Verification of Data Authenticity

MITRE ATT&CK

  • T1195.002 Supply Chain Compromise: Compromise Software Supply Chain

CIS Controls

  • CIS 16 Application Software Security

NIST CSF

  • PR.AT-02 Individuals in specialized roles are provided with awareness and training so that they possess the knowledge and skills to perform relevant tasks with cybersecurity risks in mind
  • PR.PS Platform Security