Claude Code Plugins

Community-maintained marketplace

Feedback

security-first

@j0KZ/mcp-agents
0
0

Universal security checklist and fixes for ANY project type or language

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name security-first
description Universal security checklist and fixes for ANY project type or language

Security First - Shield Your Code

🎯 When to Use This Skill

Use BEFORE:

  • Deploying to production
  • Handling sensitive data
  • Opening API endpoints
  • Processing user input
  • Storing passwords
  • Accepting file uploads
  • Going live with payments

⚡ 5-Minute Security Audit

WITH MCP (Security Scanner):

"Run complete security audit on my codebase"
"Find and fix all OWASP Top 10 vulnerabilities"

WITHOUT MCP - Quick Scan:

# 1. Find hardcoded secrets (CRITICAL!)
grep -r "password\|secret\|token\|api[_-]key" --include="*.js" --include="*.env" | grep -v ".example"

# 2. Check for SQL injection
grep -r "query.*\+\|query.*\$\{" --include="*.js"

# 3. Find eval/exec usage
grep -r "eval(\|exec(\|Function(" --include="*.js"

# 4. Check dependencies
npm audit  # or pip check, bundle audit

# 5. Find unvalidated input
grep -r "req.body\|req.query\|req.params" --include="*.js" | grep -v "validate\|sanitize"

🛡️ OWASP Top 10 Checklist (2024)

1. Injection (SQL, NoSQL, Command) 💉

Vulnerable Code:

// ❌ NEVER DO THIS
const query = `SELECT * FROM users WHERE id = ${req.params.id}`;
db.query(query);  // SQL Injection!

// ❌ Command injection
exec(`ping ${userInput}`);  // Dangerous!

Secure Code:

// ✅ Parameterized queries
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [req.params.id]);

// ✅ For MongoDB
User.findOne({ _id: sanitize(req.params.id) });

// ✅ Command execution
const { spawn } = require('child_process');
spawn('ping', [userInput], { shell: false });

2. Broken Authentication 🔐

Security Checklist:

// ✅ Strong password requirements
function validatePassword(password) {
  const requirements = {
    minLength: 12,
    hasUpperCase: /[A-Z]/.test(password),
    hasLowerCase: /[a-z]/.test(password),
    hasNumbers: /\d/.test(password),
    hasSpecialChar: /[!@#$%^&*]/.test(password),
    notCommon: !commonPasswords.includes(password)
  };

  return Object.values(requirements).every(req => req);
}

// ✅ Secure session management
app.use(session({
  secret: process.env.SESSION_SECRET,  // From environment
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: true,      // HTTPS only
    httpOnly: true,    // No JS access
    maxAge: 3600000,   // 1 hour
    sameSite: 'strict' // CSRF protection
  }
}));

// ✅ Rate limiting
const rateLimit = require('express-rate-limit');
const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,  // 15 minutes
  max: 5,  // 5 attempts
  message: 'Too many login attempts'
});
app.post('/login', loginLimiter, loginHandler);

3. Sensitive Data Exposure 🔒

Never Store in Code:

// ❌ WRONG
const API_KEY = "sk_live_abcd1234";
const DB_PASSWORD = "admin123";

// ✅ CORRECT - Use environment variables
const API_KEY = process.env.API_KEY;
const DB_PASSWORD = process.env.DB_PASSWORD;

// ✅ Use .env file (never commit!)
require('dotenv').config();

// ✅ Encrypt sensitive data at rest
const crypto = require('crypto');
const algorithm = 'aes-256-gcm';

function encrypt(text) {
  const key = Buffer.from(process.env.ENCRYPTION_KEY, 'hex');
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv(algorithm, key, iv);

  let encrypted = cipher.update(text, 'utf8', 'hex');
  encrypted += cipher.final('hex');

  const authTag = cipher.getAuthTag();

  return {
    encrypted,
    iv: iv.toString('hex'),
    authTag: authTag.toString('hex')
  };
}

4. XML External Entities (XXE) 📄

// ❌ Vulnerable XML parsing
const libxmljs = require('libxmljs');
const doc = libxmljs.parseXml(userInput);  // XXE vulnerable!

// ✅ Safe XML parsing
const parser = new DOMParser();
const doc = parser.parseFromString(userInput, 'text/xml');

// ✅ Or disable external entities
const options = {
  xmlMode: true,
  recognizeSelfClosing: true,
  decodeEntities: false  // Disable entity expansion
};

5. Broken Access Control 🚪

// ❌ No authorization check
app.get('/api/user/:id', (req, res) => {
  const user = User.findById(req.params.id);
  res.json(user);  // Anyone can see any user!
});

// ✅ Proper authorization
app.get('/api/user/:id', authenticate, (req, res) => {
  // Check if user can access this resource
  if (req.user.id !== req.params.id && !req.user.isAdmin) {
    return res.status(403).json({ error: 'Forbidden' });
  }

  const user = User.findById(req.params.id);
  res.json(user);
});

// ✅ Role-based access control (RBAC)
const authorize = (roles) => {
  return (req, res, next) => {
    if (!roles.includes(req.user.role)) {
      return res.status(403).json({ error: 'Insufficient permissions' });
    }
    next();
  };
};

app.delete('/api/users/:id', authenticate, authorize(['admin']), deleteUser);

6. Security Misconfiguration ⚙️

# ✅ Security headers
app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      styleSrc: ["'self'", "'unsafe-inline'"],
      scriptSrc: ["'self'"],
      imgSrc: ["'self'", "data:", "https:"],
    },
  },
  hsts: {
    maxAge: 31536000,
    includeSubDomains: true,
    preload: true
  }
}));

# ✅ Disable unnecessary features
app.disable('x-powered-by');  # Hide Express

# ✅ Error handling (don't leak info)
app.use((err, req, res, next) => {
  console.error(err.stack);  // Log full error

  // Send generic message to client
  res.status(500).json({
    error: 'Internal server error',
    // Don't send: err.stack or err.message
  });
});

7. Cross-Site Scripting (XSS) 🎭

// ❌ Vulnerable to XSS
app.get('/search', (req, res) => {
  res.send(`Results for: ${req.query.q}`);  // XSS!
});

// ✅ Sanitize output
const DOMPurify = require('isomorphic-dompurify');

app.get('/search', (req, res) => {
  const clean = DOMPurify.sanitize(req.query.q);
  res.send(`Results for: ${clean}`);
});

// ✅ React automatically escapes
<div>{userInput}</div>  // Safe

// ❌ But dangerouslySetInnerHTML is dangerous
<div dangerouslySetInnerHTML={{__html: userInput}} />  // XSS!

// ✅ Content-Type headers
res.set('Content-Type', 'text/plain');  // Not HTML
res.set('X-Content-Type-Options', 'nosniff');

8. Insecure Deserialization 📦

// ❌ Dangerous deserialization
const userData = JSON.parse(req.body.data);
eval(userData.code);  // Code execution!

// ✅ Validate before deserializing
const schema = Joi.object({
  name: Joi.string().required(),
  age: Joi.number().min(0).max(120)
});

const { error, value } = schema.validate(JSON.parse(req.body.data));
if (error) return res.status(400).json({ error });

// ✅ Never deserialize untrusted data into code
// Use JSON.parse() only, never eval() or Function()

9. Components with Known Vulnerabilities 📚

# ✅ Regular dependency checks
# Add to package.json
{
  "scripts": {
    "security": "npm audit && npm outdated",
    "security:fix": "npm audit fix",
    "preinstall": "npm audit"
  }
}

# ✅ Automated updates (GitHub)
# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "daily"
    open-pull-requests-limit: 10

10. Insufficient Logging & Monitoring 📊

// ✅ Comprehensive logging
const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' }),
  ],
});

// ✅ Log security events
function logSecurityEvent(event, user, details) {
  logger.warn({
    type: 'SECURITY',
    event,
    user: user?.id,
    ip: user?.ip,
    timestamp: new Date().toISOString(),
    details
  });
}

// Usage
logSecurityEvent('FAILED_LOGIN', req.user, {
  attempts: failedAttempts,
  ip: req.ip
});

logSecurityEvent('UNAUTHORIZED_ACCESS', req.user, {
  resource: req.path,
  method: req.method
});

🔐 Password Security

// ✅ NEVER store plain text passwords!
const bcrypt = require('bcrypt');

// Hashing
async function hashPassword(password) {
  const saltRounds = 12;  // Higher = more secure but slower
  return await bcrypt.hash(password, saltRounds);
}

// Verifying
async function verifyPassword(password, hash) {
  return await bcrypt.compare(password, hash);
}

// ✅ Password reset flow
async function resetPassword(email) {
  // 1. Generate secure token
  const token = crypto.randomBytes(32).toString('hex');

  // 2. Store hashed token with expiry
  await storeResetToken(email, hashToken(token), Date.now() + 3600000);

  // 3. Send unhashed token via email
  await sendEmail(email, `Reset link: ${BASE_URL}/reset?token=${token}`);
}

🚪 API Security

// ✅ API Security Checklist
const apiSecurity = {
  // 1. Authentication
  authentication: 'Bearer token (JWT)',

  // 2. Rate limiting
  rateLimit: {
    windowMs: 15 * 60 * 1000,  // 15 minutes
    max: 100  // requests per window
  },

  // 3. Input validation
  validateInput: (data, schema) => {
    return Joi.validate(data, schema);
  },

  // 4. CORS configuration
  cors: {
    origin: process.env.ALLOWED_ORIGINS?.split(',') || false,
    credentials: true
  },

  // 5. API versioning
  versioning: '/api/v1/',

  // 6. Request size limit
  bodyLimit: '10mb',

  // 7. Timeout
  timeout: 30000,  // 30 seconds

  // 8. HTTPS only
  httpsOnly: true
};

📋 Security Deployment Checklist

## Pre-Deployment Security Checklist

### Code Security
- [ ] No hardcoded secrets
- [ ] All inputs validated
- [ ] SQL queries parameterized
- [ ] XSS protection enabled
- [ ] CSRF tokens implemented
- [ ] Authentication required
- [ ] Authorization checks present
- [ ] Rate limiting configured

### Dependencies
- [ ] `npm audit` shows 0 vulnerabilities
- [ ] All packages from trusted sources
- [ ] Lock file committed
- [ ] Licenses reviewed

### Configuration
- [ ] Environment variables used
- [ ] HTTPS enforced
- [ ] Security headers set
- [ ] CORS configured
- [ ] Error messages sanitized
- [ ] Debug mode disabled
- [ ] Source maps disabled in production

### Data Protection
- [ ] Passwords hashed (bcrypt)
- [ ] Sensitive data encrypted
- [ ] PII fields marked
- [ ] Data retention policy set
- [ ] Backups encrypted

### Infrastructure
- [ ] Firewall rules configured
- [ ] Ports minimized
- [ ] SSH keys only (no passwords)
- [ ] Monitoring enabled
- [ ] Logging configured
- [ ] Incident response plan ready

🚨 Incident Response Plan

// security-incident.js
class SecurityIncident {
  async respond(incident) {
    // 1. Detect
    this.log('INCIDENT_DETECTED', incident);

    // 2. Contain
    await this.blockIP(incident.sourceIP);
    await this.disableAccount(incident.userId);

    // 3. Investigate
    const logs = await this.gatherLogs(incident);

    // 4. Remediate
    await this.patchVulnerability(incident.vulnerability);

    // 5. Recover
    await this.restoreService();

    // 6. Lessons Learned
    await this.documentIncident(incident);

    // 7. Notify
    await this.notifyStakeholders(incident);
  }
}

💡 Security Quick Wins

# 1. Add security.txt
echo "Contact: security@example.com" > public/.well-known/security.txt

# 2. Enable Dependabot
gh api repos/:owner/:repo --method PUT --field security_and_analysis[secret_scanning][status]=enabled

# 3. Add pre-commit hooks
npm install --save-dev husky
npx husky add .husky/pre-commit "npm audit"

# 4. Security headers test
curl -I https://yoursite.com | grep -i "strict-transport\|content-security\|x-frame"

Remember: Security is not a feature, it's a requirement! 🛡️