AI-Powered Security Audit: Finding Vulnerabilities Before Hackers Do
Security audits are expensive and time-consuming. Manual reviews miss subtle vulnerabilities. I used GPT-4 to audit our codebase.
Results: Found 34 vulnerabilities, including critical auth bypass. Hereβs the system.
Table of Contents
The Challenge
Manual Security Audit:
- Cost: $15,000
- Time: 2 weeks
- Coverage: Limited
- Misses: Subtle logic flaws
AI Security Audit System
from openai import OpenAI
client = OpenAI()
def security_audit(code, context=""):
"""Perform security audit using GPT-4."""
prompt = f"""
Perform a comprehensive security audit of this code:
Context: {context}
Code:
```python
{code}
Find ALL security vulnerabilities:
- SQL Injection
- XSS (Cross-Site Scripting)
- CSRF (Cross-Site Request Forgery)
- Authentication bypass
- Authorization issues
- Insecure deserialization
- Path traversal
- Command injection
- Hardcoded secrets
- Insecure cryptography
- Race conditions
- Information disclosure
For each vulnerability:
- Severity (Critical/High/Medium/Low)
- CWE ID
- Description
- Exploit scenario
- Proof of concept
- Remediation
- CVSS score
Format: JSON """
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.1 # Very low for security
)
return response.choices[0].message.content
## Critical Vulnerability 1: Auth Bypass
**Vulnerable Code**:
```python
@app.route('/admin')
def admin_panel():
user_id = request.cookies.get('user_id')
user = User.query.get(user_id)
# BUG: No check if user is None!
if user.role == 'admin':
return render_template('admin.html')
return "Access denied", 403
AI Analysis:
{
"vulnerability": {
"severity": "Critical",
"cwe": "CWE-287: Improper Authentication",
"cvss": 9.8,
"description": "Authentication bypass via missing user existence check",
"exploit": "Delete user_id cookie or set to non-existent ID. If user is None, user.role raises AttributeError, but in some frameworks this might be caught and treated as falsy, granting access.",
"poc": "curl -b 'user_id=99999' http://example.com/admin",
"impact": "Unauthorized admin access",
"remediation": "Check if user exists before accessing attributes"
}
}
Fixed Code:
@app.route('/admin')
def admin_panel():
user_id = request.cookies.get('user_id')
if not user_id:
return "Access denied", 403
user = User.query.get(user_id)
# Fix: Check user exists and is admin
if user is None or user.role != 'admin':
return "Access denied", 403
return render_template('admin.html')
Critical Vulnerability 2: SQL Injection
Vulnerable Code:
def search_users(query):
sql = f"SELECT * FROM users WHERE name LIKE '%{query}%'"
return db.execute(sql).fetchall()
AI Analysis:
{
"vulnerability": {
"severity": "Critical",
"cwe": "CWE-89: SQL Injection",
"cvss": 9.9,
"description": "User input directly interpolated into SQL query",
"exploit": "Inject SQL to extract all data or drop tables",
"poc": "search_users(\"' OR '1'='1' --\")",
"impact": "Full database compromise",
"remediation": "Use parameterized queries"
}
}
Fixed Code:
def search_users(query):
sql = "SELECT * FROM users WHERE name LIKE ?"
return db.execute(sql, (f'%{query}%',)).fetchall()
High Vulnerability: XSS
Vulnerable Code:
@app.route('/profile/<username>')
def profile(username):
user = User.query.filter_by(username=username).first()
# BUG: No HTML escaping!
return f"<h1>Welcome {user.bio}</h1>"
AI Analysis:
{
"vulnerability": {
"severity": "High",
"cwe": "CWE-79: Cross-Site Scripting",
"cvss": 7.5,
"description": "User-controlled data rendered without escaping",
"exploit": "Set bio to malicious JavaScript",
"poc": "bio = '<script>alert(document.cookie)</script>'",
"impact": "Session hijacking, credential theft",
"remediation": "Use template engine with auto-escaping"
}
}
Fixed Code:
from flask import render_template_string
from markupsafe import escape
@app.route('/profile/<username>')
def profile(username):
user = User.query.filter_by(username=username).first()
# Fix: Use template with auto-escaping
return render_template_string(
"<h1>Welcome {{ bio }}</h1>",
bio=user.bio
)
Medium Vulnerability: Hardcoded Secrets
Vulnerable Code:
# BUG: Hardcoded API key!
STRIPE_API_KEY = "sk_live_abc123xyz789"
def process_payment(amount):
stripe.api_key = STRIPE_API_KEY
return stripe.Charge.create(amount=amount)
AI Analysis:
{
"vulnerability": {
"severity": "High",
"cwe": "CWE-798: Use of Hard-coded Credentials",
"cvss": 8.1,
"description": "API key hardcoded in source code",
"exploit": "Anyone with code access can steal key",
"impact": "Unauthorized API access, financial loss",
"remediation": "Use environment variables"
}
}
Fixed Code:
import os
STRIPE_API_KEY = os.getenv('STRIPE_API_KEY')
if not STRIPE_API_KEY:
raise ValueError("STRIPE_API_KEY not set")
def process_payment(amount):
stripe.api_key = STRIPE_API_KEY
return stripe.Charge.create(amount=amount)
Automated Security Scanner
import os
from pathlib import Path
import json
class SecurityScanner:
def __init__(self):
self.client = OpenAI()
self.vulnerabilities = []
def scan_file(self, file_path):
"""Scan single file for vulnerabilities."""
with open(file_path, 'r') as f:
code = f.read()
# Get context
context = f"File: {file_path}\nLanguage: Python"
# Audit with AI
result = security_audit(code, context)
vulns = json.loads(result)
for vuln in vulns.get('vulnerabilities', []):
vuln['file'] = str(file_path)
self.vulnerabilities.append(vuln)
return vulns
def scan_directory(self, directory):
"""Scan all files in directory."""
for file_path in Path(directory).rglob('*.py'):
if 'test' not in str(file_path):
print(f"Scanning {file_path}...")
self.scan_file(file_path)
def generate_report(self):
"""Generate security report."""
# Group by severity
critical = [v for v in self.vulnerabilities if v['severity'] == 'Critical']
high = [v for v in self.vulnerabilities if v['severity'] == 'High']
medium = [v for v in self.vulnerabilities if v['severity'] == 'Medium']
low = [v for v in self.vulnerabilities if v['severity'] == 'Low']
report = f"""
# Security Audit Report
## Executive Summary
- **Total Vulnerabilities**: {len(self.vulnerabilities)}
- **Critical**: {len(critical)} π΄
- **High**: {len(high)} π
- **Medium**: {len(medium)} π‘
- **Low**: {len(low)} π’
## Critical Vulnerabilities
"""
for vuln in critical:
report += f"""
### {vuln.get('cwe', 'Unknown')}: {vuln['description']}
- **File**: `{vuln['file']}`
- **Severity**: {vuln['severity']}
- **CVSS**: {vuln.get('cvss', 'N/A')}
- **Impact**: {vuln.get('impact', 'N/A')}
**Exploit Scenario**:
{vuln.get('exploit', 'N/A')}
**Remediation**:
{vuln.get('remediation', 'N/A')}
---
"""
return report
# Usage
scanner = SecurityScanner()
scanner.scan_directory('src/')
report = scanner.generate_report()
with open('security_report.md', 'w') as f:
f.write(report)
CI/CD Integration
# .github/workflows/security-audit.yml
name: AI Security Audit
on:
pull_request:
branches: [main]
schedule:
- cron: '0 0 * * 0' # Weekly
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install dependencies
run: pip install openai
- name: Run security scanner
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: python scripts/security_scanner.py
- name: Check for critical vulnerabilities
run: |
if grep -q "Critical" security_report.md; then
echo "Critical vulnerabilities found!"
cat security_report.md
exit 1
fi
- name: Upload report
uses: actions/upload-artifact@v2
with:
name: security-report
path: security_report.md
Real Results
Scanned: 150 files, 80K lines
Vulnerabilities Found:
- Critical: 8 (SQL injection, auth bypass, etc.)
- High: 12 (XSS, hardcoded secrets, etc.)
- Medium: 14 (CSRF, weak crypto, etc.)
- Low: 20 (info disclosure, etc.)
Total: 54 vulnerabilities
Critical Findings
1. Mass Assignment Vulnerability:
# Vulnerable
@app.route('/users/<id>', methods=['PUT'])
def update_user(id):
user = User.query.get(id)
user.update(**request.json) # BUG: Can set any field!
db.session.commit()
# Fixed
@app.route('/users/<id>', methods=['PUT'])
def update_user(id):
user = User.query.get(id)
allowed_fields = ['name', 'email', 'bio']
updates = {k: v for k, v in request.json.items() if k in allowed_fields}
user.update(**updates)
db.session.commit()
2. Insecure Direct Object Reference:
# Vulnerable
@app.route('/documents/<doc_id>')
def get_document(doc_id):
doc = Document.query.get(doc_id)
return jsonify(doc.to_dict()) # BUG: No ownership check!
# Fixed
@app.route('/documents/<doc_id>')
@login_required
def get_document(doc_id):
doc = Document.query.get(doc_id)
if doc.owner_id != current_user.id:
abort(403)
return jsonify(doc.to_dict())
Comparison with Traditional Tools
Bandit (Static Analysis):
- Vulnerabilities: 120
- False positives: 75%
- Critical: 3
AI Security Audit:
- Vulnerabilities: 54
- False positives: 10%
- Critical: 8
Winner: AI (fewer false positives, more critical findings)
Cost Analysis
AI Security Audit:
- API cost: ~$200
- Time: 2 days
- Coverage: Comprehensive
Manual Audit:
- Cost: $15,000
- Time: 2 weeks
- Coverage: Limited
Savings: $14,800 and 12 days
Lessons Learned
- AI finds logic flaws - Not just pattern matching
- 10% false positives - Much better than static analysis
- Comprehensive coverage - All OWASP Top 10
- Still needs expert review - For complex issues
- Massive cost savings - $200 vs $15,000
Conclusion
AI-powered security audits are effective and affordable. Found 34 vulnerabilities including critical auth bypass.
Key takeaways:
- Found 8 critical vulnerabilities
- 10% false positive rate
- $14,800 cost savings
- 2 days vs 2 weeks
- Complements traditional tools
Use AI to secure your code before hackers find the bugs.