Vigilante reads a pull request and lists the new powers that the pull request adds. A power is an action that a change lets code, CI, a build, or an AI agent do. Examples are the first subprocess call in a package, a CI token that can push, a new MCP server, and a new install script.
Your security team approves powers in a vigilante.lock file. If a pull request adds a power that is not in the lock, the check fails.
By default, Vigilante does not run code from the repository that it checks. It reads the files and resolves calls by type. It uses Capslock for Go, the TypeScript type checker for JavaScript and TypeScript, and Pyright for Python. These tools read code, and they do not run it. Vigilante also downloads the locked packages from their public registries and reads them. If you set [engines] rust = "typed", Vigilante builds the Rust code in a Docker container that has no network access (docs/dependencies.md).
Why
AI agents open more pull requests than people can read line by line. A one-line change can change what each later agent run and CI job can do. Examples are a change to .mcp.json, .claude/settings.json, a workflow, or a postinstall script. Vigilante shows these changes at the top of the pull request. It uses the same format for each language and each type of file.
Example
An agent opens a pull request that exports invoices. Vigilante gives this report:
Vigilante: this pull request adds 6 new powers
Severity Scope Power What it means Evidence Status HIGH services/billing(code)execCan run other programs services/billing/billing/export.py:5 via export.export → subprocess.runnot in lock HIGH .mcp.json(agent)mcp_server:fs-tools: npx -y fs-tools-mcpThe agent connects to an MCP server .mcp.json:3not in lock MEDIUM .github/workflows(ci)third_party_action:acme-tools/publish-actionThe workflow runs a third-party action .github/workflows/release.yml:12not in lock MEDIUM .github/workflows/release.yml(ci)token_write:contentsThe CI token can write to the repository .github/workflows/release.yml:6not in lock MEDIUM .github/workflows/release.yml(ci)secret:PYPI_TOKENThe workflow reads a secret .github/workflows/release.yml:14not in lock MEDIUM .claude/settings.json(agent)tool_allow:Bash(curl:*)The agent can use a tool without asking .claude/settings.json:3not in lock Result: fail. 6 powers are not in vigilante.lock. Run
vigilante lockand commit the file.
The same pull request also added a second network call to services/billing, the allow rules Bash(pytest:*) and Read, and a call to actions/checkout. Vigilante does not report them, for these reasons:
- The package already used the network.
- An allow rule for a test runner has a low risk.
Readonly reads files.- The
actions/actions are first party.
What it checks
| Surface | Files | Powers |
|---|---|---|
| Code | Rust, JavaScript, TypeScript, Python, Ruby, C#, Java, and Go | exec, network, files, native, dynamic_code, read_system_state, modify_system_state, system_calls |
| Code, through dependencies | Go with Capslock. JavaScript, TypeScript, Python, Java, Rust, C#, and Ruby with the call graph of Vigilante over the locked packages. Calls resolve by type in JavaScript, TypeScript, and Python, and through the class hierarchy in Java and C#. | Each code power, with the call path. For Go, all 13 Capslock capabilities, for example operating_system, runtime, arbitrary_execution, and unanalyzed. |
| CI | .github/workflows/*.yml |
token_write, oidc, untrusted_trigger, third_party_action, secret |
| AI agents | .claude/settings.json, .mcp.json, .cursor/mcp.json, .vscode/mcp.json, .codex/config.toml, .gemini/settings.json |
tool_allow, hook, mcp_server, skip_permissions |
| Build | package.json install scripts, build.rs, setup.py, .husky/, .pre-commit-config.yaml |
install_hook, git_hook |
Vigilante reports a power only the first time that it appears in a scope. For code, a scope is the nearest package root. For Go, a scope is the Go package. Vigilante skips tests, fixtures, and vendored code. docs/powers.md tells you about each power and the rules that keep the report short.
A finding is exec, network, or native that your package reaches through its own code. This rule is the same in each language. All other results are notes:
- another power that your own code reaches;
- a power that your package reaches only through a dependency, or through another package of the same repository;
- a new package on a call path to a power.
Notes do not make the check fail. For example, a new dependency that reaches the network is a note. docs/dependencies.md tells you how Vigilante reads packages.
Install
Vigilante is one static binary for Linux and macOS, on x86_64 and arm64. Use the package manager that your team uses. The command is always vigilante.
| Package manager | Command |
|---|---|
| npm | npm install --save-dev @theonly1me/vigilante or npx @theonly1me/vigilante |
| PyPI | pip install vigilante-scan or uvx --from vigilante-scan vigilante |
| Homebrew | brew install theonly1me/tap/vigilante |
| Cargo | cargo install vigilante --locked |
| GitHub Releases | Download vigilante-<target>.tar.gz from the releases page. |
Each release file has a build attestation. To make sure that an archive comes from the release workflow of this repository, run this command:
gh attestation verify vigilante-x86_64-unknown-linux-musl.tar.gz --repo theonly1me/vigilante
Vigilante does not support Windows. To check Go code, Vigilante needs go and capslock. To install Capslock, run go install github.com/google/capslock/cmd/capslock@v0.3.3. The GitHub Action installs both.
Quick start
Run these commands in the root of your repository.
| Command | What it does |
|---|---|
vigilante scan |
Shows each power in the repository. |
vigilante lock |
Writes vigilante.lock. Commit this file. |
vigilante diff --base origin/main |
Shows the powers that your branch adds, compared with its merge base. |
vigilante check |
Fails if vigilante.lock does not agree with the repository. |
diff and check write Markdown. For other tools, add --format json or --format sarif.
| Exit code | Meaning |
|---|---|
| 0 | Pass |
| 1 | A power is not in the lock, the lock is not current, or a deny rule matches. |
| 2 | Error, for example a file that Vigilante cannot read. |
Run it on each pull request
Add .github/workflows/vigilante.yml:
name: Vigilante
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
vigilante:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
persist-credentials: false
- uses: theonly1me/vigilante@v0.1.1
On a pull request, the action runs vigilante diff against the base branch. On a push, it runs vigilante check. The action writes the report to the job summary. The job needs no secrets, so it also works on pull requests from forks.
Then make your security team the owner of the lock in CODEOWNERS. Also turn on "Require review from Code Owners".
vigilante.lock @your-org/security
vigilante.toml @your-org/security
.github/ @your-org/security
After this change, each pull request that adds a power must change vigilante.lock. The security team must approve that change. docs/github-action.md gives the full setup. It also tells you how to protect the check and how to use Vigilante in other CI systems.
Use it with AI agents
Tell your agents to run vigilante diff --base origin/main before they open a pull request. If an agent adds a power on purpose, tell it to run vigilante lock. The pull request then shows the new powers, and the change to the lock asks for the correct review.
Configuration
Vigilante works with no configuration. To change what it reports, add vigilante.toml:
[scan]
exclude = ["examples/**"]
[policy]
deny = [{ scope = "services/**", capability = "exec" }]
[ci]
trusted_owners = ["your-org"]
In a pull request, Vigilante reads vigilante.toml from the merge base. So a pull request cannot change the rules that check it. docs/configuration.md lists each key and the lock format. It also tells you how to add rules for your own wrappers.
What Vigilante is not
- It is not a malware detector. It shows what changed, and a person decides if the change is safe.
- It does not follow calls that the code makes at run time, such as reflection,
eval, or metaprogramming. - It uses no AI to find or sort powers. The same input gives the same output.
- It downloads packages only from public registries and from the registries that you allow. It keeps them in a cache.
Contribute
Read CONTRIBUTING.md. To report a security problem, read SECURITY.md. docs/README.md lists all the documentation.
License
You can use Vigilante under the Apache License 2.0 or the MIT license.
Metadata
Release files for vigilante-scan 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Actions Reset | |||
|---|---|---|---|---|
| vigilante_scan-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_2_x86_64.whl | Python 3 | none | Linux glibc 2.17+ x86-64, Linux musl 1.2+ x86-64 | Details for vigilante_scan-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_2_x86_64.whl |
| vigilante_scan-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_2_aarch64.whl | Python 3 | none | Linux musl 1.2+ ARM64, Linux glibc 2.17+ ARM64 | Details for vigilante_scan-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_2_aarch64.whl |
| vigilante_scan-0.1.1-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details for vigilante_scan-0.1.1-py3-none-macosx_11_0_arm64.whl |
| vigilante_scan-0.1.1-py3-none-macosx_10_12_x86_64.whl | Python 3 | none | macOS 10.12+ x86-64 | Details for vigilante_scan-0.1.1-py3-none-macosx_10_12_x86_64.whl |
Total release size: 22.9 MB
Release files / vigilante_scan-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_2_x86_64.whl
| Download URL | vigilante_scan-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_2_x86_64.whl |
|---|---|
| Size | 6.1 MB |
| Tags | Linux glibc 2.17+ x86-64 Linux musl 1.2+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
83f3f60027d96faa52fbebec75673f6be0a7e0f360db6cdb9b2bddd8a3e0d603
|
|
BLAKE2b-256 checksum How to use checksums |
5d2febf20015ac4acfaa3648118f74dc30ad63e986bc41a9465f961e06ff6c00
|
| 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 16, 2026.
Transparency logRelease files / vigilante_scan-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_2_aarch64.whl
| Download URL | vigilante_scan-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_2_aarch64.whl |
|---|---|
| Size | 5.8 MB |
| Tags | Linux glibc 2.17+ ARM64 Linux musl 1.2+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
d5e0d2e87816a2097ea3f1cd86a5516ea46566c9c2d0e27ea826690cf20f88ce
|
|
BLAKE2b-256 checksum How to use checksums |
c3e8c3c08a1750e4c72de881bc67247aecd09b2ac0df7382496760fdf2df9f19
|
| 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 16, 2026.
Transparency logRelease files / vigilante_scan-0.1.1-py3-none-macosx_11_0_arm64.whl
| Download URL | vigilante_scan-0.1.1-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 5.5 MB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
8a8bd180e54d26afd233cb1cf011f81f6bbc22aa128fca2e6219aae9d4c178db
|
|
BLAKE2b-256 checksum How to use checksums |
797740331491296f219c419a3d2ccd0248e99d1b87108a75f052910aa73f2566
|
| 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 16, 2026.
Transparency logRelease files / vigilante_scan-0.1.1-py3-none-macosx_10_12_x86_64.whl
| Download URL | vigilante_scan-0.1.1-py3-none-macosx_10_12_x86_64.whl |
|---|---|
| Size | 5.6 MB |
| Tags | Python 3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
4bf8b3c36dbc089538de180013db5b0a3bca2291eaa3ffb8bab5c5aa7286f599
|
|
BLAKE2b-256 checksum How to use checksums |
8a3fa7c691b363aef43c6a6b667a0459e4f5d269e0a107ee068a5ac45d0109a5
|
| 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 16, 2026.
Transparency logSecurity for vigilante-scan 0.1.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 4 files in this release have been uploaded with provenance metadata.
Attestation for vigilante_scan-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.musllinux_1_2_x86_64.whl
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 16, 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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.