Skip to main content

Developer Kit

OWASP Top 10 Scanner

Scans code for OWASP Top 10 vulnerability patterns including injection, XSS, IDOR, and insecure deserialization with severity ratings and remediation snippets. Useful for pre-commit security checks and enterprise compliance. Backend and full-stack engineers shipping user-facing or API-facing code, security-conscious teams running AI-assisted development without a dedicated AppSec program, and indie builders preparing for SOC 2 or enterprise customer security reviews. OWASP Top 10 categories — injection flaws, broken access control, security misconfiguration, XSS, insecure deserialization, and friends — remain the most common real-world vulnerability classes, and AI-generated code is not immune. Without an integrated scanner that runs inside the coding session, findings surface late (in manual review or production) rather than before code lands.

Nexus CertifiedClaude CodeCodexOpenClaw
securityowaspvulnerabilitiescode-scanningcompliance

One-Time Purchase

$19.99

Sample Output

OWASP Top 10 Scan — src/api/users.ts


Scan Summary

| Metric | Value | |---|---| | Files Scanned | 1 (src/api/users.ts) | | Total Findings | 12 | | Critical | 2 | | High | 4 | | Medium | 4 | | Low | 2 | | OWASP Categories Represented | A01, A02, A03, A05, A07, A09 |

Coverage Note: This scan covers src/api/users.ts only (347 lines). Associated middleware, ORM configuration, authentication modules, and environment files were not scanned. Findings marked with ⚠️ may have mitigating controls elsewhere in the codebase that could not be verified.


Findings


FINDING-01

OWASP: A03:2021 — Injection Severity: 🔴 Critical Confidence: High Location: src/api/users.ts, line 84

// Line 83–86
const query = `SELECT * FROM users WHERE email = '${req.body.email}'`;
const result = await db.raw(query);

Description: User-supplied input from req.body.email is interpolated directly into a raw SQL string with no sanitization or parameterization. An attacker can terminate the string literal and inject arbitrary SQL, enabling data exfiltration, authentication bypass, or destructive operations.

Remediation: Replace string interpolation with a parameterized query:

const result = await db('users')
  .where({ email: req.body.email })
  .select('*');
// Or, using raw with binding:
const result = await db.raw(
  'SELECT * FROM users WHERE email = ?',
  [req.body.email]
);

FINDING-02

OWASP: A01:2021 — Broken Access Control Severity: 🔴 Critical Confidence: High Location: src/api/users.ts, line 142

// Line 140–145
const targetUser = await User.findById(req.params.userId);
return res.json(targetUser);

Description: The endpoint returns a user record identified by req.params.userId without verifying that the requesting user is authorized to access that record. There is no comparison against req.user.id or a role check, making this a textbook Insecure Direct Object Reference (IDOR). Any authenticated user can enumerate and retrieve any other user's profile.

Remediation: Enforce ownership or role-based authorization before returning the record:

if (req.user.id !== req.params.userId && req.user.role !== 'admin') {
  return res.status(403).json({ error: 'Forbidden' });
}
const targetUser = await User.findById(req.params.userId);
return res.json(targetUser);

FINDING-03

OWASP: A07:2021 — Identification and Authentication Failures Severity: 🟠 High Confidence: High Location: src/api/users.ts, line 211

// Line 209–213
const token = jwt.sign(
  { userId: user.id, role: user.role },
  process.env.JWT_SECRET,
  { algorithm: 'HS256' }
);

Description: No expiry (expiresIn) is set on the JWT. Tokens issued here are valid indefinitely, meaning a stolen or leaked token can never be invalidated through natural expiry. Combined with no token revocation mechanism visible in this file, credential theft has permanent effect.

Remediation:

const token = jwt.sign(
  { userId: user.id, role: user.role },
  process.env.JWT_SECRET,
  { algorithm: 'HS256', expiresIn: '15m' }
);
// Also issue a short-lived refresh token separately.

FINDING-04

OWASP: A03:2021 — Injection Severity: 🟠 High Confidence: High Location: src/api/users.ts, line 178

// Line 176–179
const filter = req.query.sortBy;
const users = await db.raw(`SELECT * FROM users ORDER BY ${filter}`);

Description: req.query.sortBy is injected into an ORDER BY clause without validation. Parameterized queries cannot bind column names, so this requires allowlist validation. An attacker can inject expressions such as (SELECT CASE WHEN ...) to perform blind SQL injection or cause denial-of-service via expensive sorts.

Remediation:

const ALLOWED_SORT_COLUMNS = ['name', 'email', 'created_at'];
const sortBy = ALLOWED_SORT_COLUMNS.includes(req.query.sortBy as string)
  ? req.query.sortBy
  : 'created_at';
const users = await db('users').orderBy(sortBy);

FINDING-05

OWASP: A05:2021 — Security Misconfiguration Severity: 🟠 High Confidence: High Location: src/api/users.ts, line 23

// Line 21–25
app.use(cors({ origin: '*' }));

Description: CORS is configured to allow all origins (*). For an authenticated API that issues JWT tokens and handles user data, a wildcard CORS policy enables cross-origin requests from any domain, undermining same-origin protections.

Remediation:

const allowedOrigins = (process.env.ALLOWED_ORIGINS ?? '').split(',');
app.use(cors({
  origin: (origin, callback) => {
    if (!origin || allowedOrigins.includes(origin)) callback(null, true);
    else callback(new Error('Not allowed by CORS'));
  },
  credentials: true,
}));

FINDING-06

OWASP: A02:2021 — Cryptographic Failures Severity: 🟠 High Confidence: High Location: src/api/users.ts, line 259

// Line 257–261
const hashedPassword = crypto
  .createHash('md5')
  .update(req.body.password)
  .digest('hex');

Description: MD5 is a cryptographically broken, fast-hashing algorithm unsuitable for password storage. It is trivially reversible via precomputed rainbow tables and can be brute-forced at billions of guesses per second on commodity hardware.

Remediation: Use a purpose-built password hashing algorithm with a work factor:

import bcrypt from 'bcrypt';
const hashedPassword = await bcrypt.hash(req.body.password, 12);
// On verification:
const match = await bcrypt.compare(req.body.password, storedHash);

FINDING-07

OWASP: A03:2021 — Injection (XSS via reflected output) Severity: 🟡 Medium Confidence: Medium Location: src/api/users.ts, line 302

// Line 300–304
return res.send(`<p>Welcome back, ${req.query.name}!</p>`);

Description: req.query.name is reflected into an HTML response without escaping. If the Content-Type is text/html (as res.send with a string sets by default), an attacker can craft a URL with a malicious name parameter to execute arbitrary JavaScript in the victim's browser.

Confidence note: Medium — whether this endpoint is reachable unauthenticated and whether downstream CSP headers mitigate this could not be determined from this file alone.

Remediation:

import escapeHtml from 'escape-html';
return res.send(`<p>Welcome back, ${escapeHtml(String(req.query.name))}!</p>`);
// Preferred: return JSON from API routes and render HTML client-side.

FINDING-08

OWASP: A09:2021 — Security Logging and Monitoring Failures Severity: 🟡 Medium Confidence: Medium Location: src/api/users.ts, line 127

// Line 125–130
} catch (err) {
  console.error(err);
  return res.status(500).json({ error: err.message });
}

Description: Raw error messages (including potential stack traces and internal details) are returned directly to the client in err.message. This leaks implementation details — database schema, file paths, or dependency versions — that aid an attacker in fingerprinting the system. Additionally, console.error is not a structured logging mechanism; authentication failures and errors are not auditable.

Remediation:

} catch (err) {
  logger.error({ err, userId: req.user?.id, path: req.path }, 'Request error');
  return res.status(500).json({ error: 'An internal error occurred.' });
}

FINDING-09

OWASP: A01:2021 — Broken Access Control Severity: 🟡 Medium Confidence: Medium Location: src/api/users.ts, line 195

// Line 193–197
if (req.body.role) {
  user.role = req.body.role;
}
await user.save();

Description: The user update handler allows the caller to set their own role field from the request body. If an authenticated non-admin user hits this endpoint, they could escalate their own privileges to admin. This is a Mass Assignment vulnerability.

Confidence note: Medium — whether an upstream middleware strips role from the body before this point could not be determined from this file.

Remediation:

// Explicitly allowlist updatable fields
const { displayName, avatarUrl } = req.body;
Object.assign(user, { displayName, avatarUrl });
await user.save();
// Role changes should be a separate admin-only endpoint.

FINDING-10

OWASP: A07:2021 — Identification and Authentication Failures Severity: 🟡 Medium Confidence: High Location: src/api/users.ts, line 68

// Line 66–70
const user = await User.findOne({ email: req.body.email });
if (!user || user.password !== req.body.password) {
  return res.status(401).json({ error: 'Invalid credentials' });
}

Description: Passwords are compared with strict equality (!==), implying they are stored and compared in plaintext (or a non-bcrypt format that lacks constant-time comparison). Plaintext storage is a critical data exposure risk. Even if hashed, non-constant-time comparison enables timing attacks.

Remediation:

const user = await User.findOne({ email: req.body.email });
if (!user || !(await bcrypt.compare(req.body.password, user.passwordHash))) {
  return res.status(401).json({ error: 'Invalid credentials' });
}

FINDING-11

OWASP: A05:2021 — Security Misconfiguration Severity: 🔵 Low Confidence: Low Location: src/api/users.ts, line 14

// Line 12–16
app.use(express.json({ limit: '50mb' }));

Description: The JSON body size limit is set to 50 MB. While not a standalone vulnerability, an oversized limit increases exposure to denial-of-service via large payload attacks, particularly if this endpoint is publicly reachable.

Confidence note: Low — whether rate limiting or a reverse proxy caps request sizes upstream is unknown from this file.

Remediation: Set a conservative limit appropriate for the payload size this endpoint actually requires (typically 100kb1mb for user profile APIs):

app.use(express.json({ limit: '1mb' }));

FINDING-12

OWASP: A09:2021 — Security Logging and Monitoring Failures Severity: 🔵 Low Confidence: Low Location: src/api/users.ts, line 75

// Line 73–76
console.log(`Login attempt for: ${req.body.email}`);

Description: Login attempts are logged to stdout via console.log rather than a structured logging system. Audit trails for authentication events are typically required for compliance (SOC 2, PCI-DSS) and incident response. console.log output is ephemeral and unsearchable in most production environments.

Remediation:

logger.info({
  event: 'auth.login_attempt',
  email: req.body.email,
  ip: req.ip,
  timestamp: new Date().toISOString(),
}, 'Login attempt');

Top-3 Priority Recommendations

Findings exceed 10. The following three issues represent the highest combined severity and exploitability and should be addressed before any others.

  1. Remediate SQL injection immediately (FINDING-01, FINDING-04). Both raw-query injections are directly exploitable with no prerequisites. Migrate to parameterized queries and column allowlists before this code reaches production.

  2. Replace MD5 password hashing and plaintext comparison (FINDING-06, FINDING-10). Password storage and comparison are broken at a foundational level. Migrate to bcrypt with a work factor of ≥12, and run a forced password reset for any users whose credentials were stored under the current scheme.

  3. Enforce authorization on the user-lookup endpoint (FINDING-02). The IDOR vulnerability on line 142 allows any authenticated user to read any other user's full record. Add an ownership/role check as the first operation in that handler.


Suggested PR Reviewer Checklist

The following items should be verified by a reviewer before approving this file:

  • [ ] All database queries use parameterized inputs or ORM methods — no string interpolation in raw SQL
  • [ ] Every endpoint that accepts a resource ID verifies the requesting user is authorized to access that resource
  • [ ] JWT tokens have an expiresIn value set; no indefinitely-valid tokens are issued
  • [ ] Passwords are hashed with bcrypt (or argon2) — no crypto.createHash, md5, sha1, or sha256 used for credential storage
  • [ ] CORS origin is restricted to an explicit allowlist; wildcard * is not present on authenticated routes
  • [ ] Error responses return generic messages to clients; full error details go to the structured logger only
  • [ ] Request body fields are explicitly allowlisted before assignment to model objects (no mass assignment)
  • [ ] All authentication events (attempts, failures, password changes) are emitted to the structured logger with IP, timestamp, and user identifier

Scan performed via static pattern analysis only. No code was executed. Findings reflect patterns visible in src/api/users.ts (347 lines) exclusively — associated modules, middleware, environment configuration, and database layer were not analyzed and may contain additional vulnerabilities or mitigating controls not reflected above.

View full sample →

All sales final. No refunds on digital products.

Includes support for Claude Code, Codex, and OpenClaw in the same license.

What You Get With This Skill

Scans code for OWASP Top 10 vulnerability patterns including injection, XSS, IDOR, and insecure deserialization with severity ratings and remediation snippets. Useful for pre-commit security checks and enterprise compliance.

All ClearPoint Nexus Skills Include

  • Production-ready workflow packaging for three supported platforms.
  • Reusable structure designed for repeatable operator tasks.
  • Clear deliverable format, not just raw prompt output.

Related Skills

Developer Kit
Featured
Code Generation
Generates, reviews, debugs, and executes code in sandboxed workflows. Useful for implementation, refactoring, and technical problem solving.
Claude CodeCodexOpenClaw
codingdebuggingcode-review

$19.99

One-time license

View Skill
Developer Kit
API Documentation Generator
Generates structured, developer-ready API documentation from code, OpenAPI specs, route definitions, or descriptions. Produces reference docs, quickstart guides, error references, and code examples.
Claude CodeCodexOpenClaw
apidocumentationdeveloper-experience

$19.99

One-time license

View Skill
Developer Kit
Intelligent PR Composer
Generates pull request descriptions that capture context, alternatives considered, test plan, risk areas, and reviewer guidance beyond a simple diff summary. Useful for teams that want senior-quality PRs without manual authoring.
Claude CodeCodexOpenClaw
pull-requestscode-reviewgit

$19.99

One-time license

View Skill