CVE-2026-44359: how one pull request could hijack Meshtastic's build pipeline
A CVSS 10 GitHub Actions "pwn request" -- and the pattern that keeps compromising open-source supply chains

A single pull request -- from anyone with a GitHub account -- could have handed an attacker Meshtastic's firmware signing keys, its self-hosted build servers, and write access to the master branch. That is CVE-2026-44359, a CVSS 10.0 flaw in the meshtastic/firmware GitHub Actions pipeline, and it is a textbook example of the CI/CD "pwn request" that keeps compromising open-source supply chains.
Scores as of 20 Jul 2026live record →
What actually happened
The project's main_matrix.yml workflow was triggered by the pull_request_target event. Unlike the ordinary pull_request trigger, pull_request_target runs in the base repository's trust context -- with access to repository secrets and a write-capable GITHUB_TOKEN. The workflow then checked out the pull request author's fork and ran its build and test scripts across four separate jobs, with no approval gate. Pull requests from complete strangers (author_association: "NONE") fired the pipeline automatically.
Why `pull_request_target` is a loaded gun
GitHub built pull_request_target so that trusted automation -- labelling a PR, posting a first-response comment -- can run even on contributions from forks. The catch is that it runs with the base repo's privileges. The moment a workflow using that trigger also checks out the untrusted PR head (ref: ${{ github.event.pull_request.head.ref }}) and executes it, every secret in that job is exposed to whoever opened the PR. GitHub's own Security Lab calls the pattern a "pwn request" and flatly warns that it "may lead to repository compromise." Because the attacker needs no privileges and no user interaction, the flaw scores the maximum 10.0 (CWE-94 and CWE-829).
The exploitation chain
The attack has no memory corruption, no authentication bypass -- just four steps: fork the repo, swap a script the CI will run (say bin/check-all.sh) for a payload that reads the secrets, open a pull request, and let the pipeline run it. From there it branches into three distinct compromises. The chain below maps it end to end, with the chokepoints where a defender can prevent or detect it:
CVE-2026-44359 exploitation chain -- fork PR to supply-chain compromise
- Attacker forks meshtastic/firmware — Any GitHub account. No privileges needed.
- Swap a CI-run build script in the fork — e.g. **bin/check-all.sh** with a secret-exfil payload.
- Open a pull request — author_association: NONE.
- pull_request_target auto-runs -- NO approval — Runs in BASE context: secrets + write GITHUB_TOKEN.
- Steal PPA_GPG_PRIVATE_KEY — Sign malicious .deb served over apt.
- Own the self-hosted build runners — Persistent backdoor; pivot internally.
- Write GITHUB_TOKEN: push to master — Modify releases; grab DIST_PAGES_DEPLOY_KEY.
- Supply-chain compromise: poisoned builds to users — Signed malware reaches off-grid mesh devices.
- Prevent: pull_request / workflow_run split — Never run fork code under a privileged trigger.
- Detect: Harden-Runner egress / fork-PR alert — Unexpected outbound from a build job = exfil.
The four jobs and what each one leaks
The advisory enumerates four vulnerable jobs in the workflow. Each is a different blast radius, and together they add up to full supply-chain control:
| Job | What it exposes | Impact |
|---|---|---|
| build-debian-src | PPA_GPG_PRIVATE_KEY (runs mk-build-deps on attacker debian/control) | Sign malicious .deb packages served over apt |
| check | Self-hosted "arctastic" runners (runs check-all.sh from the fork) | Persistent runner backdoor; internal pivot |
| build | Self-hosted arctastic runners | Same -- code execution on persistent infra |
| gather-artifacts | GITHUB_TOKEN with contents:write + pull-requests:write | Push to master; modify releases; repo takeover |
Am I affected?
Meshtastic itself is patched -- but the pattern is the real story, because it is everywhere. Ask two questions of your own repositories:
- Do any workflows trigger on
pull_request_target? If not, you are not exposed to this class. - Do those workflows check out the PR head (
github.event.pull_request.head.sha/.head.ref/refs/pull/N/merge) or run fork build scripts? If yes, treat it as an emergency: those runs execute untrusted code with your secrets. - Meshtastic users and integrators: update to firmware 2.7.21.1370b23 or later and only trust binaries from the official post-fix release.
How we got here
Disclosure timeline
- CVE-2025-53637 fixed in 2.6.6A command-injection in the same
main_matrix.yml(attacker-controlled branch name) is patched -- but only in the setup job. - CVE-2026-44359 disclosedReporter avivdon shows the deeper problem: the fork-checkout execution across the check, build and build-debian-src jobs was never fixed.
- CISA-ADP marks Exploitation = PoCA proof-of-concept video exists; still no observed in-the-wild abuse of the repo.
- GitHub hardens actions/checkout v7Checkout v7 refuses fork-PR code under pull_request_target by default -- an ecosystem-wide response to this class.
- NVD publishes CVE-2026-44359CVSS 10.0. Not on CISA KEV.
Find it in your own repos
You do not need a security vendor to check for this. A two-condition sweep -- workflows that are pull_request_target and check out the PR head -- keeps false positives low. Drop the following into CI as a merge gate; it exits non-zero the moment a dangerous workflow appears:
Author-written CI gate plus off-the-shelf analyzers. All are deployable as-is.
#!/usr/bin/env bash
# fail-on-pwn-request.sh -- exit 1 if a dangerous workflow is found
set -euo pipefail
hits=0
for f in $(grep -rEl 'pull_request_target' .github/workflows/ 2>/dev/null); do
if grep -Eq 'actions/checkout' "$f" && \
grep -Eq 'github\.event\.pull_request\.head\.(sha|ref)|refs/pull/[^ ]*/merge|github\.head_ref' "$f"; then
echo "DANGEROUS pwn-request pattern: $f"; hits=1
fi
done
[ "$hits" -eq 0 ] || { echo 'pull_request_target + untrusted PR checkout detected'; exit 1; }zizmor .github/workflows/ # local audit
zizmor --format=sarif .github/workflows/ > zizmor.sarif # CI gate- uses: step-security/harden-runner@v2
with:
egress-policy: audit # move to block + allowed-endpoints once baselinedAt fleet scale, Poutine (BoostSecurity) and Gato-X (Praetorian) classify pwn requests and self-hosted-runner takeover across whole orgs with a single token.
How to fix it -- properly
The fix is architectural, not a version bump. Sanitising one input just moves the problem, which is exactly how Meshtastic ended up patching the same workflow twice:
- Do not run untrusted code under
pull_request_target. Build and test forked PRs with the ordinarypull_requesttrigger (no secrets, read-only token). - If you need base-context privileges, split the work: an unprivileged
pull_requestworkflow builds and uploads an artifact; a privilegedworkflow_runworkflow consumes it and does the sensitive step -- without ever checking out fork code. - Require approval for fork runs -- pick GitHub's strongest option, "Require approval for all outside collaborators."
- Minimise the token: default-deny
permissions: {}at the top of every workflow, grant more only per job. - Pin third-party actions by full commit SHA, not a moving tag.
- Upgrade to
actions/checkout@v7, which refuses fork-PR checkouts underpull_request_targetby default.
Why this keeps happening
CVE-2026-44359 is one point on a multi-year curve of CI/CD supply-chain compromise. The tj-actions/changed-files incident (CVE-2025-30066) leaked CI secrets from ~23,000 repositories into public logs; the Nx "s1ngularity" attack abused pull_request_target to steal an npm publish token; mass campaigns like GhostAction and Megalodon industrialised CI-token theft across thousands of repos. A pipeline is a concentrated trust boundary -- one workflow holds your signing keys, deploy keys and write tokens -- and pull_request_target hands that trust to anyone who can open a pull request. Audit your pipeline with the same rigour as your production code.
Is CVE-2026-44359 a command-injection vulnerability?
Is it being exploited in the wild?
I don't use Meshtastic -- does this affect me?
What is the fix version?
Sources
- NVD -- CVE-2026-44359
- GitHub Security Advisory GHSA-mjx5-98jq-q736
- Fix commit 5716aeb -- "Cleanup GH Actions"
- GitHub Security Lab -- Preventing pwn requests
- GitHub Changelog -- safer pull_request_target checkout defaults (v7)
- Wiz -- tj-actions/changed-files supply-chain attack (CVE-2025-30066)
- The Hacker News -- Nx "s1ngularity" supply-chain attack
- zizmor -- GitHub Actions static analysis
- StepSecurity Harden-Runner
- Predecessor: NVD -- CVE-2025-53637