The Problem
You finish a feature. Code review passes. QA approves. Then security team finds three critical vulnerabilities. Now you're rewriting authentication logic on Friday at 6pm because fixing security was left to the end.
The traditional approach: Security is a gate at the end. You build, then check for vulnerabilities.
This is backwards. By the time security reviews your code, you've already made architectural decisions. Ripping out insecure patterns means rewriting features, not tweaking them.
The Core Insight
Shift security left: find vulnerabilities while coding, not after deployment. Picture the project as a timeline running left to right — moving the security work toward the start is why the practice is called shift-left.
The earlier you catch security issues, the cheaper they are to fix. A vulnerability caught during coding may be a small edit; the same bug found during review can mean rework, and the same bug found in production can mean incident response, customer communications, and regulatory exposure.
AI is useful as an immediate first-pass reviewer: it can review code for security issues in real time as you write. It does not replace a security expert or automated scanning; it gives you a faster way to catch obvious mistakes before they harden into architecture.
The skill that does this
There's a skill that handles the second check for you — vc-precommit-security-gate. Install it and a check runs on every change you save, forever, without you thinking about it. Do it by hand once first, though: the loop has two places where a check quietly does nothing while looking exactly like one that works, and if you have never watched those moments yourself you will not spot them when the automation glides past with a confident green result.
The Shift-Left Workflow
Layer 1: Pre-Coding Security
Before writing code, ask AI about security implications. The example below is a login system built on signed identity tokens — a format known as JWT — and one of the answers heads off attacker script running in your users' browsers, an attack known as XSS:
Prompt: "I'm building a user authentication system with JWT tokens.
What are the top 5 security considerations I should handle upfront?"
AI Response:
1. Store JWT secret in environment variables, not code
2. Set token expiration (24h recommended)
3. Use HTTP-only cookies, not localStorage (XSS prevention)
4. Implement refresh token rotation
5. Add rate limiting to login endpoint
Why this works: You design security in, not bolt it on later.
Layer 2: During Coding (Real-Time Review)
As AI generates code, immediately ask for security review.
Workflow:
1. Ask AI to generate feature
2. AI provides code
3. Before accepting: "Review this code for security vulnerabilities"
4. AI points out issues
5. Fix issues in same session
6. Accept hardened code
Time added: 2-3 minutes per feature
Result: obvious issues caught before they become review or production work
The Security Sandwich Pattern
Generate → Review → Fix → Accept. Never skip the review layer. This becomes muscle memory after 10 iterations.
Layer 3: Post-Coding (Automated Scanning)
Run automated security tools before committing.
Tell your AI assistant: "Run a dependency vulnerability scan, a security-focused lint, a static analysis pass, and a secrets scan on this project, and summarize anything they find." Better still, have it wire the checks into a script git runs for you right before each commit lands — known as a pre-commit hook (Setup 1, below) — so they run automatically on every commit — you don't have to remember to run anything.
AI Security Review Prompts
Prompt 1: General Security Audit
"Perform a security audit of this code. Check for:
1. Input validation gaps
2. SQL/NoSQL injection risks
3. XSS vulnerabilities
4. Authentication/authorization issues
5. Secrets hardcoded in source
6. Timing attacks
7. Resource exhaustion (DoS)
8. Insecure dependencies
Provide severity (Critical/High/Medium/Low) for each finding."
Prompt 2: OWASP Top 10 Review
The security field keeps a ranked list of the ten most common ways web apps actually get broken into, known as the OWASP Top 10. Ask for a review against it by name:
"Review this code against OWASP Top 10 2021:
A01 Broken Access Control
A02 Cryptographic Failures
A03 Injection
A04 Insecure Design
A05 Security Misconfiguration
A06 Vulnerable Components
A07 Identification and Authentication Failures
A08 Software and Data Integrity Failures
A09 Security Logging Failures
A10 Server-Side Request Forgery
List any violations found."
Prompt 3: Threat Modeling
One question below asks what happens when two requests touch the same data at the same moment — a bug known as a race condition:
"Given this authentication endpoint:
[paste code]
Perform threat modeling:
1. What are possible attack vectors?
2. What happens if an attacker controls each input?
3. What are the trust boundaries?
4. What can go wrong with race conditions?
5. How could an attacker bypass this?
Think like a penetration tester."
Prompt 4: Language-Specific Security
Each language has its own classic traps: typed input that gets executed as a database command — the attack known as SQL injection; rebuilding live objects from stored bytes, a step called deserialization that runs attacker code when the bytes are hostile; and regular expressions an attacker can jam with a pathological input, known as ReDoS:
# Python-specific
"Review this Python code for:
- Pickle deserialization vulnerabilities
- SQL injection via f-strings
- Command injection via os.system()
- Path traversal in file operations
- Timing attacks in comparisons"
# JavaScript-specific
"Review this Node.js code for:
- Prototype pollution
- ReDoS in regex
- XSS via innerHTML
- JWT secret exposure
- NoSQL injection in MongoDB queries"
The Walkthrough: Secure Feature Development
Task: Add password reset functionality.
Phase 1: Design Review (Before Coding)
Prompt: "I need to implement password reset via email.
What security measures are essential?"
AI Response:
1. Generate cryptographically random tokens (32+ bytes)
2. Hash tokens before storing in database
3. Set token expiration (15-30 minutes)
4. Invalidate token after single use
5. Rate limit reset requests (prevent email bombing)
6. Don't reveal if email exists (timing attack prevention)
7. Log all reset attempts (security monitoring)
Great, now I know what to build.
Phase 2: Implementation with Real-Time Review
Prompt: "Generate password reset endpoint following those security requirements"
AI generates code...
Prompt: "Review this for vulnerabilities before I accept it"
AI: "Found 2 issues:
1. Token is not cryptographically random (using Math.random)
2. No rate limiting implemented
Fix these before shipping."
I fix issues, re-review, then accept.
Phase 3: Automated Pre-Commit Checks
Tell your assistant: "Commit this with the message 'Add password reset.'" Because of the pre-commit hook from Setup 1 below, the commit doesn't go through blind — the security checks run first, and you'll see something like:
- Running security checks...
- ✓ No secrets found
- ✓ No high-severity npm vulnerabilities
- ✓ ESLint security rules pass
- ✓ Semgrep found 0 issues
Only then does the commit land. If any line shows a failure instead of a checkmark, the commit is blocked until you fix it — that's the hook doing its job.
Result: Secure feature shipped in first iteration. No security team escalation needed.
Automated Security Workflows
Setup 1: Pre-Commit Hooks
Tell your assistant: "Install husky and set up a pre-commit hook that blocks the commit if npm audit finds a high-severity vulnerability or the security lint fails." This is a one-time setup — once it's in place, every future commit gets checked automatically, whether or not you remember to ask.
If you're comfortable in a terminal yourself, this is npm install --save-dev husky then npx husky add .husky/pre-commit "npm run security-check", with a security-check script in package.json that runs npm audit && eslint . --ext .js --config .eslintrc.security.js.
Setup 2: CI/CD Security Gates
The same checks can run on a build server every time code is pushed — the automated build-test-release pipeline known as CI/CD:
# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Snyk
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
- name: Run Semgrep
uses: returntocorp/semgrep-action@v1
- name: Check secrets
uses: trufflesecurity/trufflehog@main
Setup 3: IDE Integration
# VS Code: Install extensions
- SonarLint (real-time security feedback)
- Snyk (dependency scanning)
- GitLens (see who wrote vulnerable code)
# Configure real-time security linting
# .vscode/settings.json
{
"sonarlint.rules": {
"javascript:S3330": { "level": "on" }, // Detect cipher weaknesses
"javascript:S2068": { "level": "on" }, // Hard-coded credentials
"javascript:S2092": { "level": "on" } // Insecure cookie
}
}
Don't Trust AI Blindly
AI can miss vulnerabilities. Always combine AI review with automated tools (Snyk, Semgrep, npm audit). Use AI as first pass, tools as verification.
Failure Patterns
1. Security Review After Feature Complete
Symptom: You build entire feature, then discover fundamental security issues.
Fix: Review security during design phase, not after coding.
2. Only Automated Scanning
Symptom: Tools pass, but logic flaws exist (business logic bypasses).
Fix: Combine automated tools with AI threat modeling prompts.
3. Ignoring Low Severity Issues
Symptom: "It's just low severity, we'll fix later." Never gets fixed.
Fix: Fix ALL issues before merging. Low severity stacks up.
Measuring Shift-Left Success
Metrics to track:
- Vulnerabilities found in PR review: Should decrease over time
- Time to fix vulnerabilities: Lower if caught early
- Security escalations: Rare if shift-left works
- Catalogued vulnerabilities in dependencies: every publicly disclosed vulnerability gets a tracking ID known as a CVE; with automated checks the count stays near zero
| Stage | Cost to Fix | Shift-Left Impact |
|---|---|---|
| During coding | Small edit (minutes) | ✓ Main target |
| Code review | Rework (hours) | ✓ Backup catch |
| QA testing | Late-cycle rework (days) | Rare if shift-left works |
| Production | Incident response (days to weeks) | Should never happen |
Quick Reference
Shift-Left Security Checklist:
[ ] Before Coding:
- Ask AI about security considerations for feature
- Design security controls into architecture
- Identify sensitive data flows
[ ] During Coding:
- Request security review after AI generates code
- Fix issues in same session
- Use secure coding patterns from the start
[ ] Before Committing:
- Run
npm audit/pip-audit - Run security linters (ESLint security plugin)
- Scan for secrets (
git-secrets) - Scan that reads your source for vulnerable patterns without running it — known as SAST (Semgrep/SonarQube)
[ ] In CI/CD:
- Automated security scans on every PR
- Block merge if high/critical vulnerabilities
- Track security metrics over time
Quick AI Security Prompt:
"Security review this code for:
- Input validation
- SQL/XSS injection
- Auth bypasses
- Hardcoded secrets
- DoS vulnerabilities
Be critical. What could an attacker exploit?"
Tools to Install Today:
npm install -g snyk- Dependency scanningpip install semgrep- SAST scanningnpm install -D husky- scripts git runs for you around commits, known as Git hooks- IDE: SonarLint extension - Real-time feedback
Key Takeaways
What To Remember
- The cost curve is the whole argument. Early fixes are small edits; late fixes become rework, incidents, and customer-trust repair. Move the work left before the multiplier shows up.
- Three layers, every feature. Pre-coding (ask AI about security implications), during coding (Generate → Review → Fix → Accept), post-coding (npm audit, semgrep, secret scan).
- The Security Sandwich is muscle memory. Never accept AI code without a "review this for vulnerabilities" round-trip in the same session. Two minutes per feature catches obvious issues while the context is still fresh.
- Automated tools verify, they don't replace. Snyk + Semgrep + secret scanners catch known patterns; AI threat modeling catches logic flaws and business-logic bypasses. You need both.
- Pre-commit hooks make this enforceable, not optional. A hook that blocks high-severity findings is the difference between policy and practice.
Related Guides
Shift-left works best when you know what you're shifting. The other two parts of the security trio:
- The OWASP Top 10 Checklist for AI-Generated Code — the systematic categories your shift-left passes should walk through.
- Language-Specific AI Footguns — the per-language ripgrep tokens to wire into pre-commit hooks.