Scan git repos for leaked secrets and estimate their blast radius
Project description
๐ 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
Project details
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: