diff-sentry
Catch a malicious pull request before you merge it.
diff-sentry reads a change the way an attacker hopes you won't: it treats the diff as untrusted data, looks for the shapes that real supply-chain attacks use, and reports evidence rather than an opinion.
The fastest way to use it is as a GitHub Action. It needs no API key, no model, and no network access, so it runs on fork pull requests under the read-only token they already get.
# .github/workflows/diff-sentry.yml
name: diff-sentry
on: pull_request
permissions:
contents: read
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # the scan diffs against the PR base
- uses: qazbnm456/diff-sentry@v0.7.1
That is the whole setup. The job fails when an indicator at or above high fires.
What it catches
| Family | Examples |
|---|---|
| Workflow configuration | pull_request_target that checks out the PR head (the pwn-request that broke AsyncAPI) by ref:, by a hand-rolled git fetch, or by opting back in with allow-unsafe-pr-checkout: true; plus permissions: write-all and CODEOWNERS reassignment |
| Obfuscation | base64 that decodes to a shell payload, _0x… machine-mangled JavaScript, high-entropy blobs |
| Execution | pipe-to-shell installs, ${IFS} space-evasion, detached child processes, inline node -e, fetch-to-disk droppers |
| Exfiltration | secrets reaching a network sink, cross-process /proc/<pid>/mem reads, OAST callback services, IPFS and permaweb gateways |
| Diff-presentation evasion | payloads shoved past the viewport by a long whitespace run, bidi-override and zero-width characters |
| Provenance | forged [bot] identities, bot-mimicking new accounts, accounts created days before the event, profiles that describe an autonomous agent, unsigned or identity-mismatched commits, a fork deleted after the PR |
| Author-controlled channels | a PR branch name carrying shell syntax, slash-command comments that fire issue_comment workflows |
Campaign memory (watch only) |
an account or payload host already flagged in another repository, an edit that removes a flagged payload, a burst of changes from a new account |
| Prompt injection | instructions aimed at an LLM reviewer or triage workflow |
A plain workflow edit, or a pull_request_target on its own, is medium, below the failure threshold, so a benign workflow PR does not break your build. Deleted lines are not scanned, so removing a payload is not flagged. How it works explains the tuning.
Inputs
| Input | Default | Purpose |
|---|---|---|
fail-on |
high |
Severity that fails the build (info/low/medium/high/critical). |
report-only-paths |
none | Newline-separated globs scanned but never gated. For files whose job is to carry attack patterns: rule bodies, security fixtures, prompt templates, docs that tabulate payloads. |
base-sha |
derived | Override the commit to diff against. |
version |
matches the action tag | The diff-sentry release to install from PyPI. local installs from the current checkout instead, which is how this repo scans its own PRs with the rules in that PR. |
Outputs: failed, hit-count, max-severity, and report (a JSON path).
Do not reach for pull_request_target
Sooner or later you will want the scan to post its results as a PR comment, and a pull_request job on a fork PR has a read-only token. The tempting fix is pull_request_target, which is the exact misconfiguration that opened the AsyncAPI "Miasma" compromise, and which this action reports as critical.
Do it the safe way instead: keep the scan on pull_request with no secrets, upload the report as an artifact, and post it from a separate workflow_run job that runs the base branch's code and never checks out the PR head. diff-sentry's own rules make the same distinction, so the safe shape does not trip them.
Evidence a model cannot suppress
An LLM reviewer can be argued out of its conclusion by the diff it reads. The Action runs no model at all. In the full pipeline, the rules record their hits before any model takes a turn, and the alert is derived from those hits, so a prompt injection can skew a verdict but cannot remove the evidence (details).
Beyond the Action
https://github.com/user-attachments/assets/d200aee8-263b-483e-ad55-f90ae69f3ab0
The studio console: paste a real payload, watch the detection stream live, then read the evidence-framed verdict.
If you operate the infrastructure, or maintain a project where a wrong call is expensive, the rest of the system runs locally with a model endpoint you choose:
- Deep classification: a reasoning model reads a PR, issue or push in a sandbox and returns a verdict next to the evidence. See How it works.
- The studio: a local console that streams a run as it happens. See
studio/README.md. - Watch: monitors a list of repositories, alerts the moment the rules fire, and remembers the accounts and payload hosts it has seen. See Watching a watchlist.
- Trajectories for training: every run is recorded, and
exportturns the traces into a reward-free dataset for fine-tuning a smaller planner. See The full pipeline.
None of this is needed for the Action, and none of it sends your code anywhere you did not configure yourself.
Limits
A strong prompt injection can skew a model's verdict, though never the evidence. Some pipe-to-shell shapes, and a secret that reaches a network call across lines, are missed. An external watcher cannot stop an attack that fires the moment a PR opens. Honest limits lists the known gaps.
Documentation
- How it works: severity tuning, the evidence union, the full pipeline, running it locally, and the incidents the tests reconstruct.
- Watching a watchlist: the monitor, its alerts, its archive, and what the account dossier holds.
- Honest limits: what the rules and the pipeline do not see.
- Development: the test suites and CI.
- CHANGELOG
License
MIT. Built on rlm-harness.
Metadata
Release files for diff-sentry 0.7.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| diff_sentry-0.7.1.tar.gz | 857.1 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| diff_sentry-0.7.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.1 MB
Release files / diff_sentry-0.7.1.tar.gz
| Download URL | diff_sentry-0.7.1.tar.gz |
|---|---|
| Size | 857.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
949c1e95da7f8b9ba8274940c051a279be5022fec186937ca89139f28fb468ce
|
|
BLAKE2b-256 checksum How to use checksums |
28430e8a7746f03030ca854ddd8997ce994383b43ca1f0f4156043bc69944981
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logRelease files / diff_sentry-0.7.1-py3-none-any.whl
| Download URL | diff_sentry-0.7.1-py3-none-any.whl |
|---|---|
| Size | 235.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
13f9a5df9bffe7c55608cec171b4e505bd71d6cb3efe55a1c03db89d89943c7f
|
|
BLAKE2b-256 checksum How to use checksums |
32fabd491a267c8133342805bccd2ad62031fc6be63fc822256509292f32bbd2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logSecurity for diff-sentry 0.7.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for diff_sentry-0.7.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.