top of page

One Pull Request, Four Doors: Our Free GitHub Check Now Covers Packages, MCP Servers, GitHub Actions and Agent Instruction Files

Writer: Patrick Duggan
Patrick Duggan
58 minutes ago
4 min read

A pull request can hand your build and your AI agents four different things to trust: a package to install, an MCP server to launch, a GitHub Action to run, and an instruction file for the agent to obey. Today we released version 1.1.0 of the DugganUSA Checks Action, and it now checks all four before the merge. It is free, it runs in your repository, and every verdict comes with the evidence IDs you need to check it yourself.





Door 1: packages


npm, PyPI and RubyGems manifests and lockfiles. Each new or changed package is checked against our malicious-package deny-list, its registry reputation, and the published vulnerabilities for the exact version. Since this morning, a package that is malware from its first release blocks every later version too, even ones its malware record never listed; we wrote up why a malware record can be wrong in both directions. Pull requests are diff-aware, so new transitive packages in a lockfile are checked. That is where hijacked-dependency worms like Mini Shai-Hulud land.



Door 2: MCP servers


Any MCP config the PR touches (mcp.json, claude_desktop_config.json, and the Claude, VS Code, Gemini and Cursor settings files) goes to Dredd. Dredd checks whether we know the server, whether a published CVE affects this version, and whether anything in its dependency graph is known to be compromised. A launcher we cannot prove, such as a wrapper script, an extra argument or an environment variable that redirects the install, is reported as ambiguous and fails the job. It is never skipped.



Door 3: GitHub Actions (new)


Every uses: owner/repo@ref line in your workflows is a dependency that runs with your repository's secrets. The March 2025 tj-actions/changed-files compromise (CVE-2025-30066) showed what that costs: an attacker rewrote the action's version tags, and every workflow using them ran the attacker's code. The Action now reads every uses: line:


  • Exact version tag: checked against published advisories. tj-actions/changed-files at v45.0.7 returns review with the advisory; v46.0.1 returns allow.

  • Full commit SHA: pinned, but a pin to a compromised commit is still compromised. If the action has advisories, the SHA gets review.

  • Floating tag (v4, v4.1): review. The tag can move under you, which is exactly what happened with tj-actions.

  • A repository that does not exist, is under 30 days old, is archived or was renamed: review. A typo like actions/checkuot is caught this way.

  • Branch refs and expressions: unknown, never skipped.

OSV, the public vulnerability database, does not evaluate version ranges for GitHub Actions, so our API evaluates them itself.



Door 4: agent instruction files (new)


CLAUDE.md, AGENTS.md, GEMINI.md, .cursorrules, Copilot instruction files, Cursor rules and Claude commands, agents and skills are instructions your coding agent reads on every run. Poisoning one is prompt injection delivered through the agent's own configuration. The dangerous version is invisible: zero-width characters, bidirectional overrides, and Unicode TAG characters, the technique Johann Rehberger named ASCII smuggling, where each invisible character encodes one letter so a whole hidden sentence can ride inside a normal-looking line. An editor shows nothing and most diffs show nothing, but the model reads all of it.


The Action scans these files locally, with no API call, and blocks on hidden characters. For TAG characters it decodes the hidden text and prints it in the report, so the reviewer reads exactly what the model would have read. Credit to Socket's TrapDoor research for showing this attack in agent instruction files.



We broke it seven times before you got it


The GitHub Actions check did not ship on the first try. Our own security reviews and live tests found seven defects before release:


  • A SHA pin returned allow without checking advisories.

  • Version tags were parsed differently from how GitHub resolves them.

  • A lookup we could not evaluate returned allow, and repository names were not normalized.

  • The API's input schema rejected the new ecosystem name.

  • A reputation step short-circuited the advisory check.

  • Skipping reputation to fix that let a typosquatted action through.

  • This afternoon: a crafted name could steer our authenticated GitHub lookup to other paths, and the lookup could reveal whether a private repository exists.

Each one is fixed, tested and deployed, and we checked the live API against real actions before tagging the release. The rule we hold it to is simple: anything the check cannot prove becomes review or unknown, never allow.



Add it in two minutes


The Action is at github.com/pduggusa/dugganusa-checks-action, and the README has a workflow you can copy: about twenty lines of YAML that run on every pull request. Reference it as pduggusa/dugganusa-checks-action@v1 and you get 1.1.0 now and future 1.x fixes automatically. If you prefer to pin a SHA, which is what we tell everyone else to do, pin the v1.1.0 commit.


An API key is optional. Without one, package checks share the anonymous rate (currently 10 a minute and 50 a day per source IP), and GitHub-hosted runners share IPs with other users, so a large pull request can run out. Anything left unchecked is reported as unknown and fails the job; it is never passed. A free account key (register, tiers) raises the limits. The same checks are on our MCP server if you would rather have your agent ask before it installs anything.


If it blocks something it should not, open an issue on the repository. A false positive is a bug to us, and we will publish the correction on our updates page like the others.


We checked each verdict quoted in this post against the live API before publishing. At least 5% of what remains is still wrong, and we don't know which.


If this was useful, or if it wasn't, rate it at the bottom of the page. It is the only direct signal we get.




Every indicator in this post is in the feed. Free.

1.58M+ IOCs, STIX 2.1 / TAXII, 88% novel vs ThreatFox, exploited-CVE leads ahead of CISA. No credit card — a free API key in 30 seconds, and you can audit every claim above against the live endpoints.



Was this useful? Thirty seconds, no cookies, no tracking, no third parties, your address hashed and never stored. If the box below does not load, the same question lives at https://analytics.dugganusa.com/nps.html?post=one-pull-request-four-doors-our-free-github-check-now-covers-packages-mcp-servers-github-actions



Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
bottom of page