Skip to main content

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.14.0

That is the whole setup. The job fails when an indicator at or above high fires. Add push to on: to also scan commits pushed straight to a branch. A push that bypasses branch protection can also delete this workflow, so watch and release-watch read the repository and its releases from outside.

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; a workflow pointed at a lookalike of your own GitHub owner (the litellm release built from Berri-AI/litellm); 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, Python startup hooks (.pth, sitecustomize.py), packed or downloaded code run with exec
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.
  • Release watch: compares each new release of the PyPI and npm packages you depend on with the release before it, and alerts when it carries a startup hook, a packed loader or a new install script, or was published without its usual provenance. See Watching releases.
  • Trajectories for training: every run is recorded, and export turns 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.
  • Watching releases: comparing each new PyPI or npm release, and each container image, with what came before.
  • 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.14.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for diff-sentry 0.14.0
File Size Uploaded Provenance
diff_sentry-0.14.0.tar.gz 960.0 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for diff-sentry 0.14.0
File Interpreter ABI Platform
diff_sentry-0.14.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.3 MB

Release files / diff_sentry-0.14.0.tar.gz

Download URL diff_sentry-0.14.0.tar.gz
Size 960.0 kB
Tags Source
SHA-256 checksum
How to use checksums
069c7eaf1e93e50ff674f9cf705ac4e60267c4562b7b9d83fb0035415fdf1500
BLAKE2b-256 checksum
How to use checksums
794ff1e4dab3ce337f15e5b859adfcc2462c16c8cf9bfa655269acfeb437dc63
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 22, 2026.

Transparency log

Release files / diff_sentry-0.14.0-py3-none-any.whl

Download URL diff_sentry-0.14.0-py3-none-any.whl
Size 290.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d07f97d552b1117e3a560c29ed8d91153826fbe31a2f004294c7582374c0d62f
BLAKE2b-256 checksum
How to use checksums
baa9e864455786f1da85f0169c21f101eec5c68b67a1f096a7c106ca92a794b9
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 22, 2026.

Transparency log

Security for diff-sentry 0.14.0

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.

Select from 2 files

Attestation for diff_sentry-0.14.0.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 22, 2026.

Transparency log

A 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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page