AST-based static security analysis tool for Python and more — with AI-powered explanations.
PyGuard scans source code for security vulnerabilities without executing it. It combines deterministic rule-based detection with optional AI-assisted remediation suggestions via Google Gemini or local Ollama.
Publisher: eenverylmz | Repository: github.com/eenverylmz/PyGuard
Features
- AST-based analysis — structural code analysis, not text scanning
- 26 built-in vulnerability rules — covering OWASP Top 10 and CWEs
- CWE-driven auto-rule generator — synthesize new rules from CWE definitions
- Modular rule engine — add custom rules as standalone
.pyfiles - AI explanations — Gemini (cloud) or Ollama (local) powered remediation suggestions
- Multi-language support — Python (AST) + JS, Java, Go, PHP, Rust (pattern-based)
- VS Code extension — real-time scanning with sidebar panel and Problems pane
- Persistent bridge — zero startup overhead after first activation
- Debounced auto-scan — 400ms debounce prevents rapid re-analysis storms
Installation
git clone https://github.com/eenverylmz/PyGuard.git
cd PyGuard
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
VS Code Extension: Search PyGuard in the Extensions panel or visit the Marketplace.
CLI Usage
# Scan a single file
python cli.py path/to/your_file.py
# Scan a directory
python cli.py path/to/project/
# JSON output
python cli.py path/to/your_file.py --json
# With AI explanations (uses provider from PYGUARD_AI_PROVIDER env var)
python cli.py path/to/your_file.py --ai
# Force Ollama
PYGUARD_AI_PROVIDER=ollama python cli.py path/to/your_file.py --ai
# Force Gemini
PYGUARD_AI_PROVIDER=gemini python cli.py path/to/your_file.py --ai
AI Backend
PyGuard supports two AI backends for vulnerability explanations:
Ollama (Local — Default)
No API key needed. Runs entirely on your machine.
- Install Ollama: https://ollama.com
- Pull a model:
ollama pull llama3.2 - Start Ollama:
ollama serve - Set in VS Code:
pyguard.aiProvider→ollama
Environment variables:
PYGUARD_AI_PROVIDER=ollamaPYGUARD_OLLAMA_MODEL=llama3.2(default)PYGUARD_OLLAMA_URL=http://localhost:11434(default)
Gemini (Cloud)
Requires a Google AI Studio API key.
- Get a key from https://aistudio.google.com/apikey
- Set in VS Code:
pyguard.aiProvider→gemini - Run
PyGuard: Set Gemini API Keyfrom the command palette
Environment variables:
PYGUARD_AI_PROVIDER=geminiGEMINI_API_KEY=...GEMINI_MODEL=models/gemini-2.5-flash-lite(default)
Detected Vulnerability Classes (26 Rules)
Python Rules (AST)
| # | ID | Name | Severity | CWE |
|---|---|---|---|---|
| 1 | PYG002 | eval() usage |
Critical | CWE-94 |
| 2 | PYG003 | Unsafe yaml.load() |
High | CWE-94 |
| 3 | PYG004 | Unsafe subprocess shell=True |
High | CWE-78 |
| 4 | PYG005 | Insecure pickle deserialization | Critical | CWE-502 |
| 5 | PYG006 | Weak crypto hash (MD5/SHA1) | Medium | CWE-328 |
| 6 | PYG007 | Insecure random | Medium | CWE-338 |
| 7 | PYG008 | Bare except clause | Low | CWE-703 |
| 8 | PYG009 | Unsafe os.system() |
High | CWE-78 |
| 9 | PYG010 | Unsafe subprocess shell | High | CWE-78 |
| 10 | PYG011 | Unsafe builtins (compile, globals) |
Medium | CWE-94 |
| 11 | PYG012 | SQL Injection (Python) | Critical | CWE-89 |
| 12 | PYG013 | Path Traversal | High | CWE-22 |
| 13 | PYG014 | SSRF | High | CWE-918 |
| 14 | PYG015 | XXE Injection | High | CWE-611 |
| 15 | PYG016 | Insecure JWT | Critical | CWE-347 |
| 16 | PYG020 | Dangerous builtins (eval/exec/__import__) |
Critical | CWE-94 |
| 17 | PYG021 | SQL Injection (f-string / dynamic) | Critical | CWE-89 |
| 18 | PYG022 | Unsafe deserialization (pickle) | Critical | CWE-502 |
| 19 | PYG023 | Server-Side Template Injection | Critical | CWE-1336 |
| 20 | PYG024 | Hardcoded credential | High | CWE-798 |
| 21 | PYG025 | SSL/TLS verification disabled | High | CWE-295 |
| 22 | PYG026 | Unsafe os.popen() |
High | CWE-78 |
| 23 | PYG027 | Weak ciphers (DES/RC4/ECB) | High | CWE-327 |
| 24 | PYG028 | Misc security (input/temp/mktemp) | Medium | CWE-20/338/377 |
| 25 | PYG029 | Open redirect / header injection | Medium | CWE-601/113/614 |
| 26 | PYG030 | Deprecated module (crypt/imp) |
Low | CWE-477 |
Pattern-based (Python + JS + Java + Go + PHP + Rust)
| ID | Detects |
|---|---|
| PYG900 | Hardcoded secrets (AWS tokens, GitHub PATs, Stripe keys, high-entropy strings) |
| PYG950 | Injection patterns (eval, shell_exec, Runtime.exec, exec.Command) |
VS Code Extension
Install: Search PyGuard in the Extensions panel.
Features:
- Auto-scan on save (configurable via
pyguard.analyzeOnSave) - Manual scan via
Ctrl+Shift+P→PyGuard: Analyze - Findings in the Problems pane with inline highlights
- Sidebar panel with severity badges, CWE references, code snippets
- Click any finding to jump to the exact line
- AI provider selection via
Ctrl+Shift+P→PyGuard: Select AI Provider
Settings:
| Setting | Default | Description |
|---|---|---|
pyguard.analyzeOnSave |
true |
Auto-analyze on file save |
pyguard.pythonPath |
python3 |
Python interpreter path |
pyguard.aiEnabled |
false |
Enable AI-powered explanations |
pyguard.aiProvider |
ollama |
AI backend: ollama (local) or gemini (cloud) |
pyguard.ollamaModel |
llama3.2 |
Ollama model name |
pyguard.ollamaUrl |
http://localhost:11434 |
Ollama server URL |
pyguard.geminiModel |
models/gemini-2.5-flash-lite |
Gemini model name |
Architecture
VS Code (TypeScript)
extension.ts → persistent bridge, debounce, activate/deactivate
SidebarProvider.ts → WebView with postMessage incremental updates
aiKey.ts → AI provider selection, Gemini key management
│
│ spawn / JSON stdin/stdout
▼
vscode_bridge.py → persistent process (stays alive across saves)
│
▼
Python Engine
core/analyzer.py → language routing, AST parse
core/AST_parser.py → import alias collection, call resolution
core/generic_scanner.py → regex-based secret/injection scanning
engine/rule_engine.py → node-type dispatch, ctx injection, rule running
rules/ → 26 security rule modules (PYG002–PYG030)
rules/auto_rule_generator.py → CWE-driven rule synthesis (23 CWEs)
ai/client.py → unified AI provider router (Ollama + Gemini)
ai/ollama_client.py → local LLM inference via Ollama
Writing Custom Rules
Drop a .py file in rules/ — PyGuard picks it up automatically:
# rules/my_rule.py
import ast
from core.result import Vulnerability
RULE_ID = "PYG100"
def check(node: ast.Call, ctx=None) -> list:
findings = []
if isinstance(node, ast.Call):
# detection logic
findings.append(Vulnerability(
rule_id=RULE_ID, name="My Rule",
severity="high", description="...",
line=getattr(node, "lineno", 1),
cwe="CWE-XXX", code="",
))
return findings
Tips:
- Type-annotate the
nodeparam (e.g.,node: ast.Call) for faster dispatch - Use
ctx.get("import_aliases", {})for resolved import aliases - Return empty list for no findings (never return
None)
Auto-Rule Generator
Generate rules from CWE definitions:
# Generate one rule
python3 rules/auto_rule_generator.py --cwe CWE-89
# Generate all 23 CWE rules
python3 rules/auto_rule_generator.py --all --output-dir rules/ --overwrite
# List available CWEs
python3 rules/auto_rule_generator.py --list-cwes
# Validate a generated rule
python3 rules/auto_rule_generator.py --validate rules/sql_injection.py
Add new CWEs by editing the CWE_DATABASE dict in rules/auto_rule_generator.py.
Performance
- Persistent bridge — Python process stays alive (no 200-500ms startup per save)
- 400ms debounce — prevents rapid re-analysis storms
- postMessage sidebar — incremental DOM updates instead of full HTML regeneration
- Node-type dispatch — rules pre-categorized by AST node type at load time (
O(nodes * relevant_rules)instead ofO(nodes * all_rules)) - Cached signatures —
inspect.signature()called once at module load, not per-node-per-rule
Requirements
- Python 3.10+
- VS Code 1.80+ (for extension)
- Dependencies:
pip install -r requirements.txt - Ollama (optional, for local AI): https://ollama.com
- Gemini API key (optional, for cloud AI): https://aistudio.google.com/apikey
Project Structure
PyGuard/
├── src/ # VS Code extension (TypeScript)
│ ├── extension.ts # Persistent bridge, debounce, activate
│ ├── SidebarProvider.ts # WebView panel via postMessage
│ ├── aiKey.ts # AI provider selection, Gemini key management
│ └── *.map # Source maps
├── ai/ # AI backends
│ ├── client.py # Unified provider router (Ollama + Gemini)
│ └── ollama_client.py # Local LLM via Ollama
├── core/ # Analysis core
│ ├── analyzer.py # Language routing, AST parse
│ ├── AST_parser.py # Alias collection, call resolution
│ ├── generic_scanner.py # Multi-language secret/injection scanning
│ └── result.py # Vulnerability dataclass
├── engine/ # Rule engine
│ └── rule_engine.py # Node-type dispatch, ctx injection
├── rules/ # 26 security rules + auto-generator
│ ├── unsafe_os_system.py
│ ├── sql_injection.py
│ ├── auto_rule_generator.py
│ └── ... (24 more)
├── samples/ # Test files for all languages
├── assets/ # Extension icons
├── cli.py # CLI entry point
├── vscode_bridge.py # Persistent JSON bridge
├── package.json # Extension manifest
├── tsconfig.json # TypeScript config
└── requirements.txt # Python dependencies
Changelog
v1.0.1 — 2026-06-01
New features:
- Ollama (local AI) support — use local LLMs instead of Gemini cloud API
- Unified AI provider router —
ai/client.pyroutes to Ollama or Gemini viaPYGUARD_AI_PROVIDER - AI provider selection — new
PyGuard: Select AI Providercommand in VS Code - New settings —
pyguard.aiProvider,pyguard.ollamaModel,pyguard.ollamaUrl,pyguard.geminiModel pyguard.aiEnableddefault changed tofalse(opt-in AI)
v1.0.0 — 2026-06-01
New rules (11): SQL injection, dangerous builtins, unsafe deserialization, SSTI, hardcoded credentials, SSL bypass, os.popen(), weak ciphers, misc security (input/PRNG/tempfile), open redirect/header injection, deprecated modules.
New features:
- Persistent bridge process (zero startup overhead on save)
- 400ms debounced auto-scan
- postMessage-based incremental sidebar updates
- Click-to-navigate from sidebar to source line
- CWE-driven auto-rule generator (23 CWEs)
- Node-type dispatch in rule engine
- Import alias resolution in auto-generated rules
Performance: 10x faster analysis after first activation (persistent bridge).
Disclaimer
PyGuard is for educational and defensive security purposes only. Scan only code you own or have permission to analyze.