agentsclimarketplace

Nestjs attack probe

Skill Dolphinllc/claude-security-skills/skills/offensive/web/nestjs-attack-probe

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.From its SKILL.md

Install
npx -y skills add Dolphinllc/claude-security-skills --skill nestjs-attack-probe

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things 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.
  • fetches URLsInstructs the agent to fetch 6 URLs, including /api and 5 more.

SKILL.md

4.5 KB, ~1.1k tokens by cl100k_base, 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()) without whitelist: true allows 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/swagger auto-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

  1. Authorization preflight + base URL discovery.
  2. Fetch Swagger if exposed: try /api, /api/docs, /swagger, /docs. The OpenAPI JSON is usually at <docs>/json or /api-json.
  3. Probe per rule table.

Rules

IDSeverityProbeConfirmed when
NEST-DOC-001mediumGET /api, /swagger, /docs200 Swagger UI = docs exposed (use as enumeration aid)
NEST-AUTH-001criticalFor each mutating route in OpenAPI without a security requirement, send unauthenticated request2xx = @UseGuards missing
NEST-AUTH-002highFor routes with security: bearerAuth, send obviously-malformed token2xx = guard returns true instead of throwing
NEST-PIPE-001highSubmit 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-002mediumSubmit body with type-confusion (string where number expected)500 instead of 422 = transformation/validation pipe partially configured
NEST-DTO-001mediumFind 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-001highIf /socket.io or custom gateway endpoint advertised, connect without auth headerConnection upgraded + message received = no canActivate in handleConnection
NEST-CORS-001highOPTIONS /api/* with Origin: https://evil.test and credentialsACAO + ACAC: true = enableCors({ origin: '*' or true, credentials: true })
NEST-EXC-001mediumForce an error via malformed JSON / DB constraint violation500 with full stack / class names = exception filter leaking
NEST-COOKIE-001highLogin, capture cookie. Test httpOnly, secure, sameSite flags via Set-Cookie headerMissing flags = misconfigured cookie-parser/session
NEST-RATE-001medium10 rapid POST /auth/loginNo 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

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.