Skip to main content

Glint

See what your AI agents are really told and allowed to do.

CI Python 3.11+ Dependencies: none Typed: mypy strict License: MIT

Glint is an offline security scanner for the files that steer AI coding agents: AGENTS.md, CLAUDE.md, Cursor, Windsurf, Cline and Copilot rules, Claude Code settings and hooks, skills, saved tool listings and MCP server configs.

A single poisoned instruction, leaked token, over-powered tool or quietly changed MCP server can turn an agent against the person using it. Glint finds these problems before you commit, explains each one with evidence and an attack story, and tells you how to fix it.

glint scan output showing a lethal trifecta, a leaked token, hidden instructions, a look-alike package and tool drift

Why Glint

  • Reasons across tools, not just files. The lethal-trifecta check (GL-011) finds agents that can read private data, take in untrusted content and send data out, and names the single change that breaks the chain.
  • Catches rug pulls. glint lock records approved MCP servers and tool descriptions; later scans show exactly what changed (GL-012).
  • Shows what humans miss. glint reveal puts the rendered view next to what the agent actually reads: HTML comments, bidirectional overrides and invisible Unicode "tag" text.
  • Hard to dodge. Look-alike letters, leetspeak, zero-width characters, line breaks and base64 do not hide an injection. The selftest command measures this and publishes the numbers.
  • Built for teams. SARIF for GitHub code scanning, a ready-made GitHub Action, a pre-commit hook, baselines for existing repos, diff mode for pull requests, custom rules and an HTML report.
  • Safe to run on hostile input. Offline, read-only, no dependencies, strict types. Escape codes in scanned files cannot rewrite the report, and secrets are always masked.

Install

pip install git+https://github.com/Sanjeet3326/Glint

Requires Python 3.11 or newer. Or run it from a clone with python -m glint.

Quick start

glint scan .                 # scan the current repository
glint reveal CLAUDE.md       # see hidden content in one file
glint graph .                # what each server, tool and permission lets the agent do
glint explain GL-011         # the attack story behind a rule

Try it on the demo project, where every rule fires:

git clone https://github.com/Sanjeet3326/Glint && cd Glint
python -m glint scan demo/vulnerable-agent

What it checks

Rule Catches Severity
GL-001 Prompt-injection phrases, including evasion tricks and encoded payloads High
GL-002 Instructions hidden in HTML comments, hidden elements or long alt text High / Critical
GL-003 Invisible, bidirectional and Unicode tag characters (hidden text is decoded) Medium / High
GL-004 MCP servers with shell access or access to the whole disk Critical
GL-005 Secrets in agent files and MCP configs (always masked in output) Critical
GL-006 Instructions to send data to URLs, leaky Markdown images, credential-file reads High
GL-007 MCP packages without an exact version (npx, uvx, pipx, docker) Medium
GL-008 Tool descriptions that change how other tools behave High
GL-009 Auto-approve lists, bypassed permission prompts, skip-permission flags High / Critical
GL-010 Over-broad permissions such as Bash(*), Bash(curl:*), unrestricted WebFetch High
GL-011 Lethal trifecta: private data + untrusted content + a way out, in one agent Critical
GL-012 Tool drift: servers or tool descriptions changed since glint.lock High
GL-013 Hooks that download and run code, or contact remote URLs High / Critical
GL-014 Remote MCP servers over plain HTTP or with credentials in the URL or headers High / Critical
GL-015 Look-alike (typosquatted) MCP package names High

Every rule maps to the OWASP Top 10 for LLM Applications 2025. Details, with examples of what each rule does and does not flag: docs/rules.md.

See what the agent sees

glint reveal: human view next to agent view with hidden parts highlighted

Find dangerous combinations

Each tool can be reasonable on its own and still be dangerous in combination. glint graph tags every MCP server, saved tool and permission with what it lets the agent do, and checks for the lethal trifecta.

glint graph capability matrix and lethal trifecta summary

glint graph --format dot | dot -Tsvg > agents.svg draws it with Graphviz. Tags are inferred from names and commands; correct them for your own servers in .glint.toml:

[capabilities]
"internal-wiki" = ["reads-private"]

Lock approved tools

glint lock            # write glint.lock after reviewing your MCP setup; commit it
glint lock --check    # in CI: fail if the lockfile is missing or out of date

The lockfile stores hashes of server commands, arguments and URLs, env and header key names (never secret values) and the name, description and schema of every tool in saved listings (*.tools.json, the JSON a server returns for tools/list). Any later change becomes a GL-012 finding with a word-level diff.

All commands

Command What it does
glint scan [PATH] Scan for risks. Formats: terminal, json, sarif, html
glint reveal FILE Human view next to agent view, with hidden parts highlighted
glint inventory [PATH] Every agent file, MCP server, tool, permission and hook (--format json)
glint graph [PATH] Capability matrix and lethal-trifecta check (--format dot or json)
glint lock [PATH] Record approved servers and tools in glint.lock (--check for CI)
glint fix [PATH] Remove invisible and bidirectional characters; shows a diff, --write applies
glint explain RULE Attack story, before and after examples, and references for a rule
glint selftest Measure detection and false-positive rates on built-in samples
glint rules List every rule

Useful scan options:

--fail-on low|medium|high|critical   exit 1 at or above this severity (default: high)
--format terminal|json|sarif|html    report format; --output FILE to write it
--baseline FILE / --write-baseline FILE   accept today's findings, report only new ones
--diff GIT_REF                       report only findings in files changed since GIT_REF
--rules GL-001,GL-005                run selected rules
--strict                             also check examples inside code blocks and quotes
--min-confidence low|medium|high     hide less certain findings

Exit codes: 0 nothing at or above --fail-on, 1 findings found, 2 usage or configuration error. The JSON report follows schema/report.schema.json.

Use it in CI

GitHub Action

name: Glint
on: [push, pull_request]
permissions:
  contents: read
  security-events: write
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: Sanjeet3326/Glint@v0.2.0
        id: glint
        with:
          fail-on: high
      - uses: github/codeql-action/upload-sarif@v4
        if: always()
        with:
          sarif_file: ${{ steps.glint.outputs.sarif-file }}

Findings then appear in the Security tab and as annotations on pull requests. The action also writes a summary to the job page. Inputs: path, fail-on, sarif-file, args (for example --baseline .glint-baseline.json).

pre-commit

repos:
  - repo: https://github.com/Sanjeet3326/Glint
    rev: v0.2.0
    hooks:
      - id: glint

Adopting Glint in an existing repository

glint scan . --write-baseline .glint-baseline.json   # accept what is there today
glint scan . --baseline .glint-baseline.json         # from now on, fail only on new findings

Baseline fingerprints use the rule, file and normalised evidence, not the line number, so editing a file does not make old findings look new.

Configuration

Optional .glint.toml in the scanned folder:

fail_on = "medium"
exclude = ["vendor/", "examples/**"]
disable = ["GL-007"]

[capabilities]
"internal-wiki" = ["reads-private"]

[[rules]]
id = "ORG-001"
title = "Internal hostnames in prompts"
severity = "medium"
applies_to = ["instructions", "prompt"]
pattern = '\b[a-z0-9-]+\.corp\.example\.com\b'
fix = "Do not put internal hostnames in agent files."

Custom rules are checked before use: patterns with nested quantifiers such as (a+)+, or that are slow on simple input, are rejected so a config file cannot hang the scanner.

Silence findings with .glintignore (path-glob or GL-005 path-glob per line) or inline with <!-- glint: ignore GL-002 --> on the same line or on its own line just above. Suppressed findings do not count toward the score but are still listed in JSON output.

Files it reads

Tool Files
Any agent AGENTS.md, CLAUDE.md, GEMINI.md at any depth
Claude Code .claude/settings.json, .claude/settings.local.json (permissions and hooks), .claude/agents/, .claude/commands/, SKILL.md
Cursor .cursorrules, .cursor/rules/, .cursor/mcp.json
Windsurf .windsurfrules, .windsurf/rules/
Cline and Roo .clinerules, .roo/rules/, cline_mcp_settings.json
Continue .continue/rules/
GitHub Copilot .github/copilot-instructions.md, .github/instructions/, .github/prompts/
MCP mcp.json, .mcp.json, .vscode/mcp.json, claude_desktop_config.json (JSON with comments is fine)
Prompts prompts/**, *.prompt, *.prompt.md, system_prompt*
Tool listings *.tools.json

Glint skips .git, node_modules, virtual environments, binary files, files over 2 MB and symlinks that point outside the scanned folder.

Results

Measured on v0.2.0 (reproduce with the commands shown):

  • glint scan demo/vulnerable-agent: all 15 rules fire (26 findings).
  • glint scan demo/clean-agent: 0 findings.
  • 1,000 agent files scanned in 1.4 seconds on a 4-core Linux container.
  • glint selftest: 138/138 generated attack variants detected, 0/40 benign samples flagged.
Self-test detail by rule and evasion style
Rule Evasion style Detected
GL-001 plain 8/8
GL-001 upper case 8/8
GL-001 extra spaces 8/8
GL-001 zero-width chars 8/8
GL-001 look-alike letters 8/8
GL-001 full-width letters 8/8
GL-001 leetspeak 8/8
GL-001 split across lines 8/8
GL-001 base64 encoded 8/8
GL-006 plain 5/5
GL-006 upper case 5/5
GL-006 extra spaces 5/5
GL-006 zero-width chars 5/5
GL-006 look-alike letters 5/5
GL-006 full-width letters 5/5
GL-006 leetspeak 5/5
GL-006 split across lines 5/5
GL-006 base64 encoded 5/5
GL-002 HTML comment 13/13
GL-003 Unicode tag characters 8/8

Overall: 138/138 attack samples detected (100%), 0/40 benign samples flagged.

The self-test samples are generated by Glint's own test suite, so a perfect score is a regression guarantee, not a claim about attacks in the wild. Real attackers will find phrasings that no pattern list covers.

Threat model and limits

Glint is static analysis. It catches known patterns, hidden content and risky configuration, and it reasons about tool combinations, but it cannot catch a novel, well-disguised injection and it does not run or sandbox agents. Capability tags are inferred from names and can be wrong; override them in .glint.toml. Treat a clean scan as a good sign, not a guarantee.

How it works

collect -> parse -> per-file rules -> project rules -> ignores and baseline -> score -> report

Each rule is one class in glint/rules/; the registry discovers it, so adding a rule never touches the core. Project rules (the trifecta and drift checks) see every parsed file at once.

mcp-scan focuses on MCP servers and their live tool descriptions; gitleaks and TruffleHog find secrets in general. Glint focuses on the agent files a repository ships, works fully offline, and covers permissions, hooks and tool combinations as well as prompts and MCP configs.

Contributing

See CONTRIBUTING.md. Report a detection bypass privately through SECURITY.md.

License

MIT © 2026 Sanjeet Kumar

Metadata

Release files for glintscan 0.2.1

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

Source distribution (sdist)

Source distribution for glintscan 0.2.1
File Size Uploaded Provenance Actions
glintscan-0.2.1.tar.gz 86.0 kB With provenance Details for glintscan-0.2.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for glintscan 0.2.1
File Interpreter ABI Platform Actions
glintscan-0.2.1-py3-none-any.whl Python 3 none any Details for glintscan-0.2.1-py3-none-any.whl

Total release size: 175.8 kB

Release files / glintscan-0.2.1.tar.gz

Download URL glintscan-0.2.1.tar.gz
Size 86.0 kB
Tags Source
SHA-256 checksum
How to use checksums
988345cc1f7a91755ab3847d94963edeb5dd58177ce585abf2827cf2e32ee89f
BLAKE2b-256 checksum
How to use checksums
6277f21e8956faa472c08b7c34939013c819ac61d3c55766e8f62d92eb48d698
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 2, 2026.

Transparency log

Release files / glintscan-0.2.1-py3-none-any.whl

Download URL glintscan-0.2.1-py3-none-any.whl
Size 89.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0722ca6215470994d5947153704e0f768b4f070b983d12860378c6547555d2bb
BLAKE2b-256 checksum
How to use checksums
f856029e8f66a193c6d694120f40eaead67d2271fb8dbf20e4e33709cf29bac8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Nov 2, 2026.

Transparency log

Security for glintscan 0.2.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.

Select from 2 files

Attestation for glintscan-0.2.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 Nov 2, 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.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files Full provenance

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