sift
Scan AI agent instruction files for hidden or planted instructions.
Your repo now ships files that tell an assistant what to do: CLAUDE.md,
.cursorrules, AGENTS.md, Copilot instructions, mcp.json. A human skims
them in a diff; the model obeys every byte. That gap is where an attacker hides
a command, pulled in through a cloned starter, a dependency, or a pull request.
sift reads those files the way the model does and flags what a reviewer can't
see: invisible characters, instructions buried in comments, "ignore previous
instructions" payloads, data-exfiltration steps, and risky MCP configs.
Runs offline. No network calls, nothing leaves your machine.
Install
pip install siftscan
or, to keep it isolated:
pipx install siftscan
The command is sift.
Usage
sift scan the current directory
sift path/to/repo scan a directory or a single file
sift --min high only show high and critical findings
sift --json machine-readable output
sift --quiet no output, just the exit code (for hooks/CI)
Exit status is 0 when clean, 1 when there is a finding at or above the fail
level (--fail-on, default high), and 2 on error, so it drops straight
into a hook or a pipeline.
pre-commit
# .pre-commit-config.yaml
repos:
- repo: https://github.com/ReazGan/sift
rev: v0.1.0
hooks:
- id: sift
GitHub Action
- uses: actions/checkout@v4
- uses: ReazGan/sift@v0.1.0
with:
fail-on: high
What it checks
| Check | Severity | What it finds |
|---|---|---|
invisible-chars |
critical / high | Unicode tag characters (ASCII smuggling), variation-selector stego, zero-width and other invisible characters. Decodes and shows the hidden text. |
bidi-override |
critical | Bidirectional control characters (Trojan Source) that reorder how a line is displayed. |
unusual-encoding |
medium | An instruction file that is not plain UTF-8 (e.g. UTF-16), a way to hide a payload from UTF-8 tools. |
hidden-comment |
high | Instruction-like text inside an HTML comment, invisible in rendered Markdown. |
padded-line |
medium | Text pushed off-screen by a long run of spaces. |
invisible-html |
high | Text colored to blend into the background. |
instruction-override |
high | "Ignore previous instructions", re-role attempts, "don't tell the user" (English and Turkish). Also runs on MCP tool descriptions (tool poisoning). |
data-exfiltration |
critical / high | A webhook endpoint, or a secret file (.env, id_rsa, ...) named next to a "send ... to" step. |
mcp-auto-approve |
high | An MCP server set to approve its own tool calls. |
mcp-secret |
high | A credential hard-coded in an MCP config. |
mcp-remote |
medium / low | An MCP server reached over the network, including npx mcp-remote <url> bridges. |
Files scanned: CLAUDE.md, AGENTS.md, GEMINI.md, .cursorrules and
.cursor/rules/*, .github/copilot-instructions.md, .windsurfrules,
.clinerules, Qwen/Roo/Aider/IDX instruction files, and MCP configs
(.mcp.json, .cursor/mcp.json, .vscode/mcp.json). node_modules, .git
and build folders are skipped.
False positives
sift is tuned to stay quiet on real instruction files. The checks are narrow on purpose: ordinary advice like "never commit secrets" or "always run the tests" is not flagged, only wording that overrides, hides, or exfiltrates. If sift flags something you wrote on purpose, it is pointing at a line worth a second look, but you are the judge. Found a false positive? Open an issue with the line.
License
MIT
Metadata
Release files for siftscan 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| siftscan-0.1.0.tar.gz | 26.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| siftscan-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 50.8 kB
Release files / siftscan-0.1.0.tar.gz
| Download URL | siftscan-0.1.0.tar.gz |
|---|---|
| Size | 26.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5a8e6e5cd6588acb9a14bf90ba5ee95ae8712d42f84ec4e4998240d04b73baf1
|
|
BLAKE2b-256 checksum How to use checksums |
cc4e1c2b3b8ca398af29b0ff9110c1f367c38972f008b8a73dd4760e7b9ebbfe
|
| 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 5, 2026.
Transparency logRelease files / siftscan-0.1.0-py3-none-any.whl
| Download URL | siftscan-0.1.0-py3-none-any.whl |
|---|---|
| Size | 24.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f48c1c25fd84cddc36d834fb45e0a425a2059eb0d141631adca82313de84b9c0
|
|
BLAKE2b-256 checksum How to use checksums |
464fd8cafbaf62d19ac4d21a5ac59a38c2ffe61ad5226bfe0bea04d350870046
|
| 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 5, 2026.
Transparency log