From PACT
Provides SACROSANCT security rules and patterns for PACT framework development, including credential protection, backend proxy architecture, input validation with Express.js, and vulnerability checklists.
How this skill is triggered — by the user, by Claude, or both
Slash command
/PACT:pact-security-patternsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Security guidance for PACT development phases. This skill provides essential security
Security guidance for PACT development phases. This skill provides essential security patterns and links to detailed references for comprehensive implementation.
These rules are ABSOLUTE and must NEVER be violated.
NEVER ALLOW in version control:
ONLY acceptable locations for actual credentials:
| Location | Example | Security Level |
|---|---|---|
.env files in .gitignore | API_KEY=sk-xxx | Development |
Server-side process.env | process.env.API_KEY | Runtime |
| Deployment platform secrets | Railway, Vercel, AWS | Production |
| Secrets managers | Vault, AWS Secrets Manager | Enterprise |
In Documentation - Always Use Placeholders:
# Configuration
Set your API key in `.env`:
API_KEY=your_api_key_here
WRONG: Frontend --> External API (credentials in frontend)
CORRECT: Frontend --> Backend Proxy --> External API
Architecture Requirements:
/api/resource) without credentialsVerification Checklist:
# Build the application
npm run build
# Search for exposed credentials in bundle
grep -r "sk-" dist/assets/*.js
grep -r "api_key" dist/assets/*.js
grep -r "VITE_" dist/assets/*.js
# All above should return NO results
Always validate on the server side:
// Express.js example
const { body, validationResult } = require('express-validator');
app.post('/api/user',
body('email').isEmail().normalizeEmail(),
body('name').trim().escape().isLength({ min: 1, max: 100 }),
body('age').isInt({ min: 0, max: 150 }),
(req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
// Process validated input
}
);
Prevent XSS by encoding output:
// React (automatic encoding)
return <div>{userInput}</div>; // Safe - React escapes
// Dangerous - avoid unless absolutely necessary
return <div dangerouslySetInnerHTML={{__html: userInput}} />; // UNSAFE
// Node.js HTML response
const escapeHtml = (str) => str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
Always use parameterized queries:
// WRONG - SQL Injection vulnerable
const query = `SELECT * FROM users WHERE id = ${userId}`;
// CORRECT - Parameterized query
const query = 'SELECT * FROM users WHERE id = $1';
const result = await db.query(query, [userId]);
// ORM example (Prisma)
const user = await prisma.user.findUnique({
where: { id: userId } // Safe - Prisma handles escaping
});
Password Storage:
const bcrypt = require('bcrypt');
// Hashing password
const saltRounds = 12; // Minimum recommended
const hashedPassword = await bcrypt.hash(password, saltRounds);
// Verifying password
const isValid = await bcrypt.compare(password, hashedPassword);
Session Configuration:
app.use(session({
secret: process.env.SESSION_SECRET, // Strong, random secret
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // HTTPS only
httpOnly: true, // No JavaScript access
sameSite: 'strict', // CSRF protection
maxAge: 3600000 // 1 hour
}
}));
Essential HTTP headers:
const helmet = require('helmet');
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'"],
frameSrc: ["'none'"],
objectSrc: ["'none'"]
}
},
hsts: {
maxAge: 31536000,
includeSubDomains: true
}
}));
Protect against abuse:
const rateLimit = require('express-rate-limit');
// General API rate limit
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100,
message: { error: 'Too many requests, please try again later' }
});
// Stricter limit for auth endpoints
const authLimiter = rateLimit({
windowMs: 60 * 60 * 1000, // 1 hour
max: 5,
message: { error: 'Too many login attempts' }
});
app.use('/api/', apiLimiter);
app.use('/api/auth/', authLimiter);
Before any commit or deployment, verify:
git diff --staged | grep -i "key\|secret\|password").env files listed in .gitignoreFor comprehensive security guidance, see:
OWASP Top 10 Mitigations: references/owasp-top-10.md
Authentication Patterns: references/authentication-patterns.md
Data Protection: references/data-protection.md
npx claudepluginhub synaptic-labs-ai/pact-plugin --plugin PACTGuides implementation of authentication (JWT, OAuth2, sessions), authorization (RBAC), encryption, secrets management, CORS, and rate limiting with code examples and anti-pattern checks.
Guides application security reviews and implementation covering OWASP Top 10, input validation, auth, secrets management, and antipatterns.
Provides OWASP Top 10 guidelines, secure Python/Flask coding patterns, prevention strategies, and remediation for access control and cryptographic vulnerabilities.