Security Reviewer Guide: Usage, Examples, and Best Practices for Beginners
Purpose
This post demonstrates how to use the Security Reviewer skill in Claude Code to find and fix security issues in your code.
Environment
- Claude Code CLI
- claude-skills plugin
- Security Reviewer skill
- Any programming language
What is Security Reviewer?
Security Reviewer is a skill in the claude-skills plugin that helps you find security vulnerabilities in your code before you commit it. It checks for common security issues like:
- Hardcoded secrets (API keys, passwords)
- SQL injection vulnerabilities
- XSS (Cross-Site Scripting) issues
- Missing authentication/authorization
- Input validation problems
- Insecure error handling
When should you use it? You should run Security Reviewer before any commit, especially when:
- Adding authentication features
- Handling user input
- Working with databases
- Processing file uploads
- Implementing payment/sensitive features
Installation and Setup
First, install the claude-skills plugin if you haven’t already:
npm install -g @jeffallan/claude-skillsThen, activate the Security Reviewer skill in your Claude Code session:
claude skill activate security-reviewerYou can verify it’s available by asking Claude:
@claude What skills do you have available?Core Usage Patterns
The easiest way to use Security Reviewer is to ask Claude directly:
Use security-reviewer to check this codeOr use the skill command:
/security-reviewerClaude will analyze your current code and find security issues. You can also be more specific:
Use security-reviewer to check auth.ts for authentication issuesRun security-reviewer on my API endpointsExample 1: Authentication Code
I’m building a login feature and want to check it for security issues. Here’s my code:
export async function login(username: string, password: string) { const user = await db.query( `SELECT * FROM users WHERE username = '${username}'` )
if (user.password === password) { return generateToken(user.id) }
throw new Error('Invalid credentials')}I ask Claude to review it:
Use security-reviewer to check auth.tsSecurity Reviewer finds two critical issues:
-
SQL Injection: The query interpolates
usernamedirectly, allowing attackers to manipulate the SQL. -
Plaintext Password Comparison: Passwords are stored in plaintext, which is a major security vulnerability.
Here’s the fixed version:
export async function login(username: string, password: string) { // Use parameterized query to prevent SQL injection const user = await db.query( 'SELECT * FROM users WHERE username = $1', [username] )
if (!user) { throw new Error('Invalid credentials') }
// Compare hashed passwords const isValid = await bcrypt.compare(password, user.password_hash)
if (!isValid) { throw new Error('Invalid credentials') }
return generateToken(user.id)}Example 2: Input Validation
I’m creating an API endpoint that accepts user input. Let me check it:
import express from 'express'
const app = express()
app.get('/search', (req, res) => { const query = req.query.q const results = db.query( `SELECT * FROM products WHERE name LIKE '%${query}%'` ) res.json(results)})When I run security-reviewer on this code, it flags:
-
SQL Injection: The
queryparameter is interpolated into the SQL query. -
No Input Validation: No validation on the
qparameter. -
No Rate Limiting: The endpoint is vulnerable to abuse.
Here’s the secure version:
import express from 'express'import rateLimit from 'express-rate-limit'import { z } from 'zod'
const app = express()
// Add rate limitingconst limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100 // limit each IP to 100 requests per windowMs})
app.use('/search', limiter)
// Validate inputconst searchSchema = z.object({ q: z.string().min(1).max(100).regex(/^[a-zA-Z0-9\s]+$/)})
app.get('/search', async (req, res) => { // Validate input const { q } = searchSchema.parse(req.query)
// Use parameterized query const results = await db.query( 'SELECT * FROM products WHERE name LIKE $1', [`%${q}%`] )
res.json(results)})Example 3: Hardcoded Secrets
I accidentally committed an API key in my code:
export const API_KEY = "sk-proj-abc123xyz456"
export async function callExternalAPI(data: any) { const response = await fetch('https://api.example.com/endpoint', { headers: { 'Authorization': `Bearer ${API_KEY}` }, body: JSON.stringify(data) }) return response.json()}When I run security-reviewer, it immediately flags the hardcoded API key. The fix:
export async function callExternalAPI(data: any) { const apiKey = process.env.API_KEY
if (!apiKey) { throw new Error('API_KEY not configured') }
const response = await fetch('https://api.example.com/endpoint', { headers: { 'Authorization': `Bearer ${apiKey}` }, body: JSON.stringify(data) }) return response.json()}Best Practices
DO
- Run security-reviewer before every commit
- Fix CRITICAL and HIGH issues immediately
- Use environment variables for secrets
- Validate all user input with a schema library (Zod, Joi)
- Use parameterized queries for database operations
- Sanitize HTML output to prevent XSS
- Implement rate limiting on public endpoints
- Hash passwords with bcrypt/argon2
- Use HTTPS in production
- Keep dependencies updated
DON’T
- Don’t commit before running security-reviewer
- Don’t ignore CRITICAL or HIGH severity issues
- Don’t hardcode secrets in your code
- Don’t trust user input without validation
- Don’t build SQL queries with string interpolation
- Don’t store passwords in plaintext
- Don’t leak sensitive data in error messages
- Don’t skip security checks for “internal” APIs
Integration with Development Workflow
Security Reviewer works best when integrated into your workflow:
Write code → Run security-reviewer → Fix issues → CommitYou can also use it with other claude-skills:
- tdd-guide: Write tests first, then run security-reviewer
- code-reviewer: Get general code quality feedback after security checks
- planner: Plan secure features from the start
For example:
Use tdd-guide to implement user authentication, then use security-reviewer to check itCommon Issues and Solutions
Issue: False Positives
Sometimes security-reviewer flags code that’s actually safe. For example, using environment variables might trigger a “hardcoded secret” warning if the pattern isn’t recognized.
Solution: Review the issue carefully. If it’s truly safe, document why in a comment.
Issue: Too Many Warnings
A large codebase might have hundreds of security issues.
Solution: Prioritize CRITICAL and HIGH issues first. Use filters to focus on specific files or types of vulnerabilities.
Issue: Performance on Large Codebases
Running security-reviewer on a huge codebase can be slow.
Solution: Run it on specific directories or files:
Use security-reviewer to check the auth/ directoryRelated Skills
- security-review: Core security checking (this skill)
- tdd-guide: Test-driven development workflow
- code-reviewer: General code quality review
- planner: Plan secure features before implementation
Summary
In this post, I showed how to use Security Reviewer in Claude Code to find and fix security vulnerabilities. The key points are:
- Run security-reviewer before every commit
- Fix CRITICAL and HIGH issues immediately
- Never hardcode secrets
- Always validate user input
- Use parameterized queries for databases
Security Reviewer helps you catch vulnerabilities early, before they reach production. It’s not a replacement for security expertise, but it’s an excellent first line of defense for developers at any level.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 claude-skills Documentation
- 👨💻 claude-skills GitHub Repository
- 👨💻 Claude Code Official Documentation
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments