supabase
Handles the full Supabase workflow from schema changes to deployment, with built-in security guardrails that catch common traps like RLS...
audit-expert
Expert-level security auditing, compliance, code review, and vulnerability assessment
Full skill instructions
Expert guidance for security auditing, compliance assessments, code reviews, vulnerability assessments, and regulatory compliance (SOC 2, GDPR, HIPAA, PCI-DSS).
// ❌ Issues to flag
class AuthService {
// Issue 1: Weak password requirements
validatePassword(password) {
return password.length >= 6; // Too short!
}
// Issue 2: Password stored in plaintext
async createUser(email, password) {
await db.users.create({ email, password }); // No hashing!
}
// Issue 3: Timing attack vulnerability
async login(email, password) {
const user = await db.users.findOne({ email });
if (!user) return null;
// Direct comparison reveals timing
if (user.password === password) {
return user;
}
return null;
}
// Issue 4: No rate limiting
// Issue 5: No MFA support
// Issue 6: Predictable session tokens
generateSessionToken() {
return Math.random().toString(36); // Not cryptographically secure!
}
}
// ✅ Secure implementation
const bcrypt = require('bcrypt');
const crypto = require('crypto');
class SecureAuthService {
// Strong password validation
validatePassword(password) {
const minLength = 12;
const hasUppercase = /[A-Z]/.test(password);
const hasLowercase = /[a-z]/.test(password);
const hasNumber = /[0-9]/.test(password);
const hasSpecial = /[^A-Za-z0-9]/.test(password);
return password.length >= minLength &&
hasUppercase && hasLowercase &&
hasNumber && hasSpecial;
}
// Secure password hashing
async hashPassword(password) {
const saltRounds = 12;
return await bcrypt.hash(password, saltRounds);
}
async createUser(email, password) {
if (!this.validatePassword(password)) {
throw new Error('Password does not meet requirements');
}
const passwordHash = await this.hashPassword(password);
await db.users.create({
email: email.toLowerCase(),
passwordHash
});
}
// Constant-time comparison with rate limiting
async login(email, password) {
// Check rate limit
const attempts = await this.getLoginAttempts(email);
if (attempts > 5) {
throw new Error('Too many login attempts. Try again later.');
}
const user = await db.users.findOne({
email: email.toLowerCase()
});
// Always hash password even if user not found (timing attack prevention)
const isValid = user ?
await bcrypt.compare(password, user.passwordHash) :
await bcrypt.compare(password, '$2b$12$dummyhash');
if (!user || !isValid) {
await this.recordFailedAttempt(email);
throw new Error('Invalid credentials');
}
await this.clearLoginAttempts(email);
return user;
}
// Cryptographically secure tokens
generateSessionToken() {
return crypto.randomBytes(32).toString('hex');
}
// MFA support
async verifyMFA(user, token) {
const speakeasy = require('speakeasy');
return speakeasy.totp.verify({
secret: user.mfaSecret,
encoding: 'base32',
token,
window: 2
});
}
}
// Audit checklist for SQL injection:
// 1. Are all queries parameterized?
// 2. Is user input sanitized?
// 3. Are ORM features used correctly?
// 4. Are stored procedures parameterized?
// ❌ Vulnerable patterns to flag
async function searchUsers(name) {
// Issue: String concatenation
const query = `SELECT * FROM users WHERE name = '${name}'`;
return await db.query(query);
}
async function updateUser(id, data) {
// Issue: Dynamic column names not validated
const columns = Object.keys(data).join(', ');
const query = `UPDATE users SET ${columns} WHERE id = ${id}`;
return await db.query(query);
}
// ❌ ORM misuse
async function findUsers(filters) {
// Issue: Raw WHERE clause from user input
return await User.findAll({
where: db.literal(filters.where)
});
}
// ✅ Secure patterns
async function searchUsers(name) {
// Parameterized query
return await db.query(
'SELECT * FROM users WHERE name = ?',
[name]
);
}
async function updateUser(id, data) {
// Whitelist allowed columns
const allowedColumns = ['name', 'email', 'bio'];
const updates = {};
for (const [key, value] of Object.entries(data)) {
if (allowedColumns.includes(key)) {
updates[key] = value;
}
}
return await User.update(updates, {
where: { id }
});
}
async function findUsers(filters) {
// Use ORM query builder
return await User.findAll({
where: {
name: { [Op.like]: `%${filters.name}%` },
active: true
}
});
}
// Audit checklist:
// 1. Is authentication checked before authorization?
// 2. Are resource ownership checks present?
// 3. Is role-based access control implemented?
// 4. Are there direct object reference vulnerabilities?
// ❌ Insecure patterns
app.delete('/api/posts/:id', authenticate, async (req, res) => {
// Issue: No authorization check!
await Post.delete(req.params.id);
res.status(204).send();
});
app.get('/api/documents/:id', async (req, res) => {
// Issue: No authentication at all!
const doc = await Document.findById(req.params.id);
res.json(doc);
});
// ✅ Secure patterns
const authorize = (resource) => async (req, res, next) => {
const item = await db[resource].findById(req.params.id);
if (!item) {
return res.status(404).json({ error: 'Not found' });
}
// Check ownership or admin role
if (item.userId !== req.user.id && !req.user.isAdmin) {
return res.status(403).json({ error: 'Forbidden' });
}
req.resource = item;
next();
};
app.delete('/api/posts/:id',
authenticate,
authorize('posts'),
async (req, res) => {
await req.resource.delete();
res.status(204).send();
}
);
// Role-based access control
const requireRole = (...roles) => (req, res, next) => {
if (!req.user || !roles.includes(req.user.role)) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
next();
};
app.post('/api/admin/users',
authenticate,
requireRole('admin'),
async (req, res) => {
// Admin-only endpoint
}
);
// Audit checklist:
// 1. Is user input escaped in HTML context?
// 2. Is Content-Security-Policy header set?
// 3. Are dangerous functions (eval, innerHTML) avoided?
// 4. Is templating engine auto-escaping enabled?
// ❌ Vulnerable patterns
app.get('/search', (req, res) => {
// Issue: No escaping
res.send(`<h1>Results for: ${req.query.q}</h1>`);
});
app.post('/comment', async (req, res) => {
// Issue: Storing unsanitized HTML
await Comment.create({
text: req.body.comment,
html: req.body.comment // Dangerous!
});
});
// Client-side issues
function displayComment(comment) {
// Issue: Using innerHTML
document.getElementById('comment').innerHTML = comment;
// Issue: Using eval
eval(comment);
}
// ✅ Secure patterns
const escape = require('escape-html');
app.get('/search', (req, res) => {
res.send(`<h1>Results for: ${escape(req.query.q)}</h1>`);
});
// Or use templating with auto-escape
app.get('/search', (req, res) => {
res.render('search', { query: req.query.q }); // Auto-escaped
});
// Content Security Policy
app.use((req, res, next) => {
res.setHeader('Content-Security-Policy',
"default-src 'self'; " +
"script-src 'self'; " +
"style-src 'self' 'unsafe-inline'; " +
"img-src 'self' data: https:;"
);
next();
});
// Client-side: Use textContent
function displayComment(comment) {
document.getElementById('comment').textContent = comment;
}
// GDPR Requirements Audit
// 1. Lawful Basis for Processing
// ✓ Explicit consent obtained
// ✓ Purpose clearly stated
// ✓ Option to withdraw consent
// 2. Data Minimization
// Review: Are we collecting only necessary data?
async function createUser(data) {
// ❌ Collecting too much
const user = {
email: data.email,
password: data.password,
ssn: data.ssn, // Unnecessary!
medicalHistory: data.medical, // Unnecessary!
location: data.location // May be unnecessary
};
// ✅ Only essential data
const user = {
email: data.email,
passwordHash: await hashPassword(data.password)
};
}
// 3. Right to Access (Subject Access Request)
app.get('/api/gdpr/data', authenticate, async (req, res) => {
const userData = {
personalInfo: await User.findById(req.user.id),
posts: await Post.findByUserId(req.user.id),
comments: await Comment.findByUserId(req.user.id),
loginHistory: await LoginHistory.findByUserId(req.user.id)
};
res.json(userData);
});
// 4. Right to Erasure (Right to be Forgotten)
app.delete('/api/gdpr/delete-account', authenticate, async (req, res) => {
const userId = req.user.id;
await db.transaction(async (tx) => {
// Anonymize or delete personal data
await User.anonymize(userId, tx);
await Post.anonymizeByUser(userId, tx);
await Comment.anonymizeByUser(userId, tx);
// Keep audit logs (legal requirement)
await AuditLog.create({
action: 'account_deletion',
userId,
timestamp: new Date()
}, tx);
});
res.status(204).send();
});
// 5. Right to Data Portability
app.get('/api/gdpr/export', authenticate, async (req, res) => {
const data = await exportUserData(req.user.id);
res.setHeader('Content-Type', 'application/json');
res.setHeader('Content-Disposition', 'attachment; filename="my-data.json"');
res.json(data);
});
// 6. Breach Notification (72 hours)
async function handleDataBreach(breach) {
// Log breach
await SecurityIncident.create({
type: 'data_breach',
severity: breach.severity,
affectedUsers: breach.userIds.length,
detectedAt: new Date()
});
// Notify authorities within 72 hours if high risk
if (breach.severity === 'high') {
await notifyDataProtectionAuthority(breach);
}
// Notify affected users
for (const userId of breach.userIds) {
await notifyUserOfBreach(userId, breach);
}
}
// 7. Privacy by Design
// - Encryption at rest and in transit
// - Access controls
// - Audit logging
// - Data retention policies
// 8. Data Processing Agreement
// - Document third-party processors
// - Ensure processor compliance
// - Review contracts
// SOC 2 Trust Service Criteria
// 1. Security - Access Control
class AccessControlAudit {
async auditUserAccess() {
// Review user permissions
const users = await User.findAll();
const issues = [];
for (const user of users) {
// Check for overprivileged users
if (user.role === 'admin' && !user.adminJustification) {
issues.push({
type: 'excessive_privilege',
user: user.email,
message: 'Admin access without justification'
});
}
// Check for inactive users with access
const daysSinceLogin = daysBetween(user.lastLoginAt, new Date());
if (daysSinceLogin > 90) {
issues.push({
type: 'stale_access',
user: user.email,
message: `No login for ${daysSinceLogin} days`
});
}
}
return issues;
}
async auditAPIKeys() {
const apiKeys = await APIKey.findAll();
const issues = [];
for (const key of apiKeys) {
// Check for keys without expiration
if (!key.expiresAt) {
issues.push({
type: 'no_expiration',
keyId: key.id,
message: 'API key has no expiration'
});
}
// Check for unused keys
if (!key.lastUsedAt ||
daysBetween(key.lastUsedAt, new Date()) > 90) {
issues.push({
type: 'unused_key',
keyId: key.id,
message: 'API key not used in 90 days'
});
}
}
return issues;
}
}
// 2. Availability - Monitoring
class AvailabilityAudit {
async auditMonitoring() {
const checks = [
{ name: 'Health checks configured', check: this.hasHealthChecks },
{ name: 'Uptime monitoring active', check: this.hasUptimeMonitoring },
{ name: 'Alert policies defined', check: this.hasAlertPolicies },
{ name: 'On-call rotation configured', check: this.hasOnCallRotation },
{ name: 'Backup systems tested', check: this.hasBackupTesting }
];
const results = await Promise.all(
checks.map(async (check) => ({
name: check.name,
passed: await check.check()
}))
);
return results;
}
}
// 3. Processing Integrity - Data Validation
class ProcessingIntegrityAudit {
async auditDataValidation() {
// Review all API endpoints for input validation
const endpoints = [
{ path: '/api/users', method: 'POST' },
{ path: '/api/posts', method: 'POST' },
// ... all endpoints
];
const issues = [];
for (const endpoint of endpoints) {
const hasValidation = await this.checkValidation(endpoint);
if (!hasValidation) {
issues.push({
endpoint: `${endpoint.method} ${endpoint.path}`,
message: 'Missing input validation'
});
}
}
return issues;
}
}
// 4. Confidentiality - Encryption Audit
class ConfidentialityAudit {
async auditEncryption() {
const issues = [];
// Check encryption at rest
const tables = await this.getDatabaseTables();
for (const table of tables) {
if (table.containsSensitiveData && !table.encrypted) {
issues.push({
type: 'encryption_at_rest',
table: table.name,
message: 'Sensitive data not encrypted'
});
}
}
// Check TLS configuration
const tlsConfig = await this.getTLSConfig();
if (tlsConfig.version < '1.2') {
issues.push({
type: 'weak_tls',
message: 'TLS version below 1.2'
});
}
// Check for hardcoded secrets
const secrets = await this.scanForHardcodedSecrets();
if (secrets.length > 0) {
issues.push({
type: 'hardcoded_secrets',
count: secrets.length,
message: 'Found hardcoded secrets in code'
});
}
return issues;
}
}
// 5. Privacy - Data Retention
class PrivacyAudit {
async auditDataRetention() {
// Check for data retention policies
const policies = await DataRetentionPolicy.findAll();
const issues = [];
if (policies.length === 0) {
issues.push({
type: 'no_retention_policy',
message: 'No data retention policies defined'
});
}
// Check for old data
const oldRecords = await this.findOldRecords();
for (const record of oldRecords) {
issues.push({
type: 'old_data',
table: record.table,
count: record.count,
message: `${record.count} records older than retention period`
});
}
return issues;
}
}
// PCI-DSS Requirements for Payment Card Data
// 1. Never store sensitive authentication data after authorization
// ❌ Don't store:
// - Full magnetic stripe data
// - CVV2/CVC2/CID
// - PIN/PIN blocks
// ✅ Can store (encrypted):
// - Primary Account Number (PAN)
// - Cardholder name
// - Expiration date
// - Service code
class PCICompliantPayment {
async processPayment(cardData) {
// ❌ Never log card data
// console.log('Processing card:', cardData); // VIOLATION!
// ✅ Use payment processor (tokenization)
const token = await stripe.tokens.create({
card: {
number: cardData.number,
exp_month: cardData.expMonth,
exp_year: cardData.expYear,
cvc: cardData.cvc
}
});
// Store only token, not actual card data
await Payment.create({
userId: cardData.userId,
amount: cardData.amount,
stripeToken: token.id,
last4: cardData.number.slice(-4), // OK to store
// ❌ Don't store: cardNumber, cvv, etc.
});
const charge = await stripe.charges.create({
amount: cardData.amount,
currency: 'usd',
source: token.id
});
return charge;
}
async auditCardDataStorage() {
// Scan database for potential card data
const suspiciousColumns = [
'card_number', 'cvv', 'pin', 'magnetic_stripe'
];
const issues = [];
const tables = await this.getDatabaseTables();
for (const table of tables) {
for (const column of table.columns) {
if (suspiciousColumns.includes(column.name.toLowerCase())) {
issues.push({
type: 'potential_card_data_storage',
table: table.name,
column: column.name,
message: 'Possible storage of prohibited card data'
});
}
}
}
return issues;
}
}
// 2. Mask PAN when displayed
function maskCardNumber(pan) {
// Show only last 4 digits
return `****-****-****-${pan.slice(-4)}`;
}
// 3. Encryption of cardholder data
// - Use strong cryptography (AES-256)
// - Secure key management
// - Keys separate from data
class SecurityAuditReport {
constructor() {
this.findings = [];
this.summary = {
critical: 0,
high: 0,
medium: 0,
low: 0,
info: 0
};
}
addFinding(finding) {
this.findings.push({
id: this.findings.length + 1,
severity: finding.severity,
title: finding.title,
description: finding.description,
location: finding.location,
recommendation: finding.recommendation,
references: finding.references || [],
cvssScore: finding.cvssScore,
status: 'open',
discoveredAt: new Date()
});
this.summary[finding.severity]++;
}
generateReport() {
return {
reportDate: new Date(),
auditor: 'Security Team',
scope: this.scope,
summary: this.summary,
findings: this.findings.sort((a, b) =>
this.severityWeight(b.severity) - this.severityWeight(a.severity)
),
recommendations: this.generateRecommendations()
};
}
severityWeight(severity) {
const weights = { critical: 5, high: 4, medium: 3, low: 2, info: 1 };
return weights[severity] || 0;
}
generateRecommendations() {
return [
'Address all critical and high severity findings immediately',
'Implement security code review process',
'Conduct regular penetration testing',
'Provide security training for developers',
'Establish vulnerability disclosure program'
];
}
}
// Usage
const audit = new SecurityAuditReport();
audit.addFinding({
severity: 'critical',
title: 'SQL Injection in User Search',
description: 'User search endpoint concatenates user input into SQL query',
location: 'src/controllers/users.js:45',
recommendation: 'Use parameterized queries or ORM with proper escaping',
references: ['CWE-89', 'OWASP A03:2021'],
cvssScore: 9.8
});
const report = audit.generateReport();
❌ Auditing own code: Use independent reviewers ❌ Incomplete scope: Define clear boundaries ❌ No follow-up: Track remediation to completion ❌ Generic findings: Provide specific, actionable recommendations ❌ Ignoring context: Consider business requirements ❌ No prioritization: Rank findings by risk and impact
Handles the full Supabase workflow from schema changes to deployment, with built-in security guardrails that catch common traps like RLS...
Comprehensive guides and best practices for Neon Serverless Postgres, covering setup, connection methods, authentication, and platform APIs.
Guide for setting up and using Firebase Authentication. Use this skill when the user's app requires user sign-in, user management, or secure data access using auth rules.
A skill to evaluate how secure Firestore security rules are. Use this when Firestore security rules are updated to ensure that the generated rules are extremely secure and robust.
Official skill for integrating Firebase AI Logic (Gemini API) into web applications. Covers setup, multimodal inference, structured output, and security.
Complete Better Auth server and client setup with database adapters, session management, plugins, and security configuration.
Deploy and manage projects on Vercel using token-based authentication. Use when working with Vercel CLI using access tokens rather than interactive login — e.g. "deploy to vercel", "set up vercel", "add environment variables to vercel".
Complete Cloudflare platform integration with decision trees for compute, storage, AI, networking, security, and infrastructure-as-code.
Run Azure compliance and security audits with azqr plus Key Vault expiration checks. Covers best-practice assessment, resource review, policy/compliance validation, and security posture checks. WHEN: compliance scan, security audit, BEFORE running azqr (compliance cli tool), Azure best practices, Key Vault expiration check, expired certificates, expiring secrets, orphaned resources, compliance assessment.
Send, read, and manage Gmail messages, drafts, labels, and account settings.
Comprehensive website auditing across 230+ rules in 21 categories including SEO, performance, security, and accessibility.
Shared authentication, CLI syntax, and output formatting patterns for gws Google Workspace commands.
Discover your celebrity doppelgänger with StarByFace!
GeoSpy: Pricing, Features, FAQs, and Alternatives for AI Teams
Detect AI-generated voices to protect against audio fraud.
Ensure Your Content's Originality with AI Plagiarism Checker
Upscale images by 400% without quality loss
Protect your social media from copyright disputes
Accurately Detect AI-Generated Content with TheChecker.AI
Chrome extension that detects and flags AI-generated content