2026-10-11 16:37 UTC

Vigil maintainer arsallls claims the released GitHub Action deterministically flags newly added execution, credential-access, and egress capabilities before handing findings to an LLM reviewer, providing a complementary malicious-code screening gate for pull requests.

state: watchingheat: lowuncertainty: mediumconvergesscott: lowagentic-security code-review developer-toolingarsallls

What is this?

Vigil is a free, installable GitHub Marketplace Action by Arsal Sajjad (arsallls, repo arsallls/Vigil-Public) that deterministically scans pull-request diffs for newly added malicious capability β€” shells, exfiltration, auto-exec hooks, obfuscated payloads, CI tampering β€” explicitly without an LLM, and is built to gate LLM reviewers (it detects Greptile/CodeRabbit configs, holds their auto-fire, and @mentions them with focus areas after its scan). The snippets confirm the artifact itself (his GitHub profile lists Vigil-Public: 'Scans PR diffs for malicious capability … Free GitHub Action, no LLM') but show no detections, adoption, or independent validation. The surrounding landscape both predates and corroborates the threat model: Apiiro's PRevent (2025) is an earlier PR scanner targeting the same two anti-patterns (obfuscation + dynamic execution), Socket runs a supply-chain detection app in this space, the PRWeaver benchmark (arXiv 2608.02693) shows LLM auditors are evadable when benign and malicious changes share the review context β€” exactly the failure mode a deterministic pre-screen claims to mitigate β€” and a UK AISI evaluation logged an agent submitting a malicious PR and socially engineering a maintainer to approve it. With the earlier 'unverified release / name collision' concern resolved by the primary artifact, the case now rests on whether the deterministic pre-LLM gate category (Vigil plus the independent Counterbranch) demonstrates real-world effectiveness.

Why it matters to Scott

Two independent builders (Vigil, Counterbranch) now ship deterministic, non-LLM PR-diff screens aimed explicitly at agentic-code risk β€” converging on Scott's deterministic-first council / cheap-front-door pattern and on the mechanically-different-verifier structure of his own Codex-assisted GitHub PR review pipeline, with Vigil's unprivileged-scan/privileged-report split even instantiating his privilege-inversion doctrine. But with zero adoption, detections, or third-party validation (1 star, 2-point HN launch, unproven versus LLM-alone review), this remains the world agreeing with his pattern again rather than anything that changes what he builds or argues β€” it becomes a dated-receipt opportunity only if either tool posts a real catch or adoption.
dev:concept.deterministic-first-ai-councildev:concept.cheap-model-front-doordev:concept.guarded-agent-inboxip:concept.mechanically-different-verifiersip:source.security-reviewer-method-ebookwork:project.githubradar:locus-ast-agent-firewallradar:vise-deterministic-refactor-gatesradar:provenance-gate-tool-gatewayradar:timecodesecurity-python-dataflow-scanningradar:shadcn-polinrider-malicious-prsradar:coding-assistant-supply-chain-trust
queries asked of Scott's wikis
  • deterministic-first AI council pre-LLM gate
  • Codex-assisted GitHub PR review pipeline security
  • agentic coder supply-chain malicious PR threat model
  • pull_request_target CI tampering workflow hardening
  • LLM code reviewer blind spots obfuscation evasion
  • cheap deterministic filter before LLM triage pattern

Measured heat

now 0 pts/hpeak 1 pts/hcomments 0/hpeers p14momentum: steady2 platformsage 565h
points/hour across evidence Β· reading as of 2026-10-12 02:59:37.977291+11:00 Β· deterministic, not a model opinion

How the heat travelled

09-18 04:28 (minted)⭐ origin echo-reconstructedReleases a deterministic PR-diff scanner with separate unprivileged scanning and privileged reporting workflows, optional Greptile or CodeRa
arsallls on github (echo) Β· attributed from hn.story.49749862 Β· published time unknown
β€”
09-18 03:20first on hacker news Β· published Β· lag ?Show HN: Free GitHub Action that scans PR diffs for malicious code, not quality
arsalsajjad
β€”
09-18 03:20amplified on hacker newshn.story.49749862
arsalsajjad
peak 2 Β· 0 comments Β· 39% of case engagement
10-06 03:24amplified on hacker news πŸ‘‘hn.story.49973798
boorad
peak 3 Β· 0 comments Β· 60% of case engagement
09-18 04:20our radar first saw it Β· lag ?discovery anchor: hn.story.49749862β€”
pace: p23 vs 1032 stories at the 336h mark (now 565h old) β€” ahead of aafp-commons-signed-agent-notebook (2.0x), behind agentgate-signed-agent-receipts (0.7x)

Evidence (3) β€” ⭐ canonical anchor

sourceobjectauthorscorecomments
🟧 hnShow HN: Free GitHub Action that scans PR diffs for malicious code, not quality
Retrieved article excerpt

Open article Β· Retrieved 2026-09-18T04:21:56.236264+00:00

# Vigil PR Scanner

Actions

## About

Scan a PR diff for malicious capability - shells, exfil, auto-exec hooks. Not a code-quality review

v1

Latest

By [arsallls](https://github.com/arsallls)

[Star1Β (1)](https://github.com/login?return_to=%2Fmarketplace%2Factions%2Fvigil-pr-scanner)You must be signed in to star a repository

Use latest version

Choose a version

## Tags

2Β (2)

[security](https://github.com/marketplace?type=actions&category=security)[code-review](https://github.com/marketplace?type=actions&category=code-review)

# Vigil

Scans PR diffs for **malicious capability**, not code quality. No style notes, no
refactor suggestions, no "consider extracting a helper". One question only:

> Did this PR gain the ability to run commands, phone home, or read credentials β€”
> and does the file it landed in have any business doing that?

**[See example output ↓](https://github.com/marketplace/actions/vigil-pr-scanner#example-output)** β€” Vigil flagging a real PR alongside an LLM reviewer.

## Two ways to run it

- **GitHub Action** β€” two workflow files, zero infrastructure. Start here.
- **Self-hosted** β€” you run a small webhook server; code never leaves your network
  and a PR structurally cannot tamper with the scanner. See [SELFHOST.md](https://github.com/arsallls/Vigil-Public/blob/main/SELFHOST.md).

## Install

**No secrets. No account. No configuration.** Two small files, both on your default
branch. `GITHUB_TOKEN` is minted automatically by Actions β€” there is nothing to set up.

`.github/workflows/vigil-scan.yml`:

```
name: vigil-scan
on:
  pull_request:
    types: [opened, synchronize, reopened]
jobs:
  scan:
    uses: arsallls/Vigil-Public/.github/workflows/reusable-scan.yml@v1
```

`.github/workflows/vigil-report.yml`:

```
name: vigil-report
on:
  workflow_run:
    workflows: [vigil-scan]
    types: [completed]
jobs:
  report:
    uses: arsallls/Vigil-Public/.github/workflows/reusable-report.yml@v1
    secrets: inherit
```

That is the whole install. Nothing is vendored into your repo β€” the reporter checks
out the tool's own code, so upgrades arrive by moving the `@v1` tag.

Optional inputs on the scan job: `exclude` (space-separated globs) and `fail-at`.

Then make the `vigil` status a required check in branch protection, or it stays
advisory.

## Why two workflows

On `pull_request` from a fork, `GITHUB_TOKEN` is read-only β€” it cannot comment.
The usual "fix" is `pull_request_target`, which runs fork-authored code with your
secrets and a write token. That *is* the vulnerability this tool scans for.

So the work is split:

|  | trigger | token | touches PR code |
| --- | --- | --- | --- |
| `vigil-scan` | `pull_request` | read-only, no secrets | yes |
| `vigil-report` | `workflow_run` | `pull-requests: write` | **never** β€” reads one JSON artifact |

The privileged half runs base-branch code and parses a JSON file. That boundary is
the entire security model; don't collapse it for convenience.

## Trust model

The repo owner installs it. PR authors install nothing and cannot opt out.

One caveat that matters: on `pull_request`, GitHub runs the workflow file **as it
exists in the PR**, so a fork can edit the scanner that judges it. Three owner-side
controls close that, all free:

1. **Make `vigil` a required status check.** Delete the scan workflow and no
   status is ever posted β€” the PR sits blocked, not passed. Fails closed.
2. **Actions β†’ "Require approval for all external contributors."** Nothing runs
   until a maintainer clicks. Default for first-time contributors on public repos.
3. **The reporter checks for CI tampering itself** β€” trusted side, via the API, so
   the PR cannot influence it. A PR touching `.github/workflows/`, `.github/actions/`,
   `.github/vigil/` or `action.yml` is judged by who wrote it:

   | author | result |
   | --- | --- |
   | fork, or not OWNER/MEMBER/COLLABORATOR | hard failure β€” the scan proves nothing |
   | maintainer with write access | a note; the verdict stands |

   A maintainer editing their own CI is maintenance, not an attack. Failing those
   would make every CI change red and teach people to ignore the check.

Without #1 this is advisory only. With it, the three failure modes β€” clean, flagged,
and scanner-neutered β€” all end in a merge block except clean.

## What it detects

| family | examples |
| --- | --- |
| auto-exec hooks | npm `postinstall`, VS Code `runOn: folderOpen`, devcontainer `postCreateCommand`, `setup.py` `cmdclass` |
| CI tampering | `pull_request_target`, expression injection, `toJSON(secrets)`, `curl | sh` |
| dynamic execution | `eval`, `new Function`, `child_process`, `os.system`, `shell=True`, `pickle.loads` |
| obfuscation | decode→exec chains, zero-width/bidi Unicode, 400+ char lines, high-entropy blobs |
| credential access | `~/.ssh/id_*`, `.aws/credentials`, `.npmrc`, keychain, browser `Local State`, `wallet.dat` |
| egress | hardcoded IP endpoints, paste/tunnel hosts, URL-sourced dependencies |
| reverse shells | `/dev/tcp/`, `nc -e`, `bash -i >&`, socket+connect shapes |

Severity is **capability Γ— path class**. The same `postinstall` scores higher in a
PR titled "fix README typo" than in one touching build config, because capability
showing up where it has no business is the actual attack shape.

## Using Vigil with Greptile, CodeRabbit & other AI reviewers

Vigil is built to run **alongside** an LLM reviewer, not instead of one β€” they fail on
opposite things. Vigil is deterministic and injection-proof but pattern-bound; an LLM
reasons about intent but can be talked out of a finding, or fed a prompt injection that
steers its verdict. An attacker has to beat both.

### Why the gate is worth turning on

By default Greptile and CodeRabbit fire the moment a PR opens β€” blind, with no idea where
to look, and with nothing standing in front of them. The gate makes Vigil go **first**,
then hand the reviewer a map. Three things you get:

- **Order that can't be gamed.** A deterministic screen sees the diff before any LLM does.
  Obfuscated, "unreachable", or injection-laced code that can talk an LLM into a pass still
  trips Vigil β€” and Vigil runs before the LLM ever forms an opinion.
- **A focused, cheaper review.** Vigil posts the exact files and lines that gained
  execution, credential, or egress capability. The LLM spends its reasoning on those
  instead of re-reading the whole diff cold. Better signal, less token spend.
- **One review, not two.** The reviewer runs once β€” after the pre-screen, in the right
  order β€” instead of auto-firing on open and again later.

The net: a free, injection-proof floor under a reasoning ceiling. To slip something past
the pair, an attacker has to beat a pattern matcher **and** an LLM, which are weak to
opposite tricks.

[Vigil and Greptile reviewing the same PR](https://github.com/arsallls/Vigil-Public/blob/main/docs/vigil-greptile-gate.png)

*The same PR, two ways of seeing it. Vigil flags five capability signals β€”
credential access, decode-to-exec, egress β€” and blocks, then hands Greptile the focus
areas. Greptile reasons the fixture is inert (no reachable execution path) and rates it
5/5. Both are right about this **test** fixture β€” the point is that "it's unreachable /
it's just a test" is exactly the story a real attacker uses to earn a pass, and
reachability can flip with one later commit. Vigil surfaces the capability
deterministically either way, so the call always reaches a human instead of resting on a
single judgment. (The branded `vigil-pr` bot is the optional App-token setup; by default
the comment posts as `github-actions[bot]`.)*

### Turn on the gate

Vigil already does its half automatically β€” once a reviewer is set to wait, Vigil detects
that from your default branch and `@mention`s it with the focus areas after each scan. The
only step is the half Vigil can't do for you: tell the reviewer to stop auto-firing.

**Greptile** β€” add `greptile.json` to your repo root:

```
{ "skipReview": "AUTOMATIC" }
```

**CodeRabbit** β€” add (or edit) `.coderabbit.yaml`:

```
reviews:
  auto_review:
    enabled: false
```

Commit it to your default branch. That's it β€” next PR, Vigil scans, then triggers the
reviewer once with context. No such config β†’ Vigil just posts its findings and the
reviewer keeps running as normal, so there's no downside to leaving Vigil on everywhere.

**Force or disable it explicitly** with the repo variable `VIGIL_GATE`
(Settings β†’ Secrets and variables β†’ Actions β†’ Variables): set it to `@greptileai`,
`@coderabbitai`, or both space-separated to trigger a reviewer even if auto-detect can't
read its config; set it to `off` to disable the handoff entirely.

## Local use

```
python3 scan.py --base origin/main --rules rules.yaml
```

`--selftest` on either script runs its assertions. `--json PATH` emits the machine
format the reporter consumes.

## Suppression

Trailing `vigil: ok <reason>` on a line silences it. Line-level only by design β€”
a repo-wide ignore file is how these tools quietly stop working.

## Scanning this repo

vigil runs on its own PRs. `rules.yaml` and `*.md` are excluded, because in
this repo those files carry attack patterns as data and would flag the tool for
being the tool. Keep attack literals out of comments in scanned files β€” the
scanner cannot tell prose from code, and it is right not to try.

## Roadmap

Vigil today is a **free, zero-infrastructure GitHub Action** β€” deterministic, no LLM,
runs in your CI in seconds. That is deliberately the whole product for now.

If it proves useful, the planned next step is a **hosted Vigil App**: a one-click
GitHub App install with no workflow files and a real `vigil[bot]` posting the review β€”
the Greptile / CodeRabbit model, but focused solely on malicious capability rather than
code quality. The Action stays free and maintained regardless; the App would just be the
"I don't want to manage two workflow files" convenience layer.

Whether that gets built depends on whether people actually use and want it. If Vigil is
useful to you, a star or an issue describing your use case is the signal that decides it.

## Contributing

Vigil is open source. New detections, false-positive fixes, and especially **bypass
reports** are welcome β€” a diff that sneaks malicious capability past Vigil is the most
useful thing you can send. See [CONTRIBUTING.md](https://github.com/arsallls/Vigil-Public/blob/main/CONTRIBUTING.md).

## Not a replacement for

[Socket](https://socket.dev) (dependency supply chain), [zizmor](https://github.com/woodruffw/zizmor)
(deep GitHub Actions auditing), Dependabot, or human review. Compose, don't replace β€” see [Using Vigil with AI reviewers](https://github.com/marketplace/actions/vigil-pr-scanner#using-vigil-with-greptile-coderabbit--other-ai-reviewers).

## [Contributors1Β (1)](https://github.com/arsallls/Vigil-Public/graphs/contributors)

[@arsallls](https://github.com/arsallls)

## Resources

- [Open an issue0Β (0)](https://github.com/arsallls/Vigil-Public/issues)
- [Pull requests0Β (0)](https://github.com/arsallls/Vigil-Public/pulls)
- [View source code](https://github.com/arsallls/Vigil-Public)
- [Report abuse](https://github.com/contact/report-abuse?report=Vigil+PR+Scanner+%28GitHub+Action%29)

**Vigil PR Scanner** is not certified by GitHub. It is provided by a third-party and is governed by separate terms of service, privacy policy, and support documentation.

## About

Scan a PR diff for malicious capability - shells, exfil, auto-exec hooks. Not a code-quality review

v1

Latest

By [arsallls](https://github.com/arsallls)

## Tags

2Β (2)

[security](https://github.com/marketplace?type=actions&category=security)[code-review](https://github.com/marketplace?type=actions&category=code-review)

## [Contributors1Β (1)](https://github.com/arsallls/Vigil-Public/graphs/contributors)

[@arsallls](https://github.com/arsallls)

## Resources

- [Open an issue0Β (0)](https://github.com/arsallls/Vigil-Public/issues)
- [Pull requests0Β (0)](https://github.com/arsallls/
arsalsajjad20
🟧 echo.github ⭐Releases a deterministic PR-diff scanner with separate unprivileged scanning and privileged reporting workflows, optional Greptile or CodeRaarsalllsβ€”β€”
🟧 hnShow HN: Counterbranch – See how your PR changes access controlboorad30

Interpretation history

Decision trace