Skip to main content

Overview

ZenVeil maps every finding to the OWASP Top 10 (2021 edition). Here are real examples from the patterns ZenVeil detects — code snippets commonly generated by AI assistants or found in open-source projects.

A01:2021 — Broken Access Control

Missing authorization middleware

// Flagged pattern
router.get('/api/admin/users', async (req, res) => {
  const users = await User.find({});
  return res.json(users);
});
ZG-XXXX  HIGH  secrets  Potential missing authorization middleware
Location: src/routes/admin.js:12
Fix:
router.get('/api/admin/users', requireAuth, requireAdmin, async (req, res) => {
  const users = await User.find({});
  return res.json(users);
});

IDOR — Object access without ownership check

// Flagged pattern
router.get('/api/orders/:orderId', async (req, res) => {
  const order = await Order.findById(req.params.orderId); // No ownership check
  return res.json(order);
});
ZG-XXXX  MEDIUM  secrets  Potential broken object ownership check
Location: src/routes/orders.js:8
Fix:
router.get('/api/orders/:orderId', requireAuth, async (req, res) => {
  const order = await Order.findOne({
    _id: req.params.orderId,
    userId: req.user.id, // Scope by authenticated user
  });
  if (!order) return res.status(404).json({ error: 'Not found' });
  return res.json(order);
});

A02:2021 — Cryptographic Failures

Predictable JWT secret

// Flagged pattern — CRITICAL
const token = jwt.sign({ userId }, 'changeme', { expiresIn: '365d' });
ZG-XXXX  CRITICAL  secrets  Inline predictable JWT signing secret
ZG-XXXX  HIGH      secrets  Long-lived session token
Fix:
const secret = process.env.JWT_SECRET; // Min 64 random bytes
if (!secret || secret.length < 32) throw new Error('JWT_SECRET not configured');

const token = jwt.sign({ userId }, secret, { expiresIn: '1h' });

Weak password hashing

// Flagged pattern
const hash = md5(password); // MD5 is not a password hash
ZG-XXXX  HIGH  secrets  Weak password hashing
Location: src/auth/register.js:14
Fix:
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12); // Cost factor 12+

A05:2021 — Security Misconfiguration

Debug mode in production

// Flagged pattern
const app = express();
app.set('debug', true);     // Exposes stack traces
// or
// NODE_ENV=development in production config
ZG-XXXX  MEDIUM  secrets  Debug mode enabled
Location: src/app.js:3
Fix:
// Use environment-based config
if (process.env.NODE_ENV !== 'production') {
  app.set('debug', true);
}

// In production: NODE_ENV=production

Running as root in Docker

# Flagged pattern
FROM node:18
USER root  # CRITICAL: never run as root
RUN npm install
ZG-XXXX  HIGH  secrets  Application configured to run as root
Location: Dockerfile:3
Fix:
FROM node:18-slim

# Create and use a non-root user
RUN groupadd -r appuser && useradd -r -g appuser appuser
WORKDIR /app
COPY --chown=appuser:appuser . .
USER appuser

RUN npm install --only=production
CMD ["node", "server.js"]

A06:2021 — Vulnerable and Outdated Components

Missing lockfile

ZG-XXXX  HIGH  supply_chain  Missing lockfile
Location: package.json
Without a lockfile, npm install can silently install different (potentially compromised) versions. Fix:
npm install              # Creates package-lock.json
git add package-lock.json
git commit -m "Add npm lockfile for reproducible installs"

Known CVE in dependency

ZG-XXXX  HIGH  supply_chain  CVE-2021-23337 in lodash@4.17.20
CVSS Score: 7.2
Affected path: node_modules/lodash
Fix:
npm install lodash@4.17.21
# Or if lodash is a transitive dep:
npm audit fix

A07:2021 — Identification and Authentication Failures

Token in localStorage

// Flagged pattern
localStorage.setItem('auth_token', response.data.token);
ZG-XXXX  HIGH  secrets  Token stored in browser storage
Location: src/components/Login.jsx:47
Fix:
// Remove localStorage call
// Token is set by server as httpOnly cookie
// Server:
res.cookie('session', token, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
  maxAge: 3600000,
});

OWASP coverage summary

OWASP CategoryZenVeil Detection
A01: Broken Access ControlMissing auth middleware, IDOR patterns, client-side admin gates
A02: Cryptographic FailuresAWS/GitHub/Slack secrets, JWT weaknesses, MD5/SHA1 passwords, tokens in localStorage
A03: Injection(Planned)
A04: Insecure DesignOpen redirects, long-lived sessions, client-only logout
A05: Security MisconfigurationDebug mode, running as root, missing security headers, public DB, missing .env in .gitignore
A06: Vulnerable ComponentsMissing lockfiles, floating versions, CVEs via OSV.dev
A07: Auth FailuresToken storage, predictable JWT secrets, long-lived tokens
A08: Software & Data IntegrityDependency confusion, floating npm versions, unpinned CI actions
A09: Logging Failures(Planned)
A10: SSRFBlocked in API scanner (private IPs rejected)