A personal security gate. Scan before you use. Scan before you push.
gsi check . # ๐ต scan your repo before pushing
gsi check https://github.com/org/repo # ๐ข evaluate an external repo
gsi install-hook # ๐ auto-block commits containing secrets
- Why gsi?
- How to Upload This to GitHub
- Install & Quickstart
- Two Modes
- Example Output
- Git Pre-commit Hook
- All CLI Options
- Suppressing False Positives
- What Gets Detected
- Risk Scoring
- Project Structure
- Contributing
- License
Two moments where security matters most โ and where most developers have no tooling:
- Before you push โ Did you accidentally commit an
.envfile, a hardcoded API key, or a token? - Before you use โ Does that open-source dependency have unpatched CVEs? Has it been abandoned?
gsi is a single CLI that catches both. Think of it as npm audit + git-secrets + a trust score, in one command.
Follow these steps โ this takes about 5 minutes.
- Go to github.com/new
- Set the repository name to
gsi - Set visibility to Public (or Private โ your choice)
โ ๏ธ Do NOT tick "Add a README", "Add .gitignore", or "Choose a license" โ the repo must be completely empty- Click Create repository
- Copy the URL shown on the next page โ it will look like
https://github.com/selvankj/gsi.git
Replace selvankj with your actual GitHub username:
In pyproject.toml:
Homepage = "https://github.com/selvankj/gsi"
Issues = "https://github.com/selvankj/gsi/issues"In README.md (the badge line near the top):
[](https://github.com/selvankj/gsi/actions)Open a terminal, cd into the unzipped gsi/ folder, and run these commands one by one:
# Initialise git
git init
# Stage all files
git add .
# First commit
git commit -m "feat: initial release of gsi security scanner"
# Point to your GitHub repo (replace selvankj)
git remote add origin https://github.com/selvankj/gsi.git
# Push
git branch -M main
git push -u origin mainYour repo is live at https://github.com/selvankj/gsi โ
- On your new repo page, click the โ๏ธ gear icon next to About (top right)
- Set the description to:
Personal security gate โ scan for secrets, CVEs, and risk signals before you push or use a repo - Add topics:
securityclisecretspythondevtoolsvulnerability-scannergithub - Click Save changes
After pushing, go to the Actions tab on your repo. You should see a workflow called CI running. It will:
- Run all 46 tests across Python 3.9โ3.12
- Run
gsi check .on the repo itself (self-scan)
Once it goes green, the badge at the top of this README will light up โ
Requires Python 3.9+
# Clone your repo (or cd into the unzipped folder)
git clone https://github.com/selvankj/gsi
cd gsi
# Install
pip install -e .
# Verify
gsi --helpNo GitHub token needed for local scans. For scanning remote repos, a token removes rate limits:
export GITHUB_TOKEN=ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXGenerate a token at github.com/settings/tokens โ only public_repo scope is needed.
Scan your own project before git push:
gsi check .
gsi check /path/to/myprojectCatches:
- API keys, tokens, passwords, private keys in source files
.envfiles or credential configs accidentally staged- Dependencies with known CVEs (checks
requirements.txt,package.json,go.mod, and more) - Insecure code patterns: SQL injection,
eval(), weak crypto, command injection, SSRF, path traversalโฆ
Evaluate an open-source repo before depending on it:
gsi check https://github.com/some/repo
gsi check owner/repo
gsi check owner/repo --token ghp_XXXXChecks:
- Known CVEs in all declared dependencies (via OSV.dev โ free, no API key needed)
- Secrets accidentally committed to the repo
- Risk signals: archived, stale, no security policy, no branch protection
โโโโโโโโโโโโโโโโโโโโ gsi security scan โโโโโโโโโโโโโโโโโโโโ
๐ /Users/me/myproject (local ยท secrets ยท deps ยท risk)
๐ Secrets (2 found)
Sev Type File Line
โโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโ
๐ด CRIT Database connection string .env.local 3
๐ HIGH AWS Access Key ID config/aws.py 12
โ ๏ธ Vulnerabilities (1 found)
Sev Package Version CVE Fix
โโโโโโโโโโ โโโโโโโโโ โโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโ
๐ HIGH requests 2.18.0 CVE-2018-18074 โ 2.20.0
๐ Risk Score โโโโโโโโโโโโโโโโโโโโ 42/100 [C] Elevated Risk
+30pts Secrets found in a public repo (2 critical/high secrets)
+12pts High-severity CVEs (4 high CVEs)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ ๐จ UNSAFE โ
โ Fix the issues above before pushing โ your secrets โ
โ will be exposed. โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
Verdict levels:
| Verdict | Meaning |
|---|---|
| โ SAFE | No critical or high findings |
| High-severity findings or risk score โฅ 50 | |
| ๐จ UNSAFE | Critical findings โ action required before pushing/using |
Install once per project โ every git commit will automatically scan for secrets:
cd my-project
gsi install-hookNow when you commit:
$ git commit -m "add payment integration"
๐ gsi: scanning for secrets before commit...
โ gsi: Commit BLOCKED โ secrets or high-risk findings detected.
Fix the issues above, or run: git commit --no-verify to skip.
If the scan is clean:
$ git commit -m "fix: update config"
๐ gsi: scanning for secrets before commit...
โ
gsi: No secrets found โ commit allowed.
[main 3a1b2c] fix: update config
Remove the hook at any time:
gsi remove-hookBypass once (use sparingly):
git commit --no-verify -m "your message"# โโ Targets โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
gsi check . # current directory
gsi check /path/to/project # specific local path
gsi check owner/repo # GitHub repo (short form)
gsi check https://github.com/owner/repo # GitHub repo (full URL)
# โโ Modules โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
gsi check . --modules secrets # secrets only (fastest)
gsi check . --modules deps # dependency CVEs only
gsi check . --modules secrets,deps # combine modules
gsi check . --modules all # everything โ default
# โโ Filtering โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
gsi check . --min-severity medium # hide low-severity findings
gsi check . --min-severity high # only show high + critical
# โโ Output โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
gsi check . --report report.html # save a full HTML report
gsi check . --quiet # verdict + counts only (good for CI)
# โโ Remote-specific โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
gsi check owner/repo --token ghp_XXXX # provide token explicitly
gsi check owner/repo --no-clone # use GitHub API only, skip cloning
# โโ Hook management โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
gsi install-hook # install in current repo
gsi install-hook /path/to/other/repo # install in a specific repo
gsi remove-hook # remove from current repoExit codes โ useful for CI/CD:
| Code | Meaning |
|---|---|
0 |
Clean โ safe to use or publish |
1 |
High or critical findings detected |
2 |
Scan error (bad path, auth failure, etc.) |
Use in GitHub Actions:
# .github/workflows/security.yml
name: Security Gate
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install -e .
- run: gsi check . --modules secrets --min-severity medium --quietCreate a .gsiignore file in your project root. A template is included โ copy it to get started:
cp .gsiignore.example .gsiignoreSyntax:
# Ignore an entire file
tests/fixtures/fake_credentials.py
# Ignore a specific line
config/local.py:10
# Ignore a pattern type for paths matching a glob
[secrets] tests/**
[generic_api_key] docs/**
[high_entropy_string] **/*_test.py
Common suppressions to copy-paste:
# Test fixtures with fake/example credentials
[secrets] tests/fixtures/**
[secrets] tests/data/**
# Documentation examples
[secrets] docs/**
[generic_api_key] README.md
# Vendored third-party code
vendor/**
| Category | What's detected |
|---|---|
| AWS | Access Key ID (AKIAโฆ), Secret Access Key |
| GCP | API Key (AIzaโฆ), Service Account JSON |
| Azure | Client secrets |
| GitHub | Personal Access Tokens (ghp_, ghs_, fine-grained PATs) |
| Payments | Stripe secret + publishable keys |
| Comms | Slack tokens + webhooks, Twilio, SendGrid, Mailgun |
| Dev tools | NPM tokens, Heroku API keys, Docker Hub credentials |
| Crypto | RSA/EC/SSH private keys, JWTs |
| Generic | Database URLs with credentials, high-entropy strings, hardcoded passwords |
Detection uses two methods:
- Regex patterns โ high-precision matching per credential type
- Shannon entropy analysis โ catches high-entropy strings that don't match any known pattern
Powered by OSV.dev โ Google's open CVE database. No API key required.
| Language | Files scanned |
|---|---|
| Python | requirements.txt, Pipfile, Pipfile.lock, pyproject.toml |
| Node.js | package.json, package-lock.json, yarn.lock |
| Go | go.mod, go.sum |
| Ruby | Gemfile, Gemfile.lock |
| Rust | Cargo.toml, Cargo.lock |
| Java | pom.xml (basic) |
| Check | What it catches | Severity |
|---|---|---|
command_injection_risk |
shell=True + user input, os.system() |
Critical |
sql_injection_risk |
String-concatenated SQL queries | High |
eval_usage |
eval() / exec() with dynamic input |
High |
insecure_deserialization |
pickle.loads(), unsafe yaml.load() |
High |
path_traversal_risk |
User input in file paths | High |
ssrf_risk |
User-controlled URLs in HTTP calls | High |
weak_crypto |
MD5, SHA1, DES, RC4 | Medium |
insecure_http |
Plain HTTP, disabled SSL verification | Medium |
debug_code_left |
pdb, console.log(password), DEBUG=True |
Medium |
hardcoded_credentials |
Inline username/password assignments | High |
xxe_risk |
XML parsers without entity protection | Medium |
todo_fixme_security |
Security-related TODO/FIXME comments |
Low |
Every scan produces a 0โ100 risk score built from weighted signals:
| Signal | Max points |
|---|---|
| Critical secrets in a public repo | 30 |
| Critical CVEs in dependencies | 25 |
| Repository is archived | 15 |
| High-severity CVEs | 15 |
| More than 3 secrets found | 15 |
| Critical code patterns | 15 |
| No branch protection on default branch | 10 |
| Stale repo (no commits in 180+ days) | 10 |
| Secrets found in a private repo | 10 |
No SECURITY.md present |
5 |
Grade scale:
| Grade | Score | Label |
|---|---|---|
| A | 0 โ 14 | Low Risk |
| B | 15 โ 29 | Moderate Risk |
| C | 30 โ 49 | Elevated Risk |
| D | 50 โ 74 | High Risk |
| F | 75 โ 100 | Critical Risk |
gsi/
โโโ gsi/ # Main Python package
โ โโโ __init__.py
โ โโโ __main__.py # CLI entry point (Typer + Rich)
โ โโโ gsiignore.py # .gsiignore file parser
โ โโโ config/
โ โ โโโ settings.py # Configuration dataclasses
โ โโโ modules/
โ โ โโโ secret_scanner.py # Regex + entropy secret detection
โ โ โโโ dependency_scanner.py # Manifest parsing + OSV.dev CVE lookup
โ โ โโโ risk_scorer.py # Signal-based risk scoring
โ โ โโโ pattern_scanner.py # Code anti-pattern detection
โ โโโ scanner/
โ โ โโโ github_client.py # GitHub API + git clone helper
โ โโโ reports/
โ โโโ report_generator.py # Console / JSON / HTML / Markdown output
โ
โโโ tests/
โ โโโ test_secret_scanner.py # 20 tests
โ โโโ test_risk_scorer.py # 14 tests
โ โโโ test_pattern_scanner.py # 12 tests
โ
โโโ .github/
โ โโโ workflows/
โ โโโ ci.yml # CI: tests + self-scan on every push
โ
โโโ .gitignore
โโโ .gsiignore.example # Copy to .gsiignore to suppress false positives
โโโ pyproject.toml # Package config โ update selvankj here
โโโ CONTRIBUTING.md
โโโ LICENSE # MIT
Contributions are welcome โ see CONTRIBUTING.md for full details.
The most impactful things to contribute:
- New secret patterns โ add an entry to
SECRET_PATTERNSingsi/modules/secret_scanner.py - New code checks โ add an entry to
PATTERN_CHECKSingsi/modules/pattern_scanner.py - False positive fixes โ open an issue with the pattern name and a reproduction case
- New dependency ecosystems โ add a parser to
DependencyScanner._parse_content()
Dev setup:
git clone https://github.com/selvankj/gsi
cd gsi
pip install -e ".[dev]"
pytest # must show 46 passed
gsi check . --modules secrets # must return SAFEMIT โ see LICENSE.