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-ignoreto 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
.envfiles — 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_USERNAMEinscan.ymlwith 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:
- Builds Linux amd64/arm64 and Windows amd64/arm64 in parallel on
ubuntu-latestusingcross - Builds macOS arm64 natively on
macos-latest - 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyl_secret_leaks-0.5.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: pyl_secret_leaks-0.5.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.5 MB
- Tags: PyPy, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a3937816561a38098dd58315d6d52f399754e4732f9f3b65512697ab18d48004
|
|
| MD5 |
1a025e2dbfb55cf73fde5f9c78e2ed6f
|
|
| BLAKE2b-256 |
8f28e89505683fa9451f7a966237ba894bf78e13306a3852185f18e2740fdb56
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyl_secret_leaks-0.5.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
a3937816561a38098dd58315d6d52f399754e4732f9f3b65512697ab18d48004 - Sigstore transparency entry: 983311992
- Sigstore integration time:
-
Permalink:
adrian-lorenz/pyl@f5ee555bf611e85e8a453f8c79c70c1c0cc87151 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/adrian-lorenz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f5ee555bf611e85e8a453f8c79c70c1c0cc87151 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file pyl_secret_leaks-0.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: pyl_secret_leaks-0.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.5 MB
- Tags: PyPy, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b3151d73864ff926dbdbe0fde664afda0fdded11964f370c1e99479e9364ea4
|
|
| MD5 |
2927b6ed8820e9fbdf9310058177313b
|
|
| BLAKE2b-256 |
831880dc5dbcd79af1d1610d7881e11e5c5773a8449505ad0c555cdeb4dce2da
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyl_secret_leaks-0.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
0b3151d73864ff926dbdbe0fde664afda0fdded11964f370c1e99479e9364ea4 - Sigstore transparency entry: 983311995
- Sigstore integration time:
-
Permalink:
adrian-lorenz/pyl@f5ee555bf611e85e8a453f8c79c70c1c0cc87151 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/adrian-lorenz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f5ee555bf611e85e8a453f8c79c70c1c0cc87151 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file pyl_secret_leaks-0.5.0-cp38-abi3-win_amd64.whl.
File metadata
- Download URL: pyl_secret_leaks-0.5.0-cp38-abi3-win_amd64.whl
- Upload date:
- Size: 1.2 MB
- Tags: CPython 3.8+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3dd3d5a269cbc3073855069dee46951e0c204859e6a10790a39513bab243e1e7
|
|
| MD5 |
6bcdcd8519700fd13be030ab68c73b27
|
|
| BLAKE2b-256 |
ad0b15e7b44ce2991c1f5b918e56de1034f36f7beaf3569c95cfeea9275ce8c9
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyl_secret_leaks-0.5.0-cp38-abi3-win_amd64.whl -
Subject digest:
3dd3d5a269cbc3073855069dee46951e0c204859e6a10790a39513bab243e1e7 - Sigstore transparency entry: 983312000
- Sigstore integration time:
-
Permalink:
adrian-lorenz/pyl@f5ee555bf611e85e8a453f8c79c70c1c0cc87151 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/adrian-lorenz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f5ee555bf611e85e8a453f8c79c70c1c0cc87151 -
Trigger Event:
workflow_dispatch
-
Statement type:
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
- Download URL: pyl_secret_leaks-0.5.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.5 MB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b9300cec3313a0d571e4f3a66fb56d5b17f3b04f84fb528d3ae6841f3b2ef427
|
|
| MD5 |
70a948942931715e83710b5b189e8ee7
|
|
| BLAKE2b-256 |
1e53c5ccc1f5c62f655ed68121d6c8364ae815844b8539c72084b74635e48827
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyl_secret_leaks-0.5.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
b9300cec3313a0d571e4f3a66fb56d5b17f3b04f84fb528d3ae6841f3b2ef427 - Sigstore transparency entry: 983312002
- Sigstore integration time:
-
Permalink:
adrian-lorenz/pyl@f5ee555bf611e85e8a453f8c79c70c1c0cc87151 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/adrian-lorenz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f5ee555bf611e85e8a453f8c79c70c1c0cc87151 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file pyl_secret_leaks-0.5.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: pyl_secret_leaks-0.5.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.5 MB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8732c543f31176b2eedc704394fa5f5a5c14a1d5068303c593d7fd97193e9625
|
|
| MD5 |
3e4cd76f2a21206bfab77333812c0e30
|
|
| BLAKE2b-256 |
f9286acbbe80daa3dec67c6cf22ac4d6e71fadbaddcffac770c2c61ba9d8d4aa
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyl_secret_leaks-0.5.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
8732c543f31176b2eedc704394fa5f5a5c14a1d5068303c593d7fd97193e9625 - Sigstore transparency entry: 983311993
- Sigstore integration time:
-
Permalink:
adrian-lorenz/pyl@f5ee555bf611e85e8a453f8c79c70c1c0cc87151 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/adrian-lorenz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f5ee555bf611e85e8a453f8c79c70c1c0cc87151 -
Trigger Event:
workflow_dispatch
-
Statement type:
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
- Download URL: pyl_secret_leaks-0.5.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 2.7 MB
- Tags: CPython 3.8+, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f67acae6c96e84ad8508d50cd9df0e3f7deb7052d03f23f7c909fd8da1da23bc
|
|
| MD5 |
e93177fba0ab26ddcc32db4770f67a2c
|
|
| BLAKE2b-256 |
c09f02d4ec1ec98630c9f988d0475c2477d5ce4f9c173a554d1dbf6c649981bc
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyl_secret_leaks-0.5.0-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl -
Subject digest:
f67acae6c96e84ad8508d50cd9df0e3f7deb7052d03f23f7c909fd8da1da23bc - Sigstore transparency entry: 983311997
- Sigstore integration time:
-
Permalink:
adrian-lorenz/pyl@f5ee555bf611e85e8a453f8c79c70c1c0cc87151 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/adrian-lorenz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f5ee555bf611e85e8a453f8c79c70c1c0cc87151 -
Trigger Event:
workflow_dispatch
-
Statement type: