Nestjs attack probe
Skill Dolphinllc/claude-security-skills/skills/offensive/web/nestjs-attack-probe
Defensive security skills for Claude Code and the Claude Agent SDK — web applications and generative AI systems.
npx -y skills add Dolphinllc/claude-security-skills --skill nestjs-attack-probeAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Authorized self-pentest probe targeting NestJS-specific weaknesses. Tests global ValidationPipe gaps, missing @UseGuards on controller methods, default Swagger/OpenAPI exposure, WebSocket Gateway auth bypass, and TypeORM/Prisma raw query injection points discovered via OpenAPI. Use when the user asks to "pentest" their own NestJS app.
SKILL.md
4.5 KB, as published. Nobody here has run it
NestJS Attack Probe
Authorized probe of a NestJS 10.x/11.x app the user owns. Follow shared probing conventions — discover base URL from main.ts app.listen(...), process.env.PORT, Dockerfile EXPOSE, or nest-cli.json. Never hardcode.
NestJS-specific attack surface
- Validation is opt-in:
app.useGlobalPipes(new ValidationPipe())withoutwhitelist: trueallows extra fields to flow through to handlers, defeating DTO-based validation. - Guards are opt-in:
@UseGuards()on a controller class is per-class; per-method overrides + a missed method = anonymous endpoint. @nestjs/swaggerauto-mounts/api(or configured path) — by default unauthenticated.- WebSocket Gateways don't use the HTTP guard chain; they need their own auth in
handleConnection. @ApiBearerAuth()decorator is documentation only; it does not enforce the bearer token.
Procedure
- Authorization preflight + base URL discovery.
- Fetch Swagger if exposed: try
/api,/api/docs,/swagger,/docs. The OpenAPI JSON is usually at<docs>/jsonor/api-json. - Probe per rule table.
Rules
| ID | Severity | Probe | Confirmed when |
|---|---|---|---|
| NEST-DOC-001 | medium | GET /api, /swagger, /docs | 200 Swagger UI = docs exposed (use as enumeration aid) |
| NEST-AUTH-001 | critical | For each mutating route in OpenAPI without a security requirement, send unauthenticated request | 2xx = @UseGuards missing |
| NEST-AUTH-002 | high | For routes with security: bearerAuth, send obviously-malformed token | 2xx = guard returns true instead of throwing |
| NEST-PIPE-001 | high | Submit a body with extra fields not in DTO ({"role": "admin", ...valid...}) | Response shows extra field accepted = whitelist: true not set; combined with mass-assignment lookup → high |
| NEST-PIPE-002 | medium | Submit body with type-confusion (string where number expected) | 500 instead of 422 = transformation/validation pipe partially configured |
| NEST-DTO-001 | medium | Find a DTO without class-validator decorators (parse OpenAPI: properties with no constraints); send semantically invalid data (e.g., email: "not-email") | 2xx = no @IsEmail() enforcement |
| NEST-WS-001 | high | If /socket.io or custom gateway endpoint advertised, connect without auth header | Connection upgraded + message received = no canActivate in handleConnection |
| NEST-CORS-001 | high | OPTIONS /api/* with Origin: https://evil.test and credentials | ACAO + ACAC: true = enableCors({ origin: '*' or true, credentials: true }) |
| NEST-EXC-001 | medium | Force an error via malformed JSON / DB constraint violation | 500 with full stack / class names = exception filter leaking |
| NEST-COOKIE-001 | high | Login, capture cookie. Test httpOnly, secure, sameSite flags via Set-Cookie header | Missing flags = misconfigured cookie-parser/session |
| NEST-RATE-001 | medium | 10 rapid POST /auth/login | No 429 = @nestjs/throttler not registered |
Wrong vs. right
NEST-PIPE-001 (extra-field bypass)
// ❌ main.ts — pipe registered without whitelist
app.useGlobalPipes(new ValidationPipe());
// ✅
app.useGlobalPipes(new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
}));
NEST-AUTH-001 (per-method guard miss)
// ❌ Class guard, but one method missing decoration override + decorator removed
@Controller("orders")
@UseGuards(JwtAuthGuard)
export class OrdersController {
@Get() list() { /* guarded */ }
@Public() // someone added this for tests, forgot to remove
@Delete(":id") remove() { /* now anonymous */ }
}
// ✅
@Controller("orders")
@UseGuards(JwtAuthGuard, RolesGuard)
export class OrdersController {
@Get() list() { /* ... */ }
@Roles("admin")
@Delete(":id") remove() { /* ... */ }
}
References
- NestJS Validation: https://docs.nestjs.com/techniques/validation
- NestJS Guards: https://docs.nestjs.com/guards
- NestJS WebSockets: https://docs.nestjs.com/websockets/gateways
- @nestjs/swagger: https://docs.nestjs.com/openapi/introduction