api-and-interface-desi…
Guides stable API and interface design. Use when designing APIs, module boundaries, or any public interface. Use when creating…
Hardens code against vulnerabilities. Use when handling user input, authentication, data storage, or external integrations. Use when building any feature that accepts untrusted data, manages user sessions, or interacts with third-party services.
Claude Code
$ npx -y skills add kevinnft/ai-agent-skills --skill security-and-hardening --agent claude-code
Codex
$ npx skills add kevinnft/ai-agent-skills --skill security-and-hardening -a codex -y
Cursor
$ npx skills add kevinnft/ai-agent-skills --skill security-and-hardening -a cursor -y
Gemini CLI
$ npx skills add kevinnft/ai-agent-skills --skill security-and-hardening -a gemini-cli -y
GitHub Copilot
$ npx skills add kevinnft/ai-agent-skills --skill security-and-hardening -a github-copilot -y
OpenCode
$ npx skills add kevinnft/ai-agent-skills --skill security-and-hardening -a opencode -y
Windsurf
$ npx skills add kevinnft/ai-agent-skills --skill security-and-hardening -a windsurf -y
name: security-and-hardening description: Hardens code against vulnerabilities. Use when handling user input, authentication, data storage, or external integrations. Use when building any feature that accepts untrusted data, manages user sessions, or interacts with third-party services. source_repo: "addyosmani/agent-skills" source_url: "https://github.com/addyosmani/agent-skills" source_license: "MIT" origin: aggregated language: en
Security-first development practices for web applications. Treat every external input as hostile, every secret as sacred, and every authorization check as mandatory. Security isn't a phase — it's a constraint on every line of code that touches user data, authentication, or external systems.
// BAD: SQL injection via string concatenation
const query = `SELECT * FROM users WHERE id = '${userId}'`;
// GOOD: Parameterized query
const user = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
// GOOD: ORM with parameterized input
const user = await prisma.user.findUnique({ where: { id: userId } });// Password hashing
import { hash, compare } from 'bcrypt';
const SALT_ROUNDS = 12;
const hashedPassword = await hash(plaintext, SALT_ROUNDS);
const isValid = await compare(plaintext, hashedPassword);
// Session management
app.use(session({
secret: process.env.SESSION_SECRET, // From environment, not code
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true, // Not accessible via JavaScript
secure: true, // HTTPS only
sameSite: 'lax', // CSRF protection
maxAge: 24 * 60 * 60 * 1000, // 24 hours
},
}));// BAD: Rendering user input as HTML
element.innerHTML = userInput;
// GOOD: Use framework auto-escaping (React does this by default)
return <div>{userInput}</div>;
// If you MUST render HTML, sanitize first
import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(userInput);// Always check authorization, not just authentication
app.patch('/api/tasks/:id', authenticate, async (req, res) => {
const task = await taskService.findById(req.params.id);
// Check that the authenticated user owns this resource
if (task.ownerId !== req.user.id) {
return res.status(403).json({
error: { code: 'FORBIDDEN', message: 'Not authorized to modify this task' }
});
}
// Proceed with update
const updated = await taskService.update(req.params.id, req.body);
return res.json(updated);
});// Security headers (use helmet for Express)
import helmet from 'helmet';
app.use(helmet());
// Content Security Policy
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"], // Tighten if possible
imgSrc: ["'self'", 'data:', 'https:'],
connectSrc: ["'self'"],
},
}));
// CORS — restrict to known origins
app.use(cors({
origin: process.env.ALLOWED_ORIGINS?.split(',') || 'http://localhost:3000',
credentials: true,
}));// Never return sensitive fields in API responses
function sanitizeUser(user: UserRecord): PublicUser {
const { passwordHash, resetToken, ...publicFields } = user;
return publicFields;
}
// Use environment variables for secrets
const API_KEY = process.env.STRIPE_API_KEY;
if (!API_KEY) throw new Error('STRIPE_API_KEY not configured');import { z } from 'zod';
const CreateTaskSchema = z.object({
title: z.string().min(1).max(200).trim(),
description: z.string().max(2000).optional(),
priority: z.enum(['low', 'medium', 'high']).default('medium'),
dueDate: z.string().datetime().optional(),
});
// Validate at the route handler
app.post('/api/tasks', async (req, res) => {
const result = CreateTaskSchema.safeParse(req.body);
if (!result.success) {
return res.status(422).json({191 attribution-first agent skills for Hermes Agent, Claude Code, Cursor — one installer, 28 categories, searchable catalog. See NOTICE for upstream attribution.
Guides stable API and interface design. Use when designing APIs, module boundaries, or any public interface. Use when creating…
Tests in real browsers. Use when building or debugging anything that runs in a browser. Use when you need to inspect the DOM,…
Automates CI/CD pipeline setup. Use when setting up or modifying build and deployment pipelines. Use when you need to automate…
Conducts multi-axis code review. Use before merging any change. Use when reviewing code written by yourself, another agent, or a…
Simplifies code for clarity. Use when refactoring code for clarity without changing behavior. Use when code works but is harder…
Optimizes agent context setup. Use when starting a new session, when agent output quality degrades, when switching between tasks,…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.