🔐 Aysal-Scan
Detect leaked secrets in your git repos — and find out exactly what damage they can cause.
Every other tool tells you "you have a leaked key."
Aysal-Scan tells you "you have a leaked AWS key — it has AdministratorAccess on your production account. Here's how to fix it."
The Difference
| Feature | TruffleHog / GitLeaks | Aysal-Scan |
|---|---|---|
| Regex-based detection | ✅ | ✅ |
| Shannon entropy analysis | ✅ | ✅ |
| Git history scanning | ✅ | ✅ |
| Is the key still active? | ❌ | ✅ |
| What permissions does it have? | ❌ | ✅ |
| Plain English remediation | ❌ | ✅ |
| Severity score with blast radius | ❌ | ✅ |
| Scan any GitHub URL directly | ❌ | ✅ |
| Interactive UI mode | ❌ | ✅ |
Architecture
flowchart TD
A1[Local directory] --> DE
A2[Git history] --> DE
A3[GitHub URL] --> DE
A4[Staged changes] --> DE
DE["🔍 Detection engine
Regex · 17+ patterns · Shannon entropy"]
DE --> DD["Deduplication
SHA-256 per raw value"]
DD --> BR["💥 Blast radius engine
Live API verify · Permission enumeration
AWS · GitHub · OpenAI · Stripe · Slack · Twilio +12"]
BR --> SS["Severity scoring + remediation
CRITICAL → HIGH → MEDIUM → LOW"]
SS --> O1[Terminal / Rich UI]
SS --> O2[SARIF output]
SS --> O3[JSON / HTML]
style DE fill:#7F77DD,color:#fff,stroke:#534AB7
style DD fill:#888780,color:#fff,stroke:#5F5E5A
style BR fill:#D85A30,color:#fff,stroke:#993C1D
style SS fill:#1D9E75,color:#fff,stroke:#0F6E56
style O1 fill:#888780,color:#fff,stroke:#5F5E5A
style O2 fill:#888780,color:#fff,stroke:#5F5E5A
style O3 fill:#888780,color:#fff,stroke:#5F5E5A
Note: Live verification applies to most providers (AWS, GitHub, OpenAI, Stripe, Slack, Twilio, npm, SendGrid, Heroku, Google). PyPI, Azure, and GCP are flagged for manual review instead — no safe verify endpoint, no tenant ID available, and avoiding audit-log noise, respectively.
Real-World Demo
Scanning a test repo with a live canary AWS key:
aysal-scan scan https://github.com/trufflesecurity/test_keys
╭─────────────────────────── 🔴 [CRITICAL] AWS Access Key ────────────────────────────╮
│ File : new_key (line 2) │
│ Secret : AKIA************ZAM2 │
│ │
│ Blast Radius: │
│ Key status : ACTIVE │
│ Account : Account: 052310077262 | User: canarytokens.com@@c20nnjzl... │
│ Permission : Could not enumerate — insufficient IAM permissions │
│ │
│ Fix: 1. Go to AWS IAM Console → Users → Security Credentials │
│ 2. Deactivate this access key immediately │
│ 3. Rotate + store in AWS Secrets Manager │
│ 4. Remove from git history with: git filter-repo │
╰──────────────────────────────────────────────────────────────────────────────────────╯
✗ FAILED — secrets detected | Exit code: 1
The blast radius engine called
sts:GetCallerIdentityagainst live AWS, confirmed the key is active, retrieved the real account ID, and escalated severity to CRITICAL — all automatically.
Install
pip install aysal-scan
Or from source:
git clone https://github.com/Rolex-1905/aysal-scan
cd aysal-scan
pip install -e .
Requires Python 3.11+
Quick Start
# Scan current directory
aysal-scan scan .
# Interactive mode — guided, no flags needed
aysal-scan ui
All Commands
# ── Scan targets ────────────────────────────────────────────────────────────
aysal-scan scan . # current directory
aysal-scan scan /path/to/repo # specific path
aysal-scan scan secrets.env # single file
aysal-scan scan https://github.com/username/repo # GitHub URL (auto-clones)
# ── Git modes ───────────────────────────────────────────────────────────────
aysal-scan scan --staged # staged changes only
aysal-scan scan --commits 20 # last 20 commits
aysal-scan scan --full-history # entire git history
# ── Output formats ──────────────────────────────────────────────────────────
aysal-scan scan . --report json # JSON (for CI pipelines)
aysal-scan scan . --report html --output report.html # HTML report
# ── Filters & options ───────────────────────────────────────────────────────
aysal-scan scan . --min-severity HIGH # HIGH and CRITICAL only
aysal-scan scan . --no-blast-radius # skip API checks (offline)
aysal-scan scan . --no-fail # always exit 0
aysal-scan scan . --allow-list <id1>,<id2> # suppress known findings by ID
aysal-scan scan . --verbose # show detailed blast radius debug output
aysal-scan scan . --report sarif --sarif-baseline old.sarif # only alert on genuinely new findings
Supported Providers & Blast Radius Checks
| Secret Type | Detection | Blast Radius Check |
|---|---|---|
| AWS Access Key | Regex | sts:GetCallerIdentity → IAM policy list |
| GitHub Token (PAT / OAuth) | Regex | /user → scopes → repo access |
| OpenAI API Key | Regex | /v1/models → billing exposure |
| Stripe Secret Key | Regex | /v1/balance → live account access |
| Stripe Publishable Key | Regex | Auto LOW |
| Twilio Account SID | Regex | /Accounts/{SID} → status check |
| SendGrid API Key | Regex | /v3/scopes → permission list |
| Slack Bot Token | Regex | auth.test → workspace + permissions |
| Slack Webhook URL | Regex | Probe → active/inactive check |
| npm Token | Regex | registry.npmjs.org/-/whoami |
| PyPI Token | Regex | Manual review (no safe verify endpoint) |
| GCP Service Account JSON | JSON structure | Auto CRITICAL (project ID + client email parsed) |
| Azure Client Secret | Context-aware regex | Manual review (tenant ID required to verify) |
| Heroku API Key | Regex | /account → email + app access |
| Google API Key | Regex | Probe enabled APIs |
| JWT Token | Regex | Decode header + expiry check |
| Private Key (RSA / EC / SSH) | Regex | Auto CRITICAL |
| Database URL (Postgres, MySQL, Redis, MongoDB) | Regex | Auto HIGH |
| High Entropy String | Shannon entropy > 4.5 | Flagged for manual review |
Severity Levels
| Level | Meaning | Exit Code |
|---|---|---|
| 🔴 CRITICAL | Key is active + has admin/write access | 1 |
| 🟠 HIGH | Key is active + significant read access | 1 |
| 🟡 MEDIUM | Key appears valid but check failed or timed out | 0 |
| 🔵 LOW | Test/publishable key — limited exposure | 0 |
| ⚪ INFO | Likely a secret, unconfirmed | 0 |
Exit code 1 on any CRITICAL or HIGH finding. Override with --no-fail.
GitHub Actions
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Aysal-Scan Secret Scan
uses: Rolex-1905/aysal-scan@v1.0.0
with:
path: '.'
min-severity: 'HIGH'
no-blast-radius: 'false'
fail-on-findings: 'true'
- name: Upload HTML Report
uses: actions/upload-artifact@v4
if: always()
with:
name: aysal-scan-report
path: aysal-scan-report.html
retention-days: 30
- name: Upload SARIF to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: aysal-scan-results.sarif
category: aysal-scan
Pre-commit Hook
Recommended — remote repo mode (auto-installs, always up to date):
repos:
- repo: https://github.com/Rolex-1905/aysal-scan
rev: v1.0.0
hooks:
- id: aysal-scan # fast — no API calls, offline safe
With blast radius checks (slower — calls provider APIs):
repos:
- repo: https://github.com/Rolex-1905/aysal-scan
rev: v1.0.0
hooks:
- id: aysal-scan-with-blast-radius
Local mode (if you have aysal-scan already installed):
repos:
- repo: local
hooks:
- id: aysal-scan
name: Aysal-Scan — secret detection
entry: aysal-scan scan --staged --no-blast-radius
language: system
pass_filenames: false
Install pre-commit and activate:
pip install pre-commit
pre-commit install
Ignoring Files
Aysal-Scan automatically skips node_modules/, .git/, dist/, build/,
*.min.js, lock files, and binary files.
For custom rules, create an AysalScanignore file in your repo root
(same syntax as .gitignore):
# Ignore test fixtures with intentional fake keys
tests/test_cli.py
tests/test_patterns.py
# Ignore example config files
*.example
*.sample
config.example.env
How Blast Radius Works
When a secret is detected, Aysal-Scan calls the provider's API using read-only operations only to answer three questions:
- Is this key still active?
- What can it access?
- How bad is it if someone already has it?
All checks run concurrently with a 10-second timeout per provider.
A failed or timed-out check degrades gracefully to MEDIUM rather than
crashing the scan. The raw secret is never stored — only the masked value
(AKIA****XMPL) appears in any output or report.
Project Structure
aysal_scan/
├── cli.py # Typer CLI + interactive UI
├── models.py # Pydantic models (Finding, ScanReport, etc.)
├── scanner/
│ ├── patterns.py # Regex patterns for 17+ secret types
│ ├── entropy.py # Shannon entropy analysis
│ ├── file_scanner.py # File + directory scanning
│ ├── git_utils.py # Git history, staged, commit scanning
│ └── deduplicator.py # Deduplicate across commits
├── blast_radius/
│ ├── aws.py # AWS IAM checks via STS (user, group, inline policies)
│ ├── github.py # GitHub API scope check
│ ├── openai_checker.py # OpenAI key validation
│ ├── stripe.py # Stripe balance check
│ ├── slack.py # Slack auth.test
│ ├── slack_webhook.py # Slack webhook probe
│ ├── twilio.py # Twilio account check
│ ├── sendgrid.py # SendGrid scope list
│ ├── npm.py # npm whoami
│ ├── pypi.py # PyPI — flags for manual review (no safe verify endpoint)
│ ├── heroku.py # Heroku account check
│ ├── google.py # Google API probe
│ ├── gcp.py # GCP Service Account JSON parsing
│ ├── azure.py # Azure Client Secret — manual review
│ ├── jwt_checker.py # JWT decode + expiry
│ ├── base.py # Retry/backoff wrapper shared by all checkers
│ └── generic.py # Fallback for unknown types
└── reporter/
├── terminal.py # Rich-formatted terminal output
├── json_report.py # JSON output for CI
├── html_report.py # Interactive HTML report (collapsible, filterable)
└── sarif_report.py # SARIF 2.1.0 for GitHub Security tab
Tech Stack
Built with Python 3.11+ · Typer · Rich · Pydantic v2 · httpx · boto3 · GitPython
License
MIT © 2026 Aysal-Scan
Built by Neeraj Mudunuru
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
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 aysal_scan-1.0.2.tar.gz.
File metadata
- Download URL: aysal_scan-1.0.2.tar.gz
- Upload date:
- Size: 51.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c0e0e7fd5ce466618f6011f7ce49a5554b43c85c0d1915eeef290018f480b85
|
|
| MD5 |
7c5d9b7a336327b832a08242f8542e8e
|
|
| BLAKE2b-256 |
1936d0817d28013a31beaefe9ab1576dbce342b6fd376b6bec272a01519a4da7
|
Provenance
The following attestation bundles were made for aysal_scan-1.0.2.tar.gz:
Publisher:
publish.yml on Rolex-1905/aysal-scan
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aysal_scan-1.0.2.tar.gz -
Subject digest:
2c0e0e7fd5ce466618f6011f7ce49a5554b43c85c0d1915eeef290018f480b85 - Sigstore transparency entry: 1877766116
- Sigstore integration time:
-
Permalink:
Rolex-1905/aysal-scan@419743568be7d51aed7b2d0ccc73dfb7e8670c54 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Rolex-1905
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@419743568be7d51aed7b2d0ccc73dfb7e8670c54 -
Trigger Event:
push
-
Statement type:
File details
Details for the file aysal_scan-1.0.2-py3-none-any.whl.
File metadata
- Download URL: aysal_scan-1.0.2-py3-none-any.whl
- Upload date:
- Size: 52.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be46126312970298d217d3d399716c462948e5c817192b8252e4e88ef817a0f4
|
|
| MD5 |
b1aebef4b0e451a7f41de64ea4c4f956
|
|
| BLAKE2b-256 |
53f1786fc0fe59d4321c9ed3c62c68f3cb40e041b74974cacec4720353ef2e92
|
Provenance
The following attestation bundles were made for aysal_scan-1.0.2-py3-none-any.whl:
Publisher:
publish.yml on Rolex-1905/aysal-scan
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aysal_scan-1.0.2-py3-none-any.whl -
Subject digest:
be46126312970298d217d3d399716c462948e5c817192b8252e4e88ef817a0f4 - Sigstore transparency entry: 1877766169
- Sigstore integration time:
-
Permalink:
Rolex-1905/aysal-scan@419743568be7d51aed7b2d0ccc73dfb7e8670c54 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/Rolex-1905
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@419743568be7d51aed7b2d0ccc73dfb7e8670c54 -
Trigger Event:
push
-
Statement type: