Agent skill
security
Security auditing for code vulnerabilities (OWASP Top 10, XSS, SQL injection) and dependency scanning (pnpm audit, Snyk). Use when handling user input, adding authentication, before deployments, or resolving CVEs.
Install this agent skill to your Project
npx add-skill https://github.com/sgcarstrends/sgcarstrends/tree/main/.claude/skills/security
SKILL.md
Security Skill
Dependency Scanning
pnpm audit
# Run audit
pnpm audit
# Only high/critical
pnpm audit --audit-level=high
# Auto-fix
pnpm audit --fix
# JSON report
pnpm audit --json > audit.json
Fix Vulnerabilities
Direct dependencies: Update version in pnpm-workspace.yaml catalog
Transitive dependencies:
# Find dependency chain
pnpm why vulnerable-package
# Use overrides as last resort
# package.json
{
"pnpm": {
"overrides": {
"vulnerable-package": "^3.1.0"
}
}
}
Snyk
snyk auth # Authenticate
snyk test # Test for vulnerabilities
snyk monitor # Monitor for new vulnerabilities
snyk fix # Auto-fix
OWASP Top 10 Checks
1. Broken Access Control
// ❌ No authorization
export async function deletePost(postId: string) {
await db.delete(posts).where(eq(posts.id, postId));
}
// ✅ With authorization
export async function deletePost(postId: string, userId: string) {
const post = await db.query.posts.findFirst({ where: eq(posts.id, postId) });
if (post.authorId !== userId) throw new Error("Unauthorized");
await db.delete(posts).where(eq(posts.id, postId));
}
2. Injection Prevention
// ❌ SQL Injection
const query = `SELECT * FROM users WHERE id = ${userId}`;
// ✅ Parameterized query (Drizzle ORM)
const user = await db.query.users.findFirst({ where: eq(users.id, userId) });
3. XSS Prevention
React escapes content by default. When rendering HTML:
- Sanitize with
sanitize-htmllibrary before rendering - Never render untrusted content directly
4. Rate Limiting
import { Ratelimit } from "@upstash/ratelimit";
import { redis } from "@sgcarstrends/utils";
const ratelimit = new Ratelimit({
redis,
limiter: Ratelimit.slidingWindow(5, "15 m"),
});
export async function login(email: string, password: string, ip: string) {
const { success } = await ratelimit.limit(ip);
if (!success) throw new Error("Too many login attempts");
return verifyCredentials(email, password);
}
5. Password Security
import bcrypt from "bcrypt";
// ✅ Hash passwords
const hashedPassword = await bcrypt.hash(password, 10);
// ✅ Strong password validation
const passwordSchema = z.string()
.min(12)
.regex(/[A-Z]/, "Must contain uppercase")
.regex(/[a-z]/, "Must contain lowercase")
.regex(/[0-9]/, "Must contain number")
.regex(/[^A-Za-z0-9]/, "Must contain special character");
6. SSRF Prevention
// ❌ SSRF vulnerability
export async function fetchUrl(url: string) {
return await fetch(url);
}
// ✅ Whitelist approach
const ALLOWED_DOMAINS = ["api.example.com", "data.gov.sg"];
export async function fetchUrl(url: string) {
const parsedUrl = new URL(url);
if (!ALLOWED_DOMAINS.includes(parsedUrl.hostname)) {
throw new Error("Domain not allowed");
}
return await fetch(url);
}
Input Validation
import { z } from "zod";
const userInputSchema = z.object({
name: z.string().min(1).max(100),
email: z.string().email(),
age: z.number().int().min(0).max(150),
});
export async function createUser(data: unknown) {
const validated = userInputSchema.parse(data);
// Now safe to use
}
CORS Configuration
// ❌ Too permissive
app.use(cors({ origin: "*" }));
// ✅ Whitelist specific origins
app.use(cors({
origin: [
"https://sgcarstrends.com",
"https://staging.sgcarstrends.com",
process.env.NODE_ENV === "development" ? "http://localhost:3001" : "",
].filter(Boolean),
credentials: true,
}));
Security Headers
// next.config.js
const securityHeaders = [
{ key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains; preload" },
{ key: "X-Frame-Options", value: "SAMEORIGIN" },
{ key: "X-Content-Type-Options", value: "nosniff" },
{ key: "X-XSS-Protection", value: "1; mode=block" },
{ key: "Referrer-Policy", value: "origin-when-cross-origin" },
];
module.exports = {
async headers() {
return [{ source: "/:path*", headers: securityHeaders }];
},
};
Environment Variables
// ❌ Hardcoded secret
const apiKey = "sk_live_EXAMPLE_NOT_REAL";
// ✅ From environment with validation
import { z } from "zod";
const envSchema = z.object({
API_KEY: z.string().min(1),
DATABASE_URL: z.string().url(),
});
const env = envSchema.parse(process.env);
CI Integration
# .github/workflows/security.yml
name: Security Audit
on:
push:
branches: [main]
schedule:
- cron: '0 0 * * 1' # Weekly
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- run: pnpm install
- run: pnpm audit --audit-level=high
Security Checklist
- All user input validated (Zod schemas)
- SQL injection prevented (using ORM)
- XSS prevented (React escaping, sanitization)
- Authentication implemented correctly
- Authorization checks in place
- Passwords hashed (bcrypt/argon2)
- Rate limiting configured
- Security headers set
- CORS configured properly
- HTTPS enforced
- Dependencies audited (pnpm audit)
- Secrets in environment variables
- Error messages don't leak info
References
- OWASP Top 10: https://owasp.org/www-project-top-ten
- pnpm Audit: https://pnpm.io/cli/audit
- Snyk: https://snyk.io
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
component-tester
Run Vitest tests for a specific component with coverage. Use when making changes to React components to ensure tests pass and coverage is maintained.
cache-components
Ensure 'use cache' is used strategically to minimize CPU usage and ISR writes. Use when creating/modifying queries to verify caching decisions align with data update patterns and cost optimization.
ui-design-system
Enforce modern dashboard UI patterns with pill-shaped design, professional colour scheme, and typography standards. Use when building or reviewing UI components for the web application.
typography-spacing-enforcer
Enforce Typography system and modern spacing conventions. Use when implementing new UI components to ensure design consistency with project standards.
conventional-commits
Format commit messages following project conventions with commitlint validation. Use when committing changes, writing PR descriptions, or preparing releases.
dependency-upgrade
Upgrade dependencies safely using pnpm catalog, checking for breaking changes, and testing upgrades. Use when updating packages, applying security patches, upgrading major versions, resolving dependency conflicts, or modernizing tech stack.
Didn't find tool you were looking for?