Skip to main content

pyl — fast secret scanner for your codebase

Project description

pyl

pyl — fast secret scanner for your codebase

A lightweight, zero-config secret scanner written in Rust — available as CLI tool and Python library. Scans source code for accidentally committed secrets, credentials, and sensitive data.


Features

  • 89 built-in detection rules covering cloud providers, LLMs, databases, HTTP auth, and more
  • Multiple output formats — pretty-printed, JSON, and SARIF
  • GitHub Actions integration — writes a formatted Job Summary to $GITHUB_STEP_SUMMARY
  • Inline suppression — annotate lines with # pyl-ignore to silence known false positives
  • Configurable via pyl.toml — restrict file extensions, exclude paths, disable rules
  • Sorted output — findings ordered by severity (CRITICAL → HIGH → MEDIUM → LOW → WARNING), then by file and line
  • Smart false-positive filtering — skips template variables, shell variables, and attribute references
  • Binary-safe — skips non-text files automatically
  • Respects .env files — always excluded from scanning

Installation

From source

git clone https://github.com/YOUR_USERNAME/pyl.git
cd pyl
cargo install --path .

via pip

pip install pyl-secret-leaks
pyl check .

Pre-built binaries

Download the latest binary for your platform from the Releases page:

Platform File
Linux x86_64 pyl-linux-amd64
Linux ARM64 pyl-linux-arm64
Windows x86_64 pyl-windows-amd64.exe
macOS Apple Silicon pyl-macos-arm64
# Linux / macOS — make executable and move to PATH
chmod +x pyl-linux-amd64
sudo mv pyl-linux-amd64 /usr/local/bin/pyl

Python Library

After installing via pip install pyl-secret-leaks, you can use pyl directly from Python — e.g. to scan text before sending it to an LLM:

from pyl import scan_text

findings = scan_text("My API key is sk-proj-abc123xyz...")
for f in findings:
    print(f.rule_id, f.severity, f.secret)

# Disable specific rules:
findings = scan_text(text, disable_rules=["http-insecure-url"])

Each finding has the attributes: rule_id, description, severity, line_number, line, secret, tags.


CLI Usage

# Scan the current directory
pyl check

# Scan a specific path
pyl check --source ./src

# JSON output (e.g. for piping)
pyl check --format json

# SARIF output (e.g. for GitHub Code Scanning)
pyl check --format sarif

# Verbose mode (shows every file scanned/skipped)
pyl check --verbose

# Include WARNING-level findings in detail output
pyl check --warnings

# Limit file size (default: 1024 KB)
pyl check --max-size 512

# Use a custom config file
pyl check --config /path/to/pyl.toml

# Write a GitHub Actions Job Summary
pyl check --github-summary

# List all built-in rules
pyl rules

# Generate a default config file
pyl init-config

Exit codes

Code Meaning
0 No findings (or only LOW/WARNING severity)
1 At least one CRITICAL, HIGH, or MEDIUM finding

Warnings

WARNING-level findings (e.g. plain HTTP URLs) are counted in the summary but suppressed in the detail output by default to reduce noise. Use --warnings to display them:

pyl check --warnings

The summary line always shows the WARNING count regardless of this flag.


Configuration

Run pyl init-config to create a pyl.toml in the current directory:

[scan]
# Leave empty to scan all files (except .env and .git).
# Restrict to specific extensions:
# extensions = ["py", "js", "ts", "go", "yaml", "toml"]
extensions = []
exclude_paths = []
exclude_files = []

[rules]
# Disable specific rules by ID:
# disable = ["jwt-token", "http-insecure-url"]
disable = []

pyl.toml is auto-loaded from the current directory if present.


Suppression

Add a suppression comment to any line to skip it:

api_url = "http://internal-service/api"  # pyl-ignore

Supported markers: # pyl-ignore, # noqa-secrets, # nosec-secrets

pyl also automatically skips common false positives:

Pattern Example
Python f-strings / Jinja postgresql://{DB_USER}:{DB_PASSWORD}@...
Shell variables $DB_PASSWORD
Python %-format %(password)s
Attribute references settings.DB_PASSWORD, config.secret_key
localhost HTTP URLs http://localhost:8080

Detection Coverage

Category Examples
Cloud / VCS AWS keys, GitHub/GitLab PATs, Google API keys, Stripe, Slack, NPM, Docker Hub
LLM / AI OpenAI, Anthropic, Cohere, Mistral, Hugging Face, Replicate, Groq, Perplexity
Azure / M365 Tenant/Client IDs, Storage keys, Service Bus, Cosmos DB, Teams webhooks, Graph API
Frontend / SaaS Firebase, Mapbox, Sentry DSN, Contentful, Shopify, Algolia, Linear, Postman, PlanetScale, Cloudflare
Databases PostgreSQL, MySQL, MongoDB, Redis, MSSQL, Elasticsearch, RabbitMQ, JDBC
Observability Datadog, New Relic, Grafana, Honeycomb, Lightstep, OTLP endpoints
HTTP Auth Basic Auth headers, Bearer tokens, credentials in URLs, curl commands
Crypto PEM private keys (RSA, EC, DSA, OpenSSH)
Generic High-entropy secrets matching common naming patterns, JWT tokens

Run pyl rules to see all 89 rules with IDs, severity levels, and tags.


Severity Levels

Level Description
CRITICAL Direct credential exposure — rotate immediately
HIGH Sensitive token or key with significant access
MEDIUM Potentially sensitive, context-dependent
LOW Low-risk exposure (e.g. publishable keys)
WARNING Best-practice violation (e.g. plain HTTP URLs) — shown with --warnings

GitHub Actions

Use pyl in your own pipeline

Add this job to any workflow to scan for secrets and write the results to the GitHub Job Summary:

jobs:
  pyl:
    name: pyl secret scan
    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
      - uses: actions/checkout@v4

      - name: Install pyl
        run: |
          curl -sSfL \
            https://github.com/adrian-lorenz/pyl/releases/latest/download/pyl-linux-amd64 \
            -o /usr/local/bin/pyl
          chmod +x /usr/local/bin/pyl

      - name: Run scan
        run: pyl check --format markdown >> "$GITHUB_STEP_SUMMARY"

Or install via pip:

      - name: Install pyl
        run: pip install pyl-secret-leaks

      - name: Run scan
        run: pyl check --format markdown >> "$GITHUB_STEP_SUMMARY"

Two ready-to-use workflows are also included in .github/workflows/.

Secret scan on every push — scan.yml

Runs pyl check on every push and pull request, uploads results to GitHub Code Scanning as SARIF.

Replace YOUR_USERNAME in scan.yml with your GitHub username before pushing.

Release workflow — release.yml

Triggered automatically when you push a version tag:

git tag v1.0.0
git push origin v1.0.0

The workflow:

  1. Builds Linux amd64/arm64 and Windows amd64/arm64 in parallel on ubuntu-latest using cross
  2. Builds macOS arm64 natively on macos-latest
  3. Creates a GitHub Release with all 5 binaries attached and an auto-generated changelog

The release body includes a download table and install instructions automatically.


Project Structure

src/
├── lib.rs        Library root, PyO3 Python bindings
├── main.rs       CLI entry point, CLI dispatch
├── cli.rs        CLI types (Cli, Commands, OutputFormat)
├── config.rs     Configuration loading (pyl.toml)
├── rules.rs      Built-in detection rules and Severity type
├── scanner.rs    File and directory scanning logic
└── output.rs     Output formatters (pretty, JSON, SARIF, GitHub Summary)

License

MIT — Copyright (c) 2026 Adrian Lorenz <a.lorenz@noa-x.de>

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pyl_secret_leaks-0.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.5 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

pyl_secret_leaks-0.5.0-cp38-abi3-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.8+Windows x86-64

pyl_secret_leaks-0.5.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ x86-64

pyl_secret_leaks-0.5.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.5 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.17+ ARM64

pyl_secret_leaks-0.5.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (2.7 MB view details)

Uploaded CPython 3.8+macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file pyl_secret_leaks-0.5.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pyl_secret_leaks-0.5.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a3937816561a38098dd58315d6d52f399754e4732f9f3b65512697ab18d48004
MD5 1a025e2dbfb55cf73fde5f9c78e2ed6f
BLAKE2b-256 8f28e89505683fa9451f7a966237ba894bf78e13306a3852185f18e2740fdb56

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyl_secret_leaks-0.5.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on adrian-lorenz/pyl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyl_secret_leaks-0.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pyl_secret_leaks-0.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 0b3151d73864ff926dbdbe0fde664afda0fdded11964f370c1e99479e9364ea4
MD5 2927b6ed8820e9fbdf9310058177313b
BLAKE2b-256 831880dc5dbcd79af1d1610d7881e11e5c5773a8449505ad0c555cdeb4dce2da

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyl_secret_leaks-0.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on adrian-lorenz/pyl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyl_secret_leaks-0.5.0-cp38-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for pyl_secret_leaks-0.5.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 3dd3d5a269cbc3073855069dee46951e0c204859e6a10790a39513bab243e1e7
MD5 6bcdcd8519700fd13be030ab68c73b27
BLAKE2b-256 ad0b15e7b44ce2991c1f5b918e56de1034f36f7beaf3569c95cfeea9275ce8c9

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyl_secret_leaks-0.5.0-cp38-abi3-win_amd64.whl:

Publisher: release.yml on adrian-lorenz/pyl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyl_secret_leaks-0.5.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyl_secret_leaks-0.5.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b9300cec3313a0d571e4f3a66fb56d5b17f3b04f84fb528d3ae6841f3b2ef427
MD5 70a948942931715e83710b5b189e8ee7
BLAKE2b-256 1e53c5ccc1f5c62f655ed68121d6c8364ae815844b8539c72084b74635e48827

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyl_secret_leaks-0.5.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on adrian-lorenz/pyl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyl_secret_leaks-0.5.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pyl_secret_leaks-0.5.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 8732c543f31176b2eedc704394fa5f5a5c14a1d5068303c593d7fd97193e9625
MD5 3e4cd76f2a21206bfab77333812c0e30
BLAKE2b-256 f9286acbbe80daa3dec67c6cf22ac4d6e71fadbaddcffac770c2c61ba9d8d4aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyl_secret_leaks-0.5.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on adrian-lorenz/pyl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyl_secret_leaks-0.5.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for pyl_secret_leaks-0.5.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 f67acae6c96e84ad8508d50cd9df0e3f7deb7052d03f23f7c909fd8da1da23bc
MD5 e93177fba0ab26ddcc32db4770f67a2c
BLAKE2b-256 c09f02d4ec1ec98630c9f988d0475c2477d5ce4f9c173a554d1dbf6c649981bc

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyl_secret_leaks-0.5.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: release.yml on adrian-lorenz/pyl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page