security-audit
Access: /template security-audit or /t security-audit
Performs a comprehensive security audit of your MakerKit application, identifying vulnerabilities and recommending fixes.
What It Does
The security-audit command helps you:
- Scan for common security vulnerabilities
- Check authentication and authorization
- Review database security and RLS policies
- Audit API endpoints and webhooks
- Check for exposed secrets and credentials
- Review security headers and CSP
- Generate security report with fixes
Usage
bash
/template security-audit "Description"
# or
/t security-audit "Description"When prompted, specify:
- Audit depth (basic, comprehensive, pentesting)
- Areas to focus on
- Compliance requirements
- Report format preference
Prerequisites
- A MakerKit application to audit
- Understanding of security requirements
- Commercial MakerKit license from MakerKit
What Gets Checked
1. Authentication Security
typescript
// Checks performed:
const authenticationChecks = [
{
name: 'Password Policy',
check: async () => {
// Check password requirements
const policy = await getPasswordPolicy();
const issues = [];
if (policy.minLength < 8) {
issues.push('Password minimum length should be at least 8 characters');
}
if (!policy.requireUppercase) {
issues.push('Should require uppercase letters');
}
if (!policy.requireNumbers) {
issues.push('Should require numbers');
}
if (!policy.requireSpecialChars) {
issues.push('Should require special characters');
}
return { passed: issues.length === 0, issues };
},
},
{
name: 'Session Management',
check: async () => {
const issues = [];
// Check session timeout
if (!process.env.SESSION_TIMEOUT || parseInt(process.env.SESSION_TIMEOUT) > 86400) {
issues.push('Session timeout should be configured and less than 24 hours');
}
// Check secure cookies
const cookieConfig = await getCookieConfiguration();
if (!cookieConfig.secure && process.env.NODE_ENV === 'production') {
issues.push('Cookies must use secure flag in production');
}
if (!cookieConfig.httpOnly) {
issues.push('Auth cookies should use httpOnly flag');
}
if (!cookieConfig.sameSite) {
issues.push('Cookies should use sameSite attribute');
}
return { passed: issues.length === 0, issues };
},
},
{
name: 'Multi-Factor Authentication',
check: async () => {
const mfaEnabled = await isMFAAvailable();
const mfaEnforced = await isMFAEnforced();
const issues = [];
if (!mfaEnabled) {
issues.push('MFA should be available for all users');
}
if (!mfaEnforced) {
issues.push('Consider enforcing MFA for admin accounts');
}
return { passed: issues.length === 0, issues };
},
},
];2. Authorization & Access Control
typescript
// RLS Policy Audit
async function auditRLSPolicies() {
const tables = await getPublicTables();
const issues = [];
for (const table of tables) {
// Check if RLS is enabled
const rlsEnabled = await isRLSEnabled(table);
if (!rlsEnabled) {
issues.push({
severity: 'critical',
table,
issue: 'Row Level Security is not enabled',
fix: `ALTER TABLE public.${table} ENABLE ROW LEVEL SECURITY;`,
});
}
// Check for policies
const policies = await getTablePolicies(table);
if (policies.length === 0 && rlsEnabled) {
issues.push({
severity: 'critical',
table,
issue: 'RLS enabled but no policies defined',
fix: 'Add appropriate policies for all operations',
});
}
// Check for overly permissive policies
for (const policy of policies) {
if (policy.definition.includes('true')) {
issues.push({
severity: 'high',
table,
policy: policy.name,
issue: 'Policy may be overly permissive',
fix: 'Review policy to ensure proper access control',
});
}
}
}
return issues;
}
// API Endpoint Security
async function auditAPIEndpoints() {
const endpoints = await scanAPIRoutes();
const issues = [];
for (const endpoint of endpoints) {
// Check authentication
if (!endpoint.requiresAuth && endpoint.modifiesData) {
issues.push({
severity: 'high',
endpoint: endpoint.path,
issue: 'Data-modifying endpoint lacks authentication',
});
}
// Check rate limiting
if (!endpoint.hasRateLimit) {
issues.push({
severity: 'medium',
endpoint: endpoint.path,
issue: 'No rate limiting configured',
});
}
// Check input validation
if (!endpoint.hasValidation) {
issues.push({
severity: 'high',
endpoint: endpoint.path,
issue: 'Missing input validation',
});
}
}
return issues;
}3. Data Security
typescript
// Database Security Checks
const databaseSecurityChecks = [
{
name: 'Encryption at Rest',
check: async () => {
const encrypted = await isDatabaseEncrypted();
return {
passed: encrypted,
issue: 'Database should be encrypted at rest',
fix: 'Enable encryption in Supabase dashboard',
};
},
},
{
name: 'Connection Security',
check: async () => {
const issues = [];
// Check SSL enforcement
if (!process.env.DATABASE_URL?.includes('sslmode=require')) {
issues.push('Database connections should require SSL');
}
// Check for exposed credentials
if (process.env.DATABASE_URL?.includes('@db.')) {
issues.push('Using direct database URL instead of Supabase client');
}
return { passed: issues.length === 0, issues };
},
},
{
name: 'Sensitive Data Handling',
check: async () => {
const issues = [];
// Check for PII in logs
const logsContainPII = await scanLogsForPII();
if (logsContainPII) {
issues.push('Logs may contain personally identifiable information');
}
// Check for unencrypted sensitive fields
const unencryptedFields = await findUnencryptedSensitiveData();
if (unencryptedFields.length > 0) {
issues.push(`Sensitive fields not encrypted: ${unencryptedFields.join(', ')}`);
}
return { passed: issues.length === 0, issues };
},
},
];4. Dependency Vulnerabilities
typescript
// NPM Audit
async function auditDependencies() {
const { stdout } = await execAsync('npm audit --json');
const audit = JSON.parse(stdout);
const vulnerabilities = {
critical: [],
high: [],
moderate: [],
low: [],
};
for (const [, advisory] of Object.entries(audit.advisories || {})) {
vulnerabilities[advisory.severity].push({
module: advisory.module_name,
title: advisory.title,
severity: advisory.severity,
vulnerable_versions: advisory.vulnerable_versions,
recommendation: advisory.recommendation,
fix: advisory.patched_versions,
});
}
return vulnerabilities;
}
// Outdated Dependencies
async function checkOutdatedDependencies() {
const { stdout } = await execAsync('npm outdated --json');
const outdated = JSON.parse(stdout);
const criticalPackages = [
'next',
'@supabase/supabase-js',
'stripe',
'@node-saml/node-saml',
];
const issues = [];
for (const [pkg, info] of Object.entries(outdated)) {
if (criticalPackages.includes(pkg)) {
const current = info.current;
const latest = info.latest;
if (semver.major(latest) > semver.major(current)) {
issues.push({
package: pkg,
current,
latest,
severity: 'high',
message: 'Major version behind, may have security fixes',
});
}
}
}
return issues;
}5. Secret Management
typescript
// Secret Scanning
async function scanForSecrets() {
const secretPatterns = [
{
name: 'AWS Access Key',
pattern: /AKIA[0-9A-Z]{16}/g,
},
{
name: 'Private Key',
pattern: /-----BEGIN (RSA |EC )?PRIVATE KEY-----/g,
},
{
name: 'API Key',
pattern: /api[_-]?key[_-]?[:=]\s*['"]?[a-zA-Z0-9]{32,}['"]?/gi,
},
{
name: 'JWT Secret',
pattern: /jwt[_-]?secret[_-]?[:=]\s*['"]?[a-zA-Z0-9]{32,}['"]?/gi,
},
];
const issues = [];
const files = await glob('**/*.{js,ts,jsx,tsx,json,env}', {
ignore: ['node_modules/**', '.next/**', 'dist/**'],
});
for (const file of files) {
const content = await fs.readFile(file, 'utf-8');
for (const { name, pattern } of secretPatterns) {
const matches = content.match(pattern);
if (matches) {
issues.push({
file,
type: name,
severity: 'critical',
message: `Potential ${name} found in source code`,
});
}
}
}
return issues;
}
// Environment Variable Audit
async function auditEnvironmentVariables() {
const issues = [];
// Check for secrets in repository
if (await fileExists('.env')) {
issues.push({
severity: 'critical',
message: '.env file found in repository',
fix: 'Add .env to .gitignore and remove from repository',
});
}
// Check for missing required variables
const requiredVars = [
'NEXT_PUBLIC_SUPABASE_URL',
'SUPABASE_SERVICE_ROLE_KEY',
'STRIPE_SECRET_KEY',
'STRIPE_WEBHOOK_SECRET',
];
for (const varName of requiredVars) {
if (!process.env[varName]) {
issues.push({
severity: 'high',
message: `Missing required environment variable: ${varName}`,
});
}
}
return issues;
}6. Security Headers
typescript
// Header Security Audit
async function auditSecurityHeaders() {
const response = await fetch(process.env.NEXT_PUBLIC_APP_URL!);
const headers = response.headers;
const requiredHeaders = {
'strict-transport-security': {
expected: /max-age=31536000/,
severity: 'high',
message: 'HSTS header missing or misconfigured',
},
'x-frame-options': {
expected: /DENY|SAMEORIGIN/,
severity: 'medium',
message: 'X-Frame-Options header missing',
},
'x-content-type-options': {
expected: /nosniff/,
severity: 'medium',
message: 'X-Content-Type-Options header missing',
},
'content-security-policy': {
expected: /default-src/,
severity: 'high',
message: 'Content Security Policy not configured',
},
'permissions-policy': {
expected: /.+/,
severity: 'low',
message: 'Permissions Policy not configured',
},
};
const issues = [];
for (const [header, config] of Object.entries(requiredHeaders)) {
const value = headers.get(header);
if (!value || !config.expected.test(value)) {
issues.push({
header,
current: value || 'not set',
severity: config.severity,
message: config.message,
});
}
}
return issues;
}7. OWASP Top 10 Checks
typescript
// SQL Injection Prevention
async function checkSQLInjection() {
const issues = [];
const files = await glob('**/*.{ts,tsx,js,jsx}');
for (const file of files) {
const content = await fs.readFile(file, 'utf-8');
// Check for raw SQL queries
if (content.includes('.sql`') || content.includes('raw(')) {
const lines = content.split('\n');
lines.forEach((line, index) => {
if (line.includes('${') && (line.includes('.sql`') || line.includes('raw('))) {
issues.push({
file,
line: index + 1,
severity: 'critical',
issue: 'Potential SQL injection via string interpolation',
code: line.trim(),
});
}
});
}
}
return issues;
}
// XSS Prevention
async function checkXSSVulnerabilities() {
const issues = [];
const files = await glob('**/*.{tsx,jsx}');
for (const file of files) {
const content = await fs.readFile(file, 'utf-8');
// Check for dangerouslySetInnerHTML
if (content.includes('dangerouslySetInnerHTML')) {
issues.push({
file,
severity: 'high',
issue: 'Use of dangerouslySetInnerHTML detected',
recommendation: 'Ensure content is properly sanitized',
});
}
// Check for user input in URLs
const urlPattern = /href=\{[^}]*user[^}]*\}/g;
if (urlPattern.test(content)) {
issues.push({
file,
severity: 'medium',
issue: 'User input in URL detected',
recommendation: 'Validate and sanitize URLs',
});
}
}
return issues;
}8. Security Report Generation
typescript
// Generate comprehensive report
export async function generateSecurityReport() {
console.log('🔒 Starting Security Audit...\n');
const report = {
timestamp: new Date().toISOString(),
summary: {
critical: 0,
high: 0,
medium: 0,
low: 0,
},
findings: {},
};
// Run all checks
const checks = [
{ name: 'Authentication', fn: auditAuthentication },
{ name: 'Authorization', fn: auditAuthorization },
{ name: 'Database Security', fn: auditDatabase },
{ name: 'Dependencies', fn: auditDependencies },
{ name: 'Secrets', fn: scanForSecrets },
{ name: 'Headers', fn: auditSecurityHeaders },
{ name: 'OWASP', fn: auditOWASP },
];
for (const check of checks) {
console.log(`Checking ${check.name}...`);
const results = await check.fn();
report.findings[check.name] = results;
// Update summary
for (const issue of results) {
report.summary[issue.severity]++;
}
}
// Generate HTML report
const html = generateHTMLReport(report);
await fs.writeFile('security-report.html', html);
// Generate JSON report
await fs.writeFile('security-report.json', JSON.stringify(report, null, 2));
console.log('\n📊 Security Audit Complete!');
console.log(`Critical: ${report.summary.critical}`);
console.log(`High: ${report.summary.high}`);
console.log(`Medium: ${report.summary.medium}`);
console.log(`Low: ${report.summary.low}`);
console.log('\n📄 Reports generated: security-report.html, security-report.json');
return report;
}Automated Fixes
The command can automatically fix certain issues:
typescript
// Auto-fix security issues
export async function autoFixSecurityIssues() {
console.log('🔧 Applying automatic security fixes...\n');
// Fix missing security headers
await updateMiddleware();
// Update vulnerable dependencies
await execAsync('npm audit fix');
// Add missing RLS policies
await applyDefaultRLSPolicies();
// Update environment example
await updateEnvExample();
console.log('✅ Automatic fixes applied');
}License Requirement
Important: This command requires a commercial MakerKit license from https://makerkit.dev?atp=MqaGgc MakerKit is a premium SaaS starter kit and requires proper licensing for commercial use.
