Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Description: Attackers inject properties into Object.prototype via __proto__, constructor.prototype, or recursive merge functions, poisoning every object in the runtime.
Dangerous Functions / Patterns:
obj[key] = value where key is user-controlled
Recursive deepMerge, _.merge, _.defaultsDeep with untrusted input
JSON.parse() of untrusted input followed by object spread or merge
Direct access to __proto__ or constructor.prototype
Safe Alternative:
Use Object.create(null) for lookup maps
Validate keys against a denylist: __proto__, constructor, prototype
Use Map instead of plain objects for user-keyed data
Freeze prototypes with Object.freeze(Object.prototype) in sensitive contexts
Description: Dynamic code execution functions compile and run arbitrary strings, enabling full remote code execution when input is attacker-controlled.
Dangerous Functions / Patterns:
eval(userInput)
new Function('return ' + userInput)()
setTimeout(userInput, 1000) and setInterval(userInput, 1000) with string arguments
Template literal interpolation into eval
Safe Alternative:
Use JSON.parse() for data deserialization
Use a sandboxed expression parser (e.g., expr-eval, mathjs with sandbox)
Always pass function references to setTimeout/setInterval, never strings
Use a strict CSP with script-src that blocks unsafe-eval
Vulnerable Code:
// User-supplied math expression
app.post('/calc', (req, res) => {
const result = eval(req.body.expression); // RCE
res.json({ result });
});
Safe Code:
import { Parser } from 'expr-eval';
const parser = new Parser();
app.post('/calc', (req, res) => {
try {
const expr = parser.parse(req.body.expression);
const result = expr.evaluate({});
res.json({ result });
} catch {
res.status(400).json({ error: 'Invalid expression' });
}
});
3. DOM-Based XSS
Description: Client-side JavaScript writes unsanitized user input directly into the DOM, enabling script injection without server involvement.
Description: Node.js vm module does not provide a security boundary. Attackers can escape the sandbox via prototype chain traversal to access the host process object and execute arbitrary code.
Dangerous Functions / Patterns:
vm.runInNewContext(userCode)
vm.createContext() with host object leakage
vm.Script executing untrusted code
Any use of vm or vm2 for security sandboxing (vm2 has known escapes)
Safe Alternative:
Use isolated-vm for true V8 isolate sandboxing
Use Web Workers with restricted permissions
Use Deno with --allow-* permission flags
Use Cloudflare Workers or other process-isolated runtimes
Never rely on vm or vm2 for untrusted code execution
Vulnerable Code:
import vm from 'vm';
const sandbox = { result: null };
vm.createContext(sandbox);
vm.runInNewContext(userCode, sandbox);
// Escape: this.constructor.constructor('return process')().exit()
Description: Dynamic require() or import() with user-controlled paths allows loading arbitrary modules from disk or node_modules, potentially executing malicious code.
Dangerous Functions / Patterns:
require(userInput)
import(userInput)
require('./plugins/' + pluginName) without validation
require.resolve(userInput) for path probing
Safe Alternative:
Use a static allowlist of permitted modules
Validate module names against a strict pattern (alphanumeric only)
Use a plugin registry pattern with pre-registered handlers
Description: Malicious packages can enter the dependency tree via typosquatting, compromised maintainer accounts, postinstall scripts, or lockfile manipulation.
Dangerous Functions / Patterns:
Installing packages with similar names to popular ones (e.g., lodahs vs lodash)
"postinstall", "preinstall", "prepare" scripts in dependencies
Missing or modified package-lock.json / pnpm-lock.yaml
"dependencies" including packages that should be "devDependencies"
Unpinned dependency versions (*, >=, or overly broad ranges)
Lockfile entries with unexpected resolved URLs or integrity hashes
Safe Alternative:
Use npm audit and pnpm audit regularly
Enable --ignore-scripts during CI installs, run scripts explicitly
Pin exact versions or use lockfiles committed to source control
Use Socket.dev, Snyk, or similar SCA tools
Review new dependencies before adding them
Use npm config set ignore-scripts true as a default
Description: Storing JWTs in localStorage or sessionStorage exposes them to XSS theft. Storing secrets or sensitive claims in JWT payload exposes them to any holder since JWTs are base64-encoded, not encrypted.
Dangerous Functions / Patterns:
localStorage.setItem('token', jwt)
sessionStorage.setItem('token', jwt)
JWTs in URL parameters or query strings
Storing sensitive data (roles, PII) in JWT payload without encryption
Using alg: 'none' or allowing algorithm switching
Not validating iss, aud, exp claims
Safe Alternative:
Store JWTs in httpOnly, secure, sameSite cookies
Use short-lived access tokens with refresh token rotation
Validate all claims server-side (iss, aud, exp, nbf)
Pin the expected algorithm server-side
Use opaque tokens with server-side session lookup for sensitive contexts
Vulnerable Code:
// Client
const response = await fetch('/api/login', { method: 'POST', body });
const { token } = await response.json();
localStorage.setItem('authToken', token); // Accessible to any XSS payload
// Server
const token = jwt.sign(payload, secret); // No algorithm pinning
const decoded = jwt.verify(req.headers.authorization, secret);
// Algorithm confusion possible
10. TypeScript as any and @ts-ignore Security Bypass
Description: TypeScript type safety annotations that suppress errors (as any, @ts-ignore, @ts-expect-error, non-null assertions !) can mask security-critical type mismatches, allowing unsafe data to flow through the application unchecked.
Dangerous Functions / Patterns:
userInput as any to bypass validation types
// @ts-ignore above security-critical code
// @ts-expect-error to silence type errors in auth/authz logic
Non-null assertion user!.isAdmin without actual null check
as unknown as TargetType double assertion to force incompatible types
Disabling strict in tsconfig.json
Safe Alternative:
Use Zod, Valibot, or io-ts for runtime validation at boundaries
Enable strict: true in tsconfig.json
Use ESLint rules: @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion
Replace as any with proper type narrowing or type guards
Treat @ts-ignore in security-critical paths as high-severity findings
Vulnerable Code:
function processUser(input: unknown) {
// @ts-ignore
const user = input as any;
if (user.role === 'admin') { // No runtime validation
deleteAllRecords(); // Could be triggered by crafted input
}
}
Safe Code:
import { z } from 'zod';
const UserSchema = z.object({
id: z.string().uuid(),
role: z.enum(['user', 'moderator', 'admin']),
email: z.string().email(),
});
function processUser(input: unknown) {
const result = UserSchema.safeParse(input);
if (!result.success) {
throw new ValidationError(result.error);
}
const user = result.data; // Fully typed, runtime-validated
if (user.role === 'admin') {
deleteAllRecords();
}
}
11. React dangerouslySetInnerHTML and SSR Injection
Description: React's dangerouslySetInnerHTML bypasses built-in XSS protection. In SSR contexts, unsanitized user data rendered into HTML can execute on every visitor's browser.
Rendering user data into <script> tags for hydration
renderToString() with unsanitized props
href="javascript:..." in JSX (React does not block this in all versions)
Safe Alternative:
Use a sanitizer like DOMPurify before dangerouslySetInnerHTML
Use textContent-equivalent patterns (React auto-escapes JSX expressions)
For SSR hydration data, use JSON.stringify() with a replacer that escapes </script>
Validate and sanitize URLs before rendering in href or src
Vulnerable Code:
function Comment({ body }: { body: string }) {
return <div dangerouslySetInnerHTML={{ __html: body }} />;
}
// SSR hydration - userData can break out of script tag
const html = `<script>window.__DATA__ = ${JSON.stringify(userData)};</script>`;
Safe Code:
import DOMPurify from 'isomorphic-dompurify';
function Comment({ body }: { body: string }) {
const clean = DOMPurify.sanitize(body, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
});
return <div dangerouslySetInnerHTML={{ __html: clean }} />;
}
// SSR hydration - escape closing script tags
function serializeForScript(data: unknown): string {
return JSON.stringify(data).replace(/</g, '\\u003c');
}
const html = `<script>window.__DATA__ = ${serializeForScript(userData)};</script>`;
12. Next.js Server Action Injection, Middleware Bypass, and ISR Cache Poisoning
Description: Next.js introduces server-specific attack surfaces: Server Actions receive untrusted client input, middleware can be bypassed with path manipulation, and ISR/SSG cache can be poisoned to serve malicious content to all users.
Dangerous Functions / Patterns:
Server Actions without input validation (form data is fully attacker-controlled)
Middleware matching on paths vulnerable to .. or encoded traversal
ISR revalidateTag() / revalidatePath() exposed without authentication
headers() and cookies() in Server Components used without validation
redirect() with user-controlled destinations (open redirect)
unstable_cache() keyed on user-controlled values
Safe Alternative:
Validate all Server Action inputs with Zod schemas
Use middleware matchers carefully and test edge cases with encoded paths
Protect revalidation endpoints with secret tokens
Validate redirect targets against an allowlist of domains/paths
Never trust headers or cookies without validation in Server Components
Vulnerable Code:
// app/actions.ts
'use server';
export async function updateProfile(formData: FormData) {
const role = formData.get('role') as string;
// User can submit role=admin
await db.user.update({ where: { id: session.userId }, data: { role } });
}
// middleware.ts
export function middleware(request: NextRequest) {
// Bypassable with /_next/.. path encoding tricks
if (request.nextUrl.pathname.startsWith('/admin')) {
return checkAuth(request);
}
}
Safe Code:
// app/actions.ts
'use server';
import { z } from 'zod';
const UpdateProfileSchema = z.object({
displayName: z.string().min(1).max(100),
bio: z.string().max(500).optional(),
// role is NOT accepted from client input
});
export async function updateProfile(formData: FormData) {
const session = await getServerSession();
if (!session) throw new Error('Unauthorized');
const input = UpdateProfileSchema.parse({
displayName: formData.get('displayName'),
bio: formData.get('bio'),
});
await db.user.update({ where: { id: session.userId }, data: input });
}
// middleware.ts - use matcher config for reliable matching
export const config = {
matcher: ['/admin/:path*', '/api/admin/:path*'],
};
13. Prisma/Drizzle ORM Raw Query Injection
Description: ORMs provide safe query builders, but raw query methods bypass parameterization when developers interpolate strings directly.
Dangerous Functions / Patterns:
Prisma: prisma.$queryRawUnsafe() with string concatenation
Prisma: Use Prisma.sql tagged template for auto-parameterization
Drizzle: Use sql.placeholder() or the query builder
Use parameterized queries with binding arrays
Avoid $queryRawUnsafe and sql.raw() entirely with user input
Vulnerable Code:
// Prisma
const users = await prisma.$queryRawUnsafe(
`SELECT * FROM users WHERE email = '${req.query.email}'`
);
// Drizzle
const result = await db.execute(
sql`SELECT * FROM users WHERE name = ${sql.raw(req.query.name)}`
);
Safe Code:
// Prisma - tagged template auto-parameterizes
const users = await prisma.$queryRaw(
Prisma.sql`SELECT * FROM users WHERE email = ${req.query.email}`
);
// Drizzle - use query builder
const result = await db.select()
.from(users)
.where(eq(users.name, req.query.name));
14. WebSocket XSS and postMessage Origin Bypass
Description: WebSocket messages and postMessage events are often trusted without origin validation, enabling cross-origin script injection and data exfiltration.
Description: Regex patterns with nested quantifiers or overlapping alternation cause catastrophic backtracking when matched against crafted input, freezing the event loop.
Dangerous Functions / Patterns:
Patterns like (a+)+, (a|a)+, (.*a){10}
User-supplied regex via new RegExp(userInput)
Email/URL validation regex with nested groups
Regex used in hot paths (middleware, request parsing)
String.prototype.match(), .replace(), .search() with vulnerable patterns
Safe Alternative:
Use re2 (Google's RE2 engine) which guarantees linear time
Use the safe-regex or regexp-tree libraries to lint patterns
Set timeouts on regex execution with node:vm or worker threads
Prefer simple, non-nested patterns or use dedicated parsers
Validate input length before applying regex
Vulnerable Code:
// Catastrophic backtracking with nested quantifiers
const emailRegex = /^([a-zA-Z0-9]+\.)*[a-zA-Z0-9]+@([a-zA-Z0-9]+\.)+[a-zA-Z]{2,}$/;
app.post('/subscribe', (req, res) => {
if (emailRegex.test(req.body.email)) { // Hangs on crafted input
subscribe(req.body.email);
}
});
// User-controlled regex
const pattern = new RegExp(req.query.filter); // ReDoS + regex injection
Safe Code:
import RE2 from 're2';
const emailRegex = new RE2(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
app.post('/subscribe', (req, res) => {
const email = String(req.body.email);
if (email.length > 254) return res.status(400).send('Invalid email');
if (emailRegex.test(email)) {
subscribe(email);
}
});
// Never allow user-controlled regex - use substring matching instead
function matchFilter(input: string, filter: string): boolean {
return input.includes(filter); // Simple substring, no backtracking
}
16. Path Traversal via path.join / path.resolve
Description:path.join() and path.resolve() resolve .. segments, allowing attackers to escape intended directories when user input is included in file paths.
Dangerous Functions / Patterns:
path.join(uploadsDir, userFilename) where filename contains ../../
app.get('/files/:name', (req, res) => {
const baseDir = path.resolve('/app/uploads');
const filePath = path.resolve(baseDir, req.params.name);
// Ensure resolved path is still within base directory
if (!filePath.startsWith(baseDir + path.sep)) {
return res.status(400).send('Invalid path');
}
res.sendFile(filePath);
});
17. Insecure Randomness (Math.random)
Description:Math.random() uses a PRNG that is not cryptographically secure. Using it for tokens, session IDs, OTPs, or any security-sensitive value makes them predictable.
Dangerous Functions / Patterns:
Math.random().toString(36) for tokens or IDs
Math.floor(Math.random() * max) for OTP generation
Custom shuffle/selection using Math.random() for security purposes
Third-party libraries using Math.random() internally
Safe Alternative:
Use crypto.randomBytes() or crypto.randomUUID() in Node.js
Use crypto.getRandomValues() in browsers
Use nanoid or uuid libraries that use cryptographic randomness
Use crypto.randomInt() for secure random integers
Vulnerable Code:
function generateToken(): string {
return Math.random().toString(36).substring(2); // Predictable
}
function generateOTP(): string {
return String(Math.floor(Math.random() * 1000000)).padStart(6, '0');
}
Safe Code:
import crypto from 'node:crypto';
function generateToken(): string {
return crypto.randomBytes(32).toString('hex');
}
function generateOTP(): string {
return String(crypto.randomInt(0, 1000000)).padStart(6, '0');
}
18. CORS Misconfiguration in Express/Fastify
Description: Overly permissive CORS configurations allow malicious websites to make authenticated cross-origin requests, exfiltrate data, or perform actions on behalf of the user.
Dangerous Functions / Patterns:
origin: '*' combined with credentials: true
Reflecting req.headers.origin directly as Access-Control-Allow-Origin
Regex-based origin matching with bypasses
Missing CORS configuration (defaults to no restriction on simple requests)
Access-Control-Allow-Methods: * exposing all methods
Safe Alternative:
Maintain an explicit allowlist of permitted origins
Never reflect the Origin header without validation
Use exact string matching, not substring or regex
Only allow necessary methods and headers
Test CORS configuration with tools like curl from different origins
Description: npm/pnpm lifecycle scripts (preinstall, postinstall, prepare, prepublishOnly) execute arbitrary commands during npm install. Malicious or compromised packages can use these to execute code on developer machines and CI systems.
Dangerous Functions / Patterns:
"preinstall" scripts in dependency packages that download remote payloads
"postinstall": "node ./setup.js" that downloads and executes remote code
Lifecycle scripts that modify .bashrc, .npmrc, or other config files
Build scripts that execute dynamically constructed shell commands
Safe Alternative:
Run npm install --ignore-scripts and execute needed scripts explicitly
Use npm config set ignore-scripts true as a global default
Audit package.json scripts of new dependencies before installing
Use pinst to disable postinstall in published packages
Use allowScripts in .npmrc (npm v9+) to allowlist scripts per package
Run installs in sandboxed CI environments with limited network access
Description: Using === or == to compare secrets (API keys, tokens, HMAC digests) leaks information through timing differences, as the comparison short-circuits on the first mismatched character.
Dangerous Functions / Patterns:
if (token === expectedToken) for authentication tokens
if (hmac === computedHmac) for webhook signature verification
Password hash comparison with string equality
Safe Alternative:
Use crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b))
Ensure both buffers are the same length before comparison
Use scrypt or argon2 for password verification (they handle timing internally)
Description: Secrets hardcoded in source, committed .env files, or exposed via client-side bundles leak credentials. Next.js's NEXT_PUBLIC_ prefix explicitly sends variables to the browser.
// .env.local (in .gitignore)
DATABASE_URL=postgres://admin:password@localhost:5432/app
STRIPE_SECRET_KEY=sk_test_...
// Only public-safe values get the prefix
NEXT_PUBLIC_STRIPE_PUBLISHABLE=pk_live_...
// Server-only access in app/api/payment/route.ts
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
24. Server-Side Template Injection in Handlebars/EJS/Pug
Description: Template engines that compile user input into templates (rather than using it as data) enable remote code execution through template syntax.
// Pre-compiled templates only
const templates = new Map<string, HandlebarsTemplateDelegate>();
for (const file of fs.readdirSync('./templates')) {
const source = fs.readFileSync(`./templates/${file}`, 'utf8');
templates.set(path.basename(file, '.hbs'), Handlebars.compile(source));
}
app.post('/preview', (req, res) => {
const template = templates.get(req.body.templateName);
if (!template) return res.status(400).send('Unknown template');
const html = template({ name: req.body.name }); // User data as context only
res.send(html);
});
Scan Procedure
Enumerate TypeScript/JavaScript files across the project, including .ts, .tsx, .js, .jsx, .mjs, .cjs files and configuration files (tsconfig.json, package.json, .eslintrc, next.config.*).
For each vulnerability category above, search the codebase for the listed dangerous patterns using AST-aware matching when possible, falling back to regex patterns.
Classify findings by severity:
Critical: RCE vectors (eval injection, child_process injection, vm escape, SSTI, prototype pollution leading to RCE)
High: XSS, SQL injection via raw queries, SSRF, JWT misconfiguration, auth bypass
Medium: ReDoS, CORS misconfiguration, insecure randomness, timing attacks, error leakage
Low: TypeScript type safety bypass, missing security headers, suboptimal patterns