moai-security-owasp
About
This enterprise security skill provides production-ready defense patterns against OWASP Top 10 2021 vulnerabilities. It offers protection against SQL injection, XSS, CSRF attacks and implements secure access control, input validation, and security headers. Use this skill when building web applications that require enterprise-grade security measures against common web vulnerabilities.
Quick Install
Claude Code
Recommended/plugin add https://github.com/modu-ai/moai-adkgit clone https://github.com/modu-ai/moai-adk.git ~/.claude/skills/moai-security-owaspCopy and paste this command in Claude Code to install this skill
Documentation
moai-security-owasp: OWASP Top 10 2021 Defense Patterns
Complete Protection Against OWASP Top 10 2021 Vulnerabilities
Trust Score: 9.8/10 | Version: 4.0.0 | Enterprise Mode | Last Updated: 2025-11-12
Overview
The OWASP Top 10 2021 represents the most critical web application security risks. This Skill provides production-ready defense patterns for all 10 categories with code examples and validation strategies.
When to use this Skill:
- Protecting against SQL injection, XSS, and CSRF attacks
- Implementing secure access control (BOLA/IDOR prevention)
- Validating and sanitizing user input
- Implementing security headers and CSP
- Building secure file upload handling
- Protecting against XXE and deserialization attacks
- Implementing cryptographic security
- Building secure authentication systems
- Preventing sensitive data exposure
- Implementing logging and monitoring
Level 1: OWASP Top 10 2021 Overview
Rankings & Changes
| Rank | 2021 Category | Focus | OWASP A# |
|---|---|---|---|
| 1 | Broken Access Control | BOLA, IDOR, BFLA | A01 |
| 2 | Cryptographic Failures | Weak encryption, hardcoded keys | A02 |
| 3 | Injection | SQL, OS, NoSQL, LDAP | A03 |
| 4 | Insecure Design | Missing threat modeling | A04 |
| 5 | Security Misconfiguration | Default creds, verbose errors | A05 |
| 6 | Vulnerable Components | Outdated dependencies | A06 |
| 7 | Authentication Failures | Weak MFA, session flaws | A07 |
| 8 | Data Integrity Failures | Insecure deserialization | A08 |
| 9 | Logging & Monitoring Failures | Missing audit trails | A09 |
| 10 | SSRF | Server-side request forgery | A10 |
Key Changes from 2017 to 2021
2017 → 2021:
- XSS merged into Injection (A03)
- Broken Access Control elevated to #1
- Insecure Deserialization → Data Integrity Failures
- XXE moved to Injection
- Using Components with Known Vulns → Vulnerable Components
- Insufficient Logging → Logging & Monitoring
- SSRF added to Top 10
Level 2: Defense Patterns for Each Category
A01: Broken Access Control (BOLA & IDOR)
BOLA (Broken Object Level Authorization):
// VULNERABLE: No object ownership check
app.get('/api/users/:userId', jwtAuth, (req, res) => {
const user = db.users.findById(req.params.userId);
res.json(user); // Attacker can access any user!
});
// SECURE: Verify ownership
app.get('/api/users/:userId', jwtAuth, (req, res) => {
const user = db.users.findById(req.params.userId);
// Check: User can only access their own data (or admin)
if (req.user.id !== user.id && req.user.role !== 'admin') {
return res.status(403).json({ error: 'Forbidden' });
}
res.json(user);
});
// Multi-tenant: Always check tenant_id
app.get('/api/users/:userId', jwtAuth, (req, res) => {
const user = db.users.findById(req.params.userId);
// CRITICAL: Verify tenant ownership
if (user.tenant_id !== req.tenantId) {
return res.status(403).json({ error: 'Forbidden' });
}
res.json(user);
});
BFLA (Broken Function Level Authorization):
// VULNERABLE: No role check
app.post('/api/users/:userId/admin', jwtAuth, (req, res) => {
const user = db.users.findById(req.params.userId);
user.role = 'admin'; // Any user can become admin!
db.users.update(user);
res.json(user);
});
// SECURE: Verify admin role
app.post('/api/users/:userId/promote', jwtAuth, (req, res) => {
if (req.user.role !== 'admin') {
return res.status(403).json({ error: 'Forbidden' });
}
const user = db.users.findById(req.params.userId);
user.role = 'admin';
db.users.update(user);
res.json(user);
});
A03: Injection (SQL, NoSQL, OS)
SQL Injection Prevention:
// VULNERABLE: String concatenation
const userId = req.query.userId;
const query = `SELECT * FROM users WHERE id = ${userId}`;
// Attack: userId = "1 OR 1=1" returns all users
db.query(query);
// SECURE: Parameterized queries
const query = 'SELECT * FROM users WHERE id = ?';
db.query(query, [userId]); // userId treated as value, not code
// SECURE: With ORM (Sequelize)
const user = await User.findByPk(userId);
// SECURE: With TypeORM
const user = await userRepository.createQueryBuilder()
.where('user.id = :id', { id: userId })
.getOne();
NoSQL Injection:
// VULNERABLE: Direct query construction
const query = { username: req.body.username };
const user = await db.collection('users').findOne(query);
// Attack: username = { $ne: '' } bypasses auth
// SECURE: Validation + parameterized
const schema = z.object({
username: z.string().email()
});
const validated = schema.parse(req.body);
const user = await db.collection('users').findOne({
username: validated.username
});
A07: Authentication Failures
Secure Password Validation:
// Rate limiting for login attempts
const loginAttempts = new Map();
app.post('/login', async (req, res) => {
const key = req.body.email;
const attempts = loginAttempts.get(key) || 0;
if (attempts >= 5) {
return res.status(429).json({
error: 'Too many attempts. Try again in 15 minutes.'
});
}
const user = await db.users.findByEmail(req.body.email);
const passwordValid = user &&
await bcrypt.compare(req.body.password, user.passwordHash);
if (!passwordValid) {
loginAttempts.set(key, attempts + 1);
// Always return same error (prevents user enumeration)
return res.status(401).json({ error: 'Invalid credentials' });
}
loginAttempts.delete(key);
// Check MFA if enabled
if (user.mfaEnabled) {
// Send OTP or prompt for TOTP
return res.json({ requiresMfa: true });
}
res.json({ token: jwt.sign({ id: user.id }, process.env.JWT_SECRET) });
});
A05: Security Misconfiguration
HTTP Security Headers:
const helmet = require('helmet');
app.use(helmet({
// Content Security Policy
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://trusted-cdn.com"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'"],
fontSrc: ["'self'"],
objectSrc: ["'none'"],
mediaSrc: ["'self'"],
frameSrc: ["'none'"]
}
},
// HSTS: Force HTTPS
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
},
// Prevent clickjacking
frameguard: { action: 'deny' },
// Prevent MIME sniffing
noSniff: true,
// XSS Protection header
xssFilter: true,
// Referrer Policy
referrerPolicy: { policy: 'no-referrer' }
}));
// Disable server header
app.disable('x-powered-by');
Level 3: Advanced Input Validation
XSS Prevention (A03 Injection)
const { body, validationResult } = require('express-validator');
const sanitizeHtml = require('sanitize-html');
// 1. Input validation
const validateInput = [
body('comment')
.trim()
.isLength({ min: 1, max: 500 })
.escape() // Convert <, >, &, ", ' to entities
];
// 2. Sanitization (stronger than escape)
app.post('/comments', validateInput, (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors });
}
// Sanitize HTML
const sanitized = sanitizeHtml(req.body.comment, {
allowedTags: ['b', 'i', 'em', 'strong', 'p'],
allowedAttributes: {},
disallowedTagsMode: 'discard'
});
// Store sanitized version
db.comments.create({ content: sanitized });
res.json({ success: true });
});
// 3. Output encoding in templates (EJS/Handlebars)
// <%= comment %> auto-escapes HTML
// {{{ comment }}} does NOT escape (dangerous!)
CSRF Prevention
const csrf = require('csurf');
const cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use(csrf({ cookie: false }));
// GET: Return CSRF token
app.get('/form', (req, res) => {
res.json({ csrfToken: req.csrfToken() });
});
// POST: Validate CSRF token
app.post('/form', csrf(), (req, res) => {
// Token automatically verified by middleware
// If invalid, returns 403
res.json({ success: true });
});
// Alternative: SameSite cookie
res.cookie('session', token, {
sameSite: 'strict', // No cross-site requests
secure: true, // HTTPS only
httpOnly: true // No JavaScript access
});
XXE (XML External Entity) Prevention
const xml2js = require('xml2js');
// VULNERABLE: External entities enabled by default
const parser = new xml2js.Parser();
parser.parseString(xmlInput, (err, result) => {
// Entity expansion attack possible
});
// SECURE: Disable external entities
const parser = new xml2js.Parser({
strict: false,
normalize: true,
normalizeTags: true,
// Libxmljs doesn't support DTD disabling,
// use alternative parser or validate schema
});
// BETTER: Use JSON instead of XML
// If XML required: validate against schema
Reference
Official Resources
- OWASP Top 10 2021: https://owasp.org/Top10/
- OWASP Top 10 2017: https://owasp.org/www-project-top-ten-2017/
- CWE Top 25: https://cwe.mitre.org/top25/
- NIST SP 800-63: https://pages.nist.gov/800-63-3/
Tools & Libraries
- helmet (7.0.x): https://helmetjs.github.io/
- express-validator (7.0.x): https://express-validator.github.io/
- sanitize-html (2.11.x): https://github.com/apostrophecms/sanitize-html
- sql-bricks (Parameterized queries): https://github.com/dresende/sql-bricks
- OWASP Dependency Check: https://owasp.org/www-project-dependency-check/
Common Vulnerabilities
| Vulnerability | CWE | Prevention |
|---|---|---|
| SQL Injection | CWE-89 | Parameterized queries |
| XSS | CWE-79 | Input validation, output encoding |
| CSRF | CWE-352 | CSRF tokens, SameSite cookies |
| XXE | CWE-611 | Disable external entities |
| BOLA | CWE-639 | Check ownership on every request |
Version: 4.0.0 Enterprise
Skill Category: Security (Vulnerability Defense)
Complexity: Medium
Time to Implement: 2-4 hours per category
Prerequisites: Web security fundamentals, Express.js knowledge
GitHub Repository
Related Skills
sglang
MetaSGLang is a high-performance LLM serving framework that specializes in fast, structured generation for JSON, regex, and agentic workflows using its RadixAttention prefix caching. It delivers significantly faster inference, especially for tasks with repeated prefixes, making it ideal for complex, structured outputs and multi-turn conversations. Choose SGLang over alternatives like vLLM when you need constrained decoding or are building applications with extensive prefix sharing.
evaluating-llms-harness
TestingThis Claude Skill runs the lm-evaluation-harness to benchmark LLMs across 60+ standardized academic tasks like MMLU and GSM8K. It's designed for developers to compare model quality, track training progress, or report academic results. The tool supports various backends including HuggingFace and vLLM models.
llamaguard
OtherLlamaGuard is Meta's 7-8B parameter model for moderating LLM inputs and outputs across six safety categories like violence and hate speech. It offers 94-95% accuracy and can be deployed using vLLM, Hugging Face, or Amazon SageMaker. Use this skill to easily integrate content filtering and safety guardrails into your AI applications.
langchain
MetaLangChain is a framework for building LLM applications using agents, chains, and RAG pipelines. It supports multiple LLM providers, offers 500+ integrations, and includes features like tool calling and memory management. Use it for rapid prototyping and deploying production systems like chatbots, autonomous agents, and question-answering services.
