agentsclimarketplace

Cicada

Skill Synthrun/Cicada

Cicada โ€” Security Audit & Fix Skill for LLM coding agents (16 domains, cross-framework)From the repository description

Install
npx -y skills add Synthrun/Cicada

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

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 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.

SKILL.md

86.3 KB, ~22.3k tokens by cl100k_base, as published. Nobody here has run it

๐Ÿ” Cicada โ€” Security Audit & Fix Skill

Command: /cicada
Audit your backend and mobile apps for vulnerabilities โ€” and optionally fix them โ€” without deploying or breaking anything.

Compatible with: CODEX, CLAUDE, OPENCODE, Cursor, Windsurf, any LLM coding agent.
Covers: Node.js, Python, Go, Ruby, PHP, Java, .NET + Express, Next.js, NestJS, Django, Flask, FastAPI, Gin, Rails, Laravel, Spring Boot + Flutter, React Native.


How to Invoke

You:  /cicada
Agent:  Choose mode:
        1 โ†’ Report only (no code changes)
        2 โ†’ Interactive fix (ask per finding)
        3 โ†’ Auto-fix all (fix everything, confirm once)

You:  /cicada audit my backend
Agent:  (loads SKILL.md, asks mode, runs audit)

You:  security audit
Agent:  (triggered by AGENTS.md, loads SKILL.md, asks mode)

Tool-specific setup

ToolSetup
OPENCODEPlace opencode.json + AGENTS.md in project root. Run /cicada.
CLAUDEPlace AGENTS.md in project root or .claude/. Run /cicada.
CODEXLoad SKILL.md directly: /load-skill /path/to/SKILL.md then run.
Cursor / WindsurfLoad SKILL.md directly as a rules file or use .cicada config.

When to Load

Load this skill when the user says:

  • /cicada โ€” primary command
  • "security audit / security review / vulnerability scan"
  • "check for vulnerabilities / find security issues"
  • "is my app secure / are my auth flows safe"
  • "audit login / password reset / connectors / API keys"
  • "OWASP review / pentest my code / HackerOne style review"
  • "is this production-ready from a security perspective"
  • "fix security issues / patch vulnerabilities"
  • "audit my Flutter app / React Native app"

Operation Mode

The LLM must ask the user which mode they want before proceeding.

OptionWhat happens
1 โ€” Report onlyRead-only audit. Generate report.md. No code changes.
2 โ€” Interactive fixFor each finding, ask: "Fix this? (y/n/skip all)". Generate report after.
3 โ€” Auto-fix allFix every finding automatically (user confirms once). Generate report after.
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Choose mode:                                             โ”‚
โ”‚                                                          โ”‚
โ”‚  1 โ†’ Report only (no code changes)                       โ”‚
โ”‚  2 โ†’ Interactive fix (ask per finding)                   โ”‚
โ”‚  3 โ†’ Auto-fix all (fix everything, confirm once)         โ”‚
โ”‚                                                          โ”‚
โ”‚ Enter 1, 2, or 3:                                        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Audit Scope

#DomainKey Focus
1Auth & Session Mgmtlogin, logout, JWT, OAuth, magic links, timing attacks
2Password Reset Flowtoken generation, expiry, enumeration protection
3Connector SecurityAPI keys, webhooks, DB connections, third-party SDKs
4API & Input Handlinginjection, rate limiting, CORS, validation, security headers
5Secrets & Configenv vars, hardcoded secrets, .env exposure, logging
6Dependencies & Infrastructureoutdated packages, HTTPS, TLS, error handling
7Web Framework SecurityExpress, Next.js, NestJS, Django, Flask, FastAPI, Gin, Rails, Laravel, Spring Boot
8Mobile App SecurityFlutter, React Native โ€” deep links, storage, SSL pinning, obfuscation
9Cloud & InfrastructureAWS/Azure/GCP configs, S3 buckets, IAM roles, Docker, K8s
10GraphQL Securityintrospection depth, query cost, auth per resolver, batching
11WebSocket Securityorigin validation, WS auth, message rate limiting, replay
12File Upload Securitymagic bytes, size limits, virus scan, path traversal, zip bombs
13Data Privacy & CompliancePII handling, GDPR/CCPA, encryption at rest, data retention
14Cryptography & Key Mgmtciphers, key rotation, RNG, IVs, certificate lifecycle
15CI/CD & Supply Chainpipeline secrets, typosquatting, dep confusion, signed commits
16Logging & Monitoringaudit logs, log injection, retention, alerting gaps

Check Methodology

  1. Detect framework(s) used (see Framework Detection below).
  2. Search the codebase for relevant patterns (grep, glob).
  3. Read surrounding context (20โ€“40 lines) to understand the implementation.
  4. Assess severity using the rubric at the end of this document.
  5. Log every finding โ€” even low-severity โ€” into an internal findings list.
  6. If mode 2 or 3: apply the fix template associated with each finding.

Framework Detection

Before running checks, auto-detect every framework present. Read config files and key source imports. Then run only the relevant sections below.

Detection Table

FrameworkFiles to readKey imports / configs to search
Node.js / Expresspackage.jsonexpress, cors, helmet, express-rate-limit
Next.jspackage.json, next.config.js, next.config.mjsnext, next/server, middleware.ts
NestJSpackage.json, nest-cli.json@nestjs/core, @nestjs/common, @UseGuards
Python / Djangorequirements.txt, Pipfile, pyproject.toml, manage.py, settings.pydjango, SECRET_KEY, DEBUG
Python / Flaskrequirements.txt, app.py, config.pyflask, Flask(__name__), secret_key
Python / FastAPIrequirements.txt, main.pyfastapi, FastAPI(), CORSMiddleware
Go / Gingo.mod, main.gogin-gonic/gin, gin.Default()
Ruby / RailsGemfile, config/application.rb, config/secrets.ymlrails, secret_key_base, config.force_ssl
PHP / Laravelcomposer.json, .env, config/app.phplaravel/framework, APP_KEY, APP_DEBUG
Java / Spring Bootpom.xml, build.gradle, application.properties, application.ymlspring-boot-starter-web, @SpringBootApplication
Flutterpubspec.yaml, android/, ios/, lib/flutter, flutter_secure_storage, http, webview_flutter
React Nativepackage.json, android/, ios/, app.jsonreact-native, AsyncStorage, react-native-config

Run ALL relevant sections based on detected frameworks. If multiple frameworks are detected (e.g., Next.js backend + Flutter mobile), run checks for all of them.


7. Web Framework Security

Run this section for every detected web framework in addition to the universal checks (sections 1โ€“6).


7.1 Node.js / Express

Search:  package.json, express, app.use(, router.get(, router.post(
  • Missing Helmet โ€” is helmet() applied globally? Without it, default security headers (CSP, HSTS, X-Frame-Options) are absent.
  • CORS misconfigured โ€” cors({ origin: '*' }) in production? Should use an allowlist.
  • Rate limiting missing โ€” is express-rate-limit applied to auth routes?
  • Body parser size limit โ€” does express.json({ limit: '10mb' }) have an unbounded limit? Set to '1mb' or '10kb' for small payloads.
  • HTTP parameter pollution โ€” does the app handle duplicate query params safely? (e.g., ?id=1&id=2)
  • Prototype pollution โ€” are there any unsafe lodash.merge, Object.assign(req.body, ...), or for...in patterns?
  • Cookie config โ€” are cookies missing httpOnly, secure, sameSite?
  • Express app.set('trust proxy') โ€” is it configured correctly behind a reverse proxy? If not, rate limiting may see all traffic from 127.0.0.1.
  • Directory listing โ€” is express.static configured without dotfiles: 'deny'? Can attackers list directories?

Fix: Add Helmet + rate limiting + secure cookies

const helmet = require('helmet');
const rateLimit = require('express-rate-limit');

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

const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5,
  message: 'Too many attempts'
});
app.post('/login', authLimiter, loginHandler);

app.use(require('cookie-parser')());
app.use((req, res, next) => {
  res.cookie('session', req.sessionID, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'strict',
    maxAge: 24 * 60 * 60 * 1000
  });
  next();
});

7.2 Next.js

Search:  package.json, next.config, middleware.ts, pages/api/, app/api/
  • Server Actions CSRF โ€” are Next.js Server Actions protected with CSRF tokens? (Next.js 14+ has built-in CSRF for Server Actions โ€” verify it's not disabled.)
  • Middleware bypass โ€” does middleware.ts protect all sensitive routes? Check for missing matcher config.
  • API route exposure โ€” are internal API routes behind authentication middleware? Check pages/api/ or app/api/ for unprotected handlers.
  • getServerSideProps data leakage โ€” does getServerSideProps pass sensitive data (tokens, DB records) to the client without filtering?
  • next/image SSRF โ€” are remote image URLs user-controllable without a host allowlist? (CVE-2023-34247)
  • next.config.js exposure โ€” is publicRuntimeConfig leaking secrets to the client bundle?
  • Incremental Static Regeneration (ISR) โ€” are secret revalidation URLs predictable or unprotected?
  • App Router: useSearchParams XSS โ€” are search params rendered without sanitization in client components?
  • next/script CSP bypass โ€” are external scripts loaded with strategy: 'beforeInteractive' bypassing CSP?

Fix: Secure middleware

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const token = request.cookies.get('session')?.value;
  const isAuthPage = request.nextUrl.pathname.startsWith('/login');

  if (!token && !isAuthPage) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  return NextResponse.next();
}

export const config = {
  matcher: ['/dashboard/:path*', '/api/protected/:path*']
};

Fix: Image SSRF protection

// next.config.js
module.exports = {
  images: {
    remotePatterns: [
      { protocol: 'https', hostname: 'cdn.example.com' },
      { protocol: 'https', hostname: 'images.example.com' }
    ]
  }
};

7.3 NestJS

Search:  package.json, @nestjs, @UseGuards, @Controller, GraphQLModule
  • Missing @UseGuards โ€” are controllers/routes missing authentication guards? Check for public endpoints that should be protected.
  • DTO validation bypass โ€” are DTOs missing class-validator decorators? (@IsEmail(), @IsString(), @MinLength(8))
  • GraphQL introspection enabled in production โ€” is introspection: true set in GraphQLModule.forRoot()? (Leaks entire schema.)
  • @Serialize / class-serializer exposure โ€” does @Serialize expose sensitive fields like password, ssn?
  • Rate limiting missing โ€” is @nestjs/throttler configured globally?
  • CORS misconfigured โ€” is cors: true / origin: '*' in NestFactory.create()?
  • File upload validation โ€” are file uploads unrestricted in size or type?
  • Validation pipe global โ€” is app.useGlobalPipes(new ValidationPipe()) applied? (Without it, DTO validation is opt-in per route.)

Fix: Global validation + throttling

import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { ThrottlerGuard, ThrottlerModule } from '@nestjs/throttler';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  app.enableCors({
    origin: process.env.CORS_ORIGIN?.split(',') || 'http://localhost:3000',
    credentials: true
  });

  app.useGlobalPipes(new ValidationPipe({
    whitelist: true,
    forbidNonWhitelisted: true,
    transform: true
  }));

  await app.listen(3000);
}
// app.module.ts
@Module({
  imports: [
    ThrottlerModule.forRoot([{
      ttl: 60000,
      limit: 100
    }])
  ],
  providers: [{ provide: APP_GUARD, useClass: ThrottlerGuard }]
})

7.4 Python / Django

Search:  settings.py, manage.py, requirements.txt, SECRET_KEY, DEBUG, ALLOWED_HOSTS
  • SECRET_KEY hardcoded or committed โ€” is the Django SECRET_KEY in settings.py instead of an env var?
  • DEBUG = True in production โ€” is DEBUG set to True in production settings? (Leaks stack traces, settings, queries.)
  • ALLOWED_HOSTS misconfigured โ€” is ['*'] used? (Permits host header injection.)
  • SQL injection via .raw() / extra() โ€” are raw SQL queries parameterized?
  • Mass assignment โ€” are Django REST Framework serializers using fields = '__all__' without read-only fields?
  • mark_safe() / safe filter XSS โ€” is mark_safe() used on user input in templates?
  • CSRF middleware missing โ€” is CsrfViewMiddleware in MIDDLEWARE settings?
  • Session cookie config โ€” are SESSION_COOKIE_HTTPONLY, SESSION_COOKIE_SECURE, CSRF_COOKIE_SECURE set?
  • File upload validation โ€” is FILE_UPLOAD_MAX_MEMORY_SIZE set? Are uploaded file types validated?
  • Django REST Framework throttle โ€” is DEFAULT_THROTTLE_CLASSES configured for auth endpoints?
  • CORS headers โ€” is django-cors-headers configured with a specific CORS_ALLOWED_ORIGINS, not CORS_ALLOW_ALL_ORIGINS = True?
  • Admin panel exposure โ€” is django.contrib.admin accessible at /admin/ without IP restriction or VPN?

Fix: Secure settings.py

import os

SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
DEBUG = os.environ.get('DJANGO_DEBUG', 'False') == 'False'
ALLOWED_HOSTS = os.environ.get('DJANGO_ALLOWED_HOSTS', '.example.com').split(',')

SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
SECURE_HSTS_SECONDS = 63072000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_SSL_REDIRECT = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
X_FRAME_OPTIONS = 'DENY'

# Rate limiting
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.AnonRateThrottle',
    ],
    'DEFAULT_THROTTLE_RATES': {
        'anon': '100/hour',
        'user': '1000/hour'
    }
}

7.5 Python / Flask

Search:  app.py, config.py, requirements.txt, Flask(__name__), secret_key, debug=True
  • secret_key hardcoded โ€” is app.secret_key set to a static string in source?
  • debug=True in production โ€” does app.run(debug=True) exist? (Leaves the Werkzeug debugger and console open โ€” RCE via debugger PIN.)
  • Jinja2 SSTI (Server-Side Template Injection) โ€” is render_template_string() used with user input?
  • Missing CSRF protection โ€” is Flask-WTF or flask-seasurf installed and enabled?
  • Session cookies โ€” are SESSION_COOKIE_HTTPONLY, SESSION_COOKIE_SECURE, SESSION_COOKIE_SAMESITE configured?
  • CORS wildcard โ€” is flask-cors configured with origins='*'?
  • Rate limiting โ€” is flask-limiter applied to auth routes?

Fix: Secure Flask app

from flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from flask_talisman import Talisman

app = Flask(__name__)
app.secret_key = os.environ['FLASK_SECRET_KEY']
app.config.update(
    SESSION_COOKIE_HTTPONLY=True,
    SESSION_COOKIE_SECURE=True,
    SESSION_COOKIE_SAMESITE='Lax'
)

# Security headers
Talisman(app, content_security_policy={
    'default-src': "'self'",
    'script-src': "'self'"
})

# Rate limiting
limiter = Limiter(
    get_remote_address,
    app=app,
    default_limits=["200 per day", "50 per hour"]
)

# ๐Ÿšซ NEVER: app.run(debug=True)

7.6 Python / FastAPI

Search:  main.py, requirements.txt, FastAPI(), CORSMiddleware, @app.get
  • CORS wildcard โ€” is CORSMiddleware configured with allow_origins=["*"]?
  • Missing authentication โ€” are routes missing Depends(get_current_user)?
  • Pydantic validation bypass โ€” are request models missing Pydantic validators? (Field(..., min_length=8))
  • GraphQL introspection โ€” if using Strawberry/Ariadne, is introspection disabled in production?
  • File upload size โ€” are file uploads missing max_size on UploadFile?
  • Rate limiting โ€” is slowapi or fastapi-limiter configured?
  • OpenAPI / Swagger exposure โ€” is /docs or /redoc exposed in production? (Leaks full API structure.)
  • Server info leakage โ€” does uvicorn run with --header Server: uvicorn? Attackers can target known uvicorn bugs.

Fix: Secure FastAPI

from fastapi import FastAPI, Depends, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address

limiter = Limiter(key_func=get_remote_address)

app = FastAPI(
    docs_url=None,          # Disable Swagger in production
    redoc_url=None,         # Disable ReDoc in production
    servers=[{"url": "https://api.example.com"}]
)

app.state.limiter = limiter
app.add_exception_handler(429, _rate_limit_exceeded_handler)

app.add_middleware(
    CORSMiddleware,
    allow_origins=os.environ.get('CORS_ORIGINS', '').split(','),
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["Authorization", "Content-Type"],
)

@app.get("/users/me")
@limiter.limit("30/minute")
async def read_users_me(current_user=Depends(get_current_user)):
    return current_user

7.7 Go / Gin

Search:  go.mod, main.go, gin.Default(), router.GET(, c.Query(, db.Query(
  • CORS wildcard โ€” is gin-contrib/cors configured with AllowAllOrigins: true?
  • Missing recovery middleware โ€” is gin.Recovery() included? (Without it, panics crash the server.)
  • No rate limiting โ€” is gin-limiter or similar applied to auth routes?
  • Raw SQL injection โ€” are there db.Query(fmt.Sprintf(...)) calls with user input?
  • No TrustedPlatform โ€” is gin.TrustedPlatform set behind a reverse proxy? (Without it, client IP detection may be wrong for rate limiting.)
  • Verbose error responses โ€” does the API return raw error messages or stack traces?
  • Cookie config โ€” are session cookies missing HttpOnly, Secure, SameSite?
  • No request size limit โ€” is c.MaxMultipartMemory and gin.MaxMultipartMemory configured?

Fix: Secure Gin

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/gin-contrib/cors"
    "golang.org/x/time/rate"
)

func main() {
    r := gin.New()
    r.Use(gin.Recovery())
    r.Use(gin.Logger())

    // CORS
    r.Use(cors.New(cors.Config{
        AllowOrigins: []string{"https://app.example.com"},
        AllowCredentials: true,
        AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
        AllowHeaders: []string{"Authorization", "Content-Type"},
    }))

    // Rate limiting
    limiter := rate.NewLimiter(rate.Limit(10), 20)
    r.Use(func(c *gin.Context) {
        if !limiter.Allow() {
            c.AbortWithStatusJSON(429, gin.H{"error": "Too many requests"})
            return
        }
        c.Next()
    })

    r.GET("/login", loginHandler)
    r.Run(":3000")
}

7.8 Ruby on Rails

Search:  Gemfile, config/application.rb, config/secrets.yml, app/controllers/
  • secret_key_base hardcoded or weak โ€” is secret_key_base in config/secrets.yml or credentials.yml.enc exposed?
  • config.force_ssl = false โ€” is HTTPS not enforced?
  • Mass assignment โ€” are there params.permit! calls that allow all attributes? (CVE-2012-2660, CVE-2012-2695)
  • Render inline SSTI โ€” is render inline: used with user input? (Server-Side Template Injection.)
  • attr_accessible / attr_protected bypass โ€” are sensitive model attributes protected from mass assignment?
  • SQL injection via where() strings โ€” are there Model.where("name = '#{params[:name]}'") calls?
  • Missing CSRF token โ€” is protect_from_forgery with: :exception in ApplicationController?
  • Open redirect โ€” are there unsafe redirect_to params[:url] patterns? (CVE-2023-23913)
  • N+1 queries exposed โ€” does the JSON API leak child records without authorization checks?
  • Cookie config โ€” are cookies missing httponly, secure, samesite in config/initializers/session_store.rb?

Fix: Secure Rails configuration

# config/application.rb
config.force_ssl = true
config.ssl_options = { redirect: { status: 301 } }

# config/initializers/session_store.rb
Rails.application.config.session_store :cookie_store, {
  key: '_app_session',
  httponly: true,
  secure: Rails.env.production?,
  same_site: :strict,
  expire_after: 24.hours
}

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  before_action :sanitize_redirect
  private
  def sanitize_redirect
    redirect_url = params[:url]
    if redirect_url.present? && !redirect_url.start_with?('/')
      redirect_to root_path, alert: 'Invalid redirect'
    end
  end
end

7.9 PHP / Laravel

Search:  composer.json, .env, config/app.php, routes/web.php, routes/api.php
  • APP_KEY exposed โ€” is APP_KEY in .env committed to the repo?
  • APP_DEBUG=true in production โ€” is debug mode enabled? (Leaks full stack traces and env vars.)
  • Mass assignment โ€” are Eloquent models missing $fillable or using $guarded = []?
  • SQL injection via whereRaw / DB::raw โ€” are raw queries using string interpolation with user input?
  • Blade XSS โ€” is {!! $var !!} (unescaped Blade output) used with user-controlled content?
  • Missing CSRF โ€” is @csrf excluded from forms? Is VerifyCsrfToken middleware removed?
  • CORS misconfigured โ€” is laravel-cors set to 'allowed_origins' => ['*']?
  • Rate limiting โ€” is throttle middleware applied to auth routes? (Route::post('login', ...)->middleware('throttle:5,60'))
  • Session config โ€” are sessions configured with http_only => true, secure => true?
  • Debug bar in production โ€” is barryvdh/laravel-debugbar installed and visible?
  • Artisan console exposure โ€” is routes/console.php exposing sensitive commands?

Fix: Secure Laravel

// .env (ensure in .gitignore!)
APP_KEY=base64:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
APP_DEBUG=false
APP_URL=https://example.com

DB_CONNECTION=mysql
DB_HOST=${DB_HOST}
DB_DATABASE=${DB_DATABASE}
DB_USERNAME=${DB_USERNAME}
DB_PASSWORD=${DB_PASSWORD}

// config/session.php
'http_only' => true,
'secure' => env('APP_ENV') === 'production',
'same_site' => 'strict',

// routes/api.php
Route::post('/login', [AuthController::class, 'login'])
    ->middleware(['throttle:5,60']);

7.10 Java / Spring Boot

Search:  pom.xml, build.gradle, application.properties, application.yml, @RestController, @RequestMapping
  • Actuator endpoints exposed โ€” are /actuator, /actuator/env, /actuator/heapdump accessible without authentication? (Leaks env vars โ€” including AWS keys, DB passwords.)
  • @CrossOrigin(origins = "*") โ€” are any controllers using wildcard CORS?
  • @PathVariable injection โ€” are path variables used in SQL queries without parameterization?
  • H2 console in production โ€” is spring.h2.console.enabled=true set? (Database admin panel with no auth.)
  • Default Actuator ports โ€” is Actuator on the same port as the app? Should be on a separate, firewalled port.
  • No CSRF protection โ€” is Spring Security CSRF protection disabled? (http.csrf().disable())
  • Verbose error responses โ€” is server.error.include-stacktrace=always set? (Leaks internal paths and framework details.)
  • Unvalidated file uploads โ€” is spring.servlet.multipart.max-file-size unset or too large?
  • Spring Boot DevTools in production โ€” is spring-boot-devtools on the classpath? (Remote restart and debug endpoints.)
  • Sensitive fields in JSON โ€” are @JsonIgnore annotations missing on password, secret, token fields?

Fix: Secure application.properties

# Disable actuator in production or secure it
management.endpoints.web.exposure.exclude=*
management.endpoint.health.show-details=never

# Disable H2 console
spring.h2.console.enabled=false

# Limit file uploads
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB

# No stack traces
server.error.include-stacktrace=never
server.error.include-message=never

# Force HTTPS
server.ssl.enabled=true
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            .csrf(csrf -> csrf.requireCsrfProtectionMatcher(...))
            .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/auth/**").permitAll()
                .anyRequest().authenticated()
            );
        return http.build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(List.of("https://app.example.com"));
        config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
        config.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }
}

8. Mobile App Security

Run this section when the project contains Flutter (pubspec.yaml) or React Native (package.json with react-native).


8.1 Flutter / Dart

Search:  pubspec.yaml, android/app/src/main/AndroidManifest.xml, ios/Runner/Info.plist, lib/
  • API keys hardcoded in Dart โ€” are API keys, Firebase configs, or tokens hardcoded in Dart source? (Dart code decompiles easily with dart2js / flutter build apk --release + dex2jar.)
  • Insecure local storage โ€” is sensitive data stored in SharedPreferences instead of flutter_secure_storage? (SharedPreferences is plaintext on disk.)
  • No SSL pinning โ€” is HTTP client created without certificate pinning? (http.Client() vs pinned dio or http_secure?)
  • Deep link hijacking โ€” are Android App Links / iOS Universal Links configured? Or does the app use custom URL schemes (e.g., myapp://) that any app can register?
  • WebView XSS / JS bridge โ€” does webview_flutter have javascriptMode: JavascriptMode.unrestricted? Does JavaScriptChannel expose sensitive native APIs?
  • obscureText: false on password fields โ€” are password TextFields missing obscureText: true?
  • Sensitive logging โ€” is debugPrint() or print() used for sensitive data? (Release builds can still have debug logging.)
  • Android: Allow cleartext traffic โ€” is android:usesCleartextTraffic="true" in AndroidManifest.xml?
  • iOS: ATS bypass โ€” is NSAllowsArbitraryLoads = true in Info.plist? (Disables App Transport Security.)
  • Root / jailbreak detection โ€” is there any root detection? If not, attackers can modify the app binary and extract secrets.
  • Code obfuscation โ€” was the app built without --obfuscate and --split-debug-info? (Without obfuscation, Dart code retains class/method names.)
  • Firebase config files โ€” are google-services.json (Android) or GoogleService-Info.plist (iOS) readable and restricted to the intended app? (These contain API keys.)
  • Biometric auth โ€” if using biometrics, is the secret stored with KeyStore / Keychain integration (via local_auth + flutter_secure_storage)?
  • Android: Exported components โ€” are Activity, Service, or BroadcastReceiver exported without permission? (android:exported="true" without intent filters.)
  • iOS: Keychain accessibility โ€” is kSecAttrAccessible set to kSecAttrAccessibleWhenUnlockedThisDeviceOnly for sensitive data?

Fix: Secure storage + SSL pinning (Flutter)

// ๐Ÿšซ BAD:
final prefs = await SharedPreferences.getInstance();
await prefs.setString('auth_token', token);

// โœ… GOOD:
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

const storage = FlutterSecureStorage();
await storage.write(key: 'auth_token', value: token);
// ๐Ÿšซ BAD:
final response = await http.get(Uri.parse('https://api.example.com/data'));

// โœ… GOOD โ€” SSL pinning with Dio
import 'package:dio/dio.dart';

final dio = Dio(BaseOptions(
  baseUrl: 'https://api.example.com',
  connectTimeout: const Duration(seconds: 10),
));

(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
    (client) {
  client.badCertificateCallback = (cert, host, port) => false; // reject all
  return client;
};

Fix: Secure Android manifest

<!-- AndroidManifest.xml -->
<application
    android:usesCleartextTraffic="false"
    android:allowBackup="false"
    android:networkSecurityConfig="@xml/network_security_config">

    <!-- Only export if required -->
    <activity
        android:name=".MainActivity"
        android:exported="false" />
</application>
<!-- res/xml/network_security_config.xml -->
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="false">
        <domain includeSubdomains="true">api.example.com</domain>
    </domain-config>
</network-security-config>

Fix: iOS ATS configuration

<!-- Info.plist -->
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>api.example.com</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
    </dict>
</dict>

Fix: Build with obfuscation

flutter build apk --obfuscate --split-debug-info=build/debug-info/
flutter build ios --obfuscate --split-debug-info=build/debug-info/

8.2 React Native

Search:  package.json, android/app/src/main/AndroidManifest.xml, ios/Info.plist, app.json
  • API keys in .env or hardcoded โ€” are API keys in react-native-config .env files committed? Are they hardcoded in JS source? (JS bundle is unencrypted on device.)
  • AsyncStorage for sensitive data โ€” is AsyncStorage used for tokens, secrets, or PII? (AsyncStorage is unencrypted plaintext โ€” use react-native-keychain or expo-secure-store.)
  • No SSL pinning โ€” does fetch() or axios connect without certificate validation? (Use react-native-ssl-pinning or axios with httpsAgent.)
  • Deep link hijacking โ€” are Android App Links / iOS Universal Links properly configured, or does a custom URL scheme (myapp://) allow any app to intercept?
  • WebView vulnerabilities โ€” does react-native-webview have allowFileAccess={true}, allowUniversalAccessFromFileURLs={true}, or javaScriptEnabled={true} without a content allowlist?
  • secureTextEntry: false on password fields โ€” are password TextInputs missing secureTextEntry={true}?
  • console.log in production โ€” are console.log, console.warn, console.error statements present in production code? (They can leak data to logs accessible by other apps on device.)
  • Android: Allow cleartext traffic โ€” is android:usesCleartextTraffic="true" in AndroidManifest.xml?
  • iOS: ATS bypass โ€” is NSAllowsArbitraryLoads = true in Info.plist?
  • Firebase / Google Services โ€” are google-services.json or GoogleService-Info.plist committed with unrestricted API keys?
  • Code obfuscation โ€” is Hermes enabled without obfuscation? (JS bundle can be reverse-engineered with react-native-decompiler.)
  • React Native Debugger enabled โ€” is __DEV__ mode exposed in production? (Debugger allows arbitrary JS execution.)
  • Flipper / Metro bundler in production โ€” is react-native-flipper or Metro bundler enabled in release builds? (Exposes debugging endpoints.)
  • Android: Exported activities โ€” are Activitys exported without permission?
  • iOS: Keychain accessibility โ€” is react-native-keychain configured with accessControl: ACCESS_CONTROL.BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE?
  • Clipboard exposure โ€” is sensitive data (passwords, tokens) accessible via the system clipboard? (Other apps can read the clipboard on Android.)
  • Bundle ID / Package name spoofing โ€” does the app validate its own bundle identifier at runtime? (Without it, a malicious clone with the same bundle ID can steal keychain data.)

Fix: Secure storage (React Native)

// ๐Ÿšซ BAD:
import AsyncStorage from '@react-native-async-storage/async-storage';
await AsyncStorage.setItem('auth_token', token);

// โœ… GOOD:
import * as Keychain from 'react-native-keychain';

await Keychain.setInternetCredentials(
  'api.example.com', // server
  'user',            // username
  token,             // password (stores token securely)
  {
    accessControl: Keychain.ACCESS_CONTROL.BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE,
    accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY
  }
);

Fix: SSL pinning (React Native)

// ๐Ÿšซ BAD:
const response = await fetch('https://api.example.com/data');

// โœ… GOOD (with react-native-ssl-pinning):
import { fetch } from 'react-native-ssl-pinning';

const response = await fetch('https://api.example.com/data', {
  method: 'GET',
  sslPinning: {
    certs: ['certificate_name'] // bundled .cer files
  },
  timeoutInterval: 10000
});

Fix: Secure WebView configuration

// ๐Ÿšซ BAD:
<WebView
  source={{ uri: 'https://example.com' }}
  javaScriptEnabled={true}
  allowFileAccess={true}
/>

// โœ… GOOD:
<WebView
  source={{ uri: 'https://example.com' }}
  javaScriptEnabled={true}
  allowFileAccess={false}
  allowUniversalAccessFromFileURLs={false}
  allowFileAccessFromFileURLs={false}
  mixedContentMode="never"
  onMessage={(event) => {
    // Only accept messages if origin is trusted
    if (event.nativeEvent.url.startsWith('https://example.com')) {
      handleMessage(event.nativeEvent.data);
    }
  }}
/>

Fix: Android manifest hardening

<!-- AndroidManifest.xml -->
<application
    android:usesCleartextTraffic="false"
    android:allowBackup="false"
    android:networkSecurityConfig="@xml/network_security_config">

    <activity
        android:name=".MainActivity"
        android:exported="false"
        android:windowSoftInputMode="adjustResize">

        <!-- Deep links: use verified App Links -->
        <intent-filter android:autoVerify="true">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="https" android:host="app.example.com" />
        </intent-filter>
    </activity>
</application>

Fix: Remove debug logs in production

// At app entry point (index.ts)
if (!__DEV__) {
  global.console.log = () => {};
  global.console.warn = () => {};
  global.console.error = () => {};
  // Keep global.console.error for crash reporting if needed
}

9. Cloud & Infrastructure Security

Search:  Dockerfile, docker-compose, kubernetes, deploy, aws, gcp, azure, s3, bucket, iam, role, policy

9.1 Container Security (Docker / K8s)

  • Root user in container โ€” does Dockerfile use USER nobody or USER 1000? Running as root inside a container allows escape on container break-out.
  • Unpinned base images โ€” are base images pinned to a digest (alpine:latest@sha256:...) or a patch version? (FROM node:18 vs FROM node:18.17.1-slim)
  • Secrets in Dockerfile โ€” are ENV or ARG directives used for secrets? (They persist in image layers.)
  • .dockerignore missing โ€” is there a .dockerignore? Without it, .env and secrets may be copied into the image.
  • K8s: Pod security context โ€” do pods have runAsNonRoot: true, allowPrivilegeEscalation: false, readOnlyRootFilesystem: true?
  • K8s: RBAC over-permissive โ€” do service accounts have cluster-admin or wildcard resource access?
  • K8s: Secrets not encrypted โ€” are Secrets used without encryption at rest? (K8s Secrets are base64 only by default.)
  • K8s: No network policy โ€” is there a NetworkPolicy restricting pod-to-pod traffic? (Default is allow-all.)
  • K8s: Host network / host PID โ€” are pods using hostNetwork: true or hostPID: true? (Escapes container isolation.)

Fix: Secure Dockerfile

FROM node:18-slim@sha256:abc123def456

# Create non-root user
RUN groupadd -r appuser && useradd -r -g appuser appuser

WORKDIR /app
COPY --chown=appuser:appuser package*.json ./
RUN npm ci --only=production

COPY --chown=appuser:appuser . .
USER appuser

EXPOSE 3000
CMD ["node", "server.js"]
# .dockerignore
.env
.env.local
node_modules
.git
*.md
tests/

Fix: K8s pod security context

apiVersion: v1
kind: Pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 1000
  containers:
    - name: app
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]

9.2 Cloud Provider Configuration

  • S3 bucket public access โ€” are there any S3 buckets with public-read or public-read-write ACLs? (Data exposure.)
  • S3 bucket block public access โ€” is BlockPublicAccess enabled at account or bucket level?
  • IAM wildcard policies โ€” do IAM policies use "Effect": "Allow", "Action": "*" or "Resource": "*" unnecessarily?
  • IAM keys not rotated โ€” are there IAM access keys older than 90 days?
  • Cloud storage bucket encryption โ€” is server-side encryption (SSE-S3, SSE-KMS) enabled on storage buckets?
  • Cloud function public invocation โ€” are cloud functions (AWS Lambda, GCP Cloud Functions) invocable without authentication?
  • Managed DB publicly accessible โ€” are RDS, Cloud SQL, or Cosmos DB instances publicly accessible with a password alone?
  • Security group / firewall rules โ€” are there security group rules with 0.0.0.0/0 for SSH (22), RDP (3389), or database ports?
  • TLS termination โ€” is TLS terminated at the load balancer with a valid certificate, or are backends handling raw HTTP?
  • CloudTrail / Audit Logs โ€” is CloudTrail (AWS), Audit Logs (GCP), or equivalent enabled for the account?
  • Default VPC โ€” is the default VPC in use with open egress? Should use a custom VPC with restricted egress.

Fix: S3 bucket hardening

# Terraform: Block public access
resource "aws_s3_bucket_public_access_block" "example" {
  bucket                  = aws_s3_bucket.example.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

# IAM least privilege
resource "aws_iam_policy" "restricted" {
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect   = "Allow"
      Action   = ["s3:GetObject", "s3:ListBucket"]
      Resource = ["arn:aws:s3:::example-bucket/*",
                  "arn:aws:s3:::example-bucket"]
      Condition = {
        IpAddress = { "aws:SourceIp" = ["203.0.113.0/24"] }
      }
    }]
  })
}

10. GraphQL Security

Search:  graphql, GraphQL, Apollo, graphql-yoga, strawberry, ariadne, type-graphql, @Resolver
  • Introspection enabled in production โ€” is introspection: true or GraphiQL enabled in production? (Exposes full schema, queries, mutations, and types.)
  • No query depth limiting โ€” can an attacker craft deeply nested queries? (e.g., user โ†’ friends โ†’ user โ†’ friends โ†’ ...) Crashes the server with exponential queries.
  • No query cost / complexity analysis โ€” is there no cost limit per query? Attackers can request thousands of nodes in a single request (DoS).
  • No rate limiting per operation โ€” is there a rate limiter that covers GraphQL endpoints? (Most rate limiters count HTTP requests, not query cost โ€” a single request can contain an expensive query.)
  • Auth missing per resolver โ€” is authentication applied globally instead of per resolver/resource? (A user may access another user's data through a field resolver.)
  • Batching / alias attacks โ€” can an attacker use aliases to run the same expensive query hundreds of times in one request? (query { a1: users, a2: users, ..., a100: users })
  • N+1 query exposure โ€” are resolvers making N+1 database calls without DataLoader? (Performance issue that can be exploited as DoS.)
  • Field-level access control โ€” are sensitive fields (e.g., email, ssn, passwordHash) exposable without field-level authorization?
  • Mutation logging โ€” are sensitive mutations (e.g., deleteUser, updatePassword) logged for audit?
  • CSRF via GraphQL โ€” is there CSRF protection on the GraphQL endpoint? (Most GraphQL endpoints accept application/json โ€” not protected by standard CSRF tokens.)

Fix: Secure Apollo Server (Node.js)

import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import depthLimit from 'graphql-depth-limit';
import costAnalysis from 'graphql-cost-analysis';

const server = new ApolloServer({
  typeDefs,
  resolvers,
  validationRules: [
    depthLimit(7),                          // max nesting depth
    costAnalysis({
      maximumCost: 1000,
      defaultCost: 1,
      costMap: {
        Query: { users: 5, search: 20 }    // weight complex queries
      }
    })
  ],
  introspection: process.env.NODE_ENV !== 'production',
});

// Per-resolver auth
const resolvers = {
  Query: {
    user: async (_, { id }, { dataSources, userId }) => {
      if (!userId) throw new AuthenticationError('Not logged in');
      const user = await dataSources.users.getById(id);
      if (user.id !== userId && !user.isAdmin(userId)) {
        throw new ForbiddenError('Not authorized');
      }
      return user;
    }
  }
};

Fix: GraphQL rate limiting

import { createRateLimitRule } from 'graphql-rate-limit';
import { shield } from 'graphql-shield';

const rateLimitRule = createRateLimitRule({
  identifyContext: (ctx) => ctx.ip
});

const permissions = shield({
  Query: {
    users: rateLimitRule({ window: '1s', max: 5 }),
    search: rateLimitRule({ window: '10s', max: 2 })
  },
  Mutation: {
    login: rateLimitRule({ window: '15m', max: 10 })
  }
});

11. WebSocket Security

Search:  WebSocket, websocket, ws://, wss://, io(), socket.io, WebSocketServer, on('connection')
  • No origin validation โ€” does the WebSocket server validate the Origin header on upgrade? (Without it, any website can open a socket to your server.)
  • No authentication on connect โ€” does the WebSocket handshake verify a token (JWT, session cookie) before accepting the connection?
  • No message validation โ€” are incoming messages parsed without schema validation? (An attacker can send malformed messages to crash the server or trigger injection.)
  • No rate limiting per connection โ€” is there a message rate limiter per WebSocket connection? (Unlimited messages = DoS.)
  • No disconnection on idle โ€” are connections kept open indefinitely? (Resource exhaustion โ€” attackers can open thousands of connections.)
  • Replay attacks โ€” are messages idempotent or sequenced? (Without sequence numbers or monotonic IDs, an attacker can replay a "send money" message.)
  • No message size limit โ€” is there a maximum message size? (An attacker can send a single multi-GB message to crash the server.)
  • Broadcasting without authorization โ€” does the server broadcast messages to all connected clients without checking room/channel permissions?
  • TLS not enforced โ€” are WebSocket connections using wss:// in production? (ws:// sends all data in plaintext, including any auth tokens in the handshake.)
  • No subprotocol validation โ€” does the server accept any subprotocol without verification? (Can confuse the server's message parser.)

Fix: Secure WebSocket server (Node.js)

import { WebSocketServer } from 'ws';
import { verify } from 'jsonwebtoken';
import { rateLimit } from 'express-rate-limit';

const wss = new WebSocketServer({
  port: 8080,
  // Verify the origin
  verifyClient: (info, cb) => {
    const origin = info.origin || info.req.headers.origin;
    const allowedOrigins = ['https://app.example.com'];
    cb(allowedOrigins.includes(origin));
  },
  maxPayload: 1024 * 100  // 100KB max message
});

wss.on('connection', (ws, req) => {
  // 1. Authenticate on connect
  const token = new URL(req.url, 'http://localhost').searchParams.get('token');
  if (!token) { ws.close(4001, 'Authentication required'); return; }

  let user;
  try {
    user = verify(token, process.env.JWT_SECRET);
  } catch { ws.close(4001, 'Invalid token'); return; }

  // 2. Per-connection rate limiter
  const messageCounts = new Map();
  const rateLimitWindow = 60000; // 1 minute
  const maxMessages = 60;

  const interval = setInterval(() => messageCounts.clear(), rateLimitWindow);

  ws.on('message', (data) => {
    const count = (messageCounts.get(user.id) || 0) + 1;
    messageCounts.set(user.id, count);
    if (count > maxMessages) {
      ws.close(4002, 'Rate limit exceeded');
      clearInterval(interval);
      return;
    }

    // 3. Validate message schema
    try {
      const msg = JSON.parse(data.toString());
      if (!msg.type || !msg.payload) {
        ws.send(JSON.stringify({ error: 'Invalid message format' }));
        return;
      }
      handleMessage(user, msg);
    } catch {
      ws.send(JSON.stringify({ error: 'Invalid JSON' }));
    }
  });

  // 4. Idle timeout
  ws.isAlive = true;
  ws.on('pong', () => { ws.isAlive = true; });

  const pingInterval = setInterval(() => {
    if (!ws.isAlive) { ws.terminate(); clearInterval(pingInterval); return; }
    ws.isAlive = false;
    ws.ping();
  }, 30000);

  ws.on('close', () => {
    clearInterval(interval);
    clearInterval(pingInterval);
  });
});

12. File Upload Security

Search:  upload, file, multipart, multer, formidable, UploadFile, FileField, req.file, blob
  • File type validation by extension only โ€” is file type checked by extension (file.endsWith('.pdf')) instead of magic bytes? (An attacker can rename malware.exe to resume.pdf.)
  • No file size limit โ€” is there no maximum file size? (An attacker can upload a multi-GB file to fill your disk.)
  • No virus scanning โ€” are uploads scanned for malware? (Users can upload infected files that then spread through your system.)
  • Path traversal in filename โ€” is the original filename used without sanitization? (../../../etc/passwd can overwrite system files.)
  • Files stored in web root โ€” are uploads saved inside the web root (e.g., public/uploads/)? (Attacker can access uploaded files directly via URL.)
  • No CDN / cloud storage โ€” are files stored on the application server's local disk instead of S3/GCS/Azure Blob? (Local storage = disk full = DoS.)
  • Zip bombs โ€” are archive files (zip, tar, gz) scanned for decompression bombs? (A small zip can expand to petabytes, crashing the server.)
  • SVG / HTML upload XSS โ€” are SVGs or HTML files allowed? (SVGs can contain <script> tags, leading to stored XSS.)
  • Filename collision โ€” are uploaded filenames predictable? (Without UUIDs in filenames, one user can overwrite another user's file.)
  • Exif data leakage โ€” are uploaded images stripped of EXIF metadata? (EXIF can contain GPS coordinates, device info, and author names.)

Fix: Secure file upload (Node.js + Multer + S3)

const multer = require('multer');
const { v4: uuidv4 } = require('uuid');
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
const { fromBuffer } = require('file-type');

const ALLOWED_MIME_TYPES = [
  'image/jpeg', 'image/png', 'image/webp',
  'application/pdf',
  'text/plain'
];
const MAX_SIZE = 10 * 1024 * 1024; // 10MB

const upload = multer({
  storage: multer.memoryStorage(),
  limits: { fileSize: MAX_SIZE },
  fileFilter: (req, file, cb) => {
    // Reject by extension fast
    const ext = file.originalname.split('.').pop()?.toLowerCase();
    if (!['jpg', 'jpeg', 'png', 'webp', 'pdf', 'txt'].includes(ext)) {
      cb(new Error('Invalid file extension'), false);
      return;
    }
    cb(null, true);
  }
});

app.post('/upload', upload.single('file'), async (req, res) => {
  // Check magic bytes (not just extension)
  const type = await fromBuffer(req.file.buffer);
  if (!type || !ALLOWED_MIME_TYPES.includes(type.mime)) {
    return res.status(400).json({ error: 'Invalid file type' });
  }

  // Sanitize filename โ€” never trust user input
  const safeName = `${uuidv4()}.${type.ext}`;

  // Stream directly to S3 (never local disk)
  const s3 = new S3Client({ region: 'us-east-1' });
  await s3.send(new PutObjectCommand({
    Bucket: 'uploads-bucket',
    Key: `uploads/${safeName}`,
    Body: req.file.buffer,
    ContentType: type.mime,
  }));

  // EXIF stripping โ€” use sharp for images
  if (type.mime.startsWith('image/')) {
    const sharp = require('sharp');
    const cleaned = await sharp(req.file.buffer)
      .withMetadata({ exif: false });  // strip EXIF
    // re-upload without EXIF
    await s3.send(new PutObjectCommand({
      Bucket: 'uploads-bucket',
      Key: `uploads/${safeName}`,
      Body: await cleaned.toBuffer(),
      ContentType: type.mime,
    }));
  }

  res.json({ url: `https://cdn.example.com/uploads/${safeName}` });
});

Fix: Archive / zip bomb protection

const yauzl = require('yauzl');
const MAX_UNCOMPRESSED_RATIO = 100; // 1:100 expansion max

function checkZipBomb(buffer) {
  return new Promise((resolve, reject) => {
    yauzl.fromBuffer(buffer, { lazyEntries: true }, (err, zipfile) => {
      if (err) return reject(err);
      let totalCompressed = 0;
      let totalUncompressed = 0;

      zipfile.readEntry();
      zipfile.on('entry', (entry) => {
        totalCompressed += entry.compressedSize;
        totalUncompressed += entry.uncompressedSize;
        if (totalUncompressed > totalCompressed * MAX_UNCOMPRESSED_RATIO) {
          return reject(new Error('Zip bomb detected'));
        }
        zipfile.readEntry();
      });
      zipfile.on('end', () => resolve(true));
    });
  });
}

13. Data Privacy & Compliance

Search:  pii, privacy, gdpr, ccpa, consent, cookie, personal, user data, email, phone, ssn, export, delete, retention
  • PII not classified โ€” is there no data classification layer marking fields as PII? (Without it, you can't audit or control PII exposure.)
  • Cookie consent missing โ€” is there a cookie consent banner for non-essential cookies? (GDPR requires opt-in for tracking cookies.)
  • No user data export โ€” can users export all their data? (GDPR "right of access" โ€” must be provided within 30 days.)
  • No user deletion / right to be forgotten โ€” can users delete their account and all associated data?
  • Data retention policy missing โ€” are logs, backups, and user data kept indefinitely? (GDPR requires data minimization.)
  • PII in URLs โ€” are user identifiers (email, user ID) in URL query params? (/[email protected] โ€” leaked in server logs, referrer headers.)
  • PII in logs โ€” are emails, IPs, or names logged verbatim? (Logs are often sent to third-party services.)
  • Encryption at rest missing โ€” is the database unencrypted at rest?
  • Backups unencrypted โ€” are database backups stored without encryption?
  • Third-party data sharing โ€” is user data shared with third-party services without disclosure in the privacy policy?
  • Consent not recorded โ€” is user consent for data processing stored as evidence? (GDPR requires proof of consent.)
  • Password in plaintext โ€” are passwords stored in plaintext or reversible encryption? (Flat violation of every privacy regulation.)

Fix: PII data layer + data export/delete

// PII field annotation
const PII_FIELDS = ['email', 'phone', 'ssn', 'dob', 'fullName', 'ipAddress'];

function redactPII(obj: Record<string, any>): Record<string, any> {
  const copy = { ...obj };
  for (const key of Object.keys(copy)) {
    if (PII_FIELDS.includes(key)) {
      copy[key] = '[REDACTED]';
    }
  }
  return copy;
}

// Data export endpoint
app.get('/api/user/data-export', authenticate, async (req, res) => {
  const user = await User.findById(req.userId)
    .populate('orders')
    .populate('messages')
    .populate('activityLog');

  const exportData = {
    profile: user.profile,
    orders: user.orders,
    messages: user.messages.map(redactPII),
    consentRecords: user.consentRecords,
    generatedAt: new Date().toISOString()
  };

  res.setHeader('Content-Type', 'application/json');
  res.setHeader('Content-Disposition', 'attachment; filename=user-data.json');
  res.json(exportData);
});

// Deletion endpoint
app.delete('/api/user', authenticate, async (req, res) => {
  const userId = req.userId;

  // Anonymize PII rather than delete if you need referential integrity
  await User.findByIdAndUpdate(userId, {
    $set: {
      email: `deleted-${userId}@example.com`,
      fullName: '[DELETED]',
      phone: null,
      profilePicture: null,
    },
    $unset: { passwordHash: '', ssn: '' }
  });

  // Delete dependent data
  await Promise.all([
    Session.deleteMany({ userId }),
    ActivityLog.deleteMany({ userId }),
    ConsentRecord.deleteMany({ userId }),
  ]);

  // Log the deletion
  console.log(`User ${userId} deleted at ${new Date().toISOString()}`);

  res.json({ message: 'Account deleted' });
});

14. Cryptography & Key Management

Search:  crypto, cipher, encrypt, decrypt, hash, createHash, createCipheriv, createDecipheriv, MD5, SHA1, RSA, AES, GCM, CBC, ECB
  • Weak hashing algorithm โ€” is MD5 or SHA-1 used for security contexts? (Password hashing, signatures, integrity checks.)
  • ECB mode encryption โ€” is AES-ECB used? (Deterministic โ€” identical plaintext blocks produce identical ciphertext.)
  • Static IV / nonce โ€” is the IV for AES-CBC or nonce for AES-GCM static or reused? (Reused nonce destroys GCM security.)
  • No key rotation โ€” are encryption keys never rotated? (Compromise of a static key exposes all data ever encrypted.)
  • Keys in source code โ€” are encryption keys, certificates, or passwords in source files?
  • Weak RSA key size โ€” is RSA key size < 2048 bits?
  • Weak PRNG โ€” is Math.random() used instead of crypto.randomBytes() or SecureRandom for any security-sensitive operation?
  • Hardcoded certificates โ€” are TLS certificates and private keys in the repo or Docker image?
  • No PBKDF2 / bcrypt / argon2 โ€” is a fast hash (SHA-256, MD5) used for password storage instead of a slow KDF?
  • JWT algorithm confusion โ€” is the server vulnerable to algorithm confusion? (Accepting both symmetric HS256 and asymmetric RS256 tokens with the same secret.)
  • Legacy protocols โ€” is SSLv3, TLS 1.0, or TLS 1.1 allowed?
  • Self-signed certificates in production โ€” are self-signed certs used instead of a trusted CA?

Fix: Modern crypto practices

// โœ… BCRYPT for passwords
const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12);  // cost factor 12

// โœ… AES-256-GCM with random IV
const crypto = require('crypto');
function encrypt(text, key) {
  const iv = crypto.randomBytes(16);     // NEVER reuse IV
  const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
  let encrypted = cipher.update(text, 'utf8', 'hex');
  encrypted += cipher.final('hex');
  const authTag = cipher.getAuthTag().toString('hex');
  return { encrypted, iv: iv.toString('hex'), authTag };
}

// โœ… Key rotation support
const keyRing = [
  { id: 'v2', key: process.env.ENCRYPTION_KEY_V2, active: true },
  { id: 'v1', key: process.env.ENCRYPTION_KEY_V1, active: false },
];

function encryptWithKeyRing(text) {
  const active = keyRing.find(k => k.active);
  const { encrypted, iv, authTag } = encrypt(text, active.key);
  return `{key:${active.id},iv:${iv},tag:${authTag}}${encrypted}`;
}

function decryptFromKeyRing(encoded) {
  const match = encoded.match(/^\{key:(\w+),iv:(\w+),tag:(\w+)\}(.+)$/);
  if (!match) throw new Error('Invalid format');
  const [_, keyId, iv, authTag, encrypted] = match;
  const keyEntry = keyRing.find(k => k.id === keyId);
  if (!keyEntry) throw new Error('Unknown key ID');
  const decipher = crypto.createDecipheriv('aes-256-gcm', keyEntry.key, Buffer.from(iv, 'hex'));
  decipher.setAuthTag(Buffer.from(authTag, 'hex'));
  let decrypted = decipher.update(encrypted, 'hex', 'utf8');
  decrypted += decipher.final('utf8');
  return decrypted;
}

15. CI/CD & Supply Chain Security

Search:  .github/workflows, .gitlab-ci.yml, Jenkinsfile, Dockerfile, Makefile, npm install, pip install, go get
  • Secrets in CI logs โ€” are secrets (env vars, keys) printed in CI output or available to forked PRs? (GitHub: are secrets masked in logs? GitLab: are protected variables used?)
  • No dependency lock files โ€” is there no package-lock.json, yarn.lock, requirements.txt with pinned hashes? (Without locks, builds are non-deterministic โ€” a compromised dependency version can be pushed without notice.)
  • Subresource Integrity (SRI) missing โ€” are CDN-loaded scripts missing integrity hashes? (<script src="https://cdn.example.com/lib.js"> without integrity="sha384-...".)
  • Dependency confusion โ€” does the package manager combine public and private registries without scoping? (@scope/package vs unscoped private packages that match public package names.)
  • Typosquatting risk โ€” are there any dependencies that are typo-squats of popular packages? (e.g., cors instead of cors, bcrypt instead of bcryptjs.)
  • Unsigned commits โ€” are commits signed with GPG or SSH? (Unsigned commits can be authored by anyone.)
  • No SBOM โ€” is there no Software Bill of Materials generated? (Without it, you can't audit third-party vulnerabilities comprehensively.)
  • CI pipeline self-modification โ€” can the CI pipeline (e.g., .github/workflows/) be modified by a PR before it runs? (Token theft โ€” a PR can modify CI to exfiltrate secrets.)
  • Artifact integrity / signing โ€” are build artifacts signed and checksummed? (Without it, artifacts can be replaced between build and deploy.)
  • No least privilege CI โ€” do CI workflows use tokens with more permissions than needed? (e.g., contents: write on a PR workflow that only needs contents: read.)
  • No container image scanning โ€” are Docker images scanned for vulnerabilities before deployment?

Fix: Secure CI pipeline (GitHub Actions)

name: CI/CD Pipeline
on: [pull_request]

# Least-privilege permissions
permissions:
  contents: read
  checks: write
  pull-requests: read

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Dependency lockfile check
      - name: Verify lockfile
        run: |
          if [ ! -f package-lock.json ] && [ ! -f yarn.lock ]; then
            echo "No lockfile found โ€” builds are non-deterministic!"
            exit 1
          fi

      # Dependency audit
      - name: Audit
        run: npm audit --audit-level=high

      # SAST
      - name: Semgrep
        uses: semgrep/semgrep-action@v1
        with:
          config: p/default

      # Secrets scan
      - name: Gitleaks
        uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      # SBOM
      - name: Generate SBOM
        uses: cyclonedx/gha-generate-sbom@v1

Fix: Dependency confusion protection

# npm: scope all private packages
npm init --scope=@mycompany

# .npmrc
@mycompany:registry=https://npm.mycompany.com
registry=https://registry.npmjs.org/

# pip: index-url isolation
# requirements.txt with hashes
pip install --require-hashes -r requirements.txt

# Docker: pin base images by digest
FROM node:18-slim@sha256:abc123def456...

16. Logging & Monitoring Security

Search:  log, logger, debug, info, warn, error, audit, auditLog, activityLog, winston, pino, log4j, sentry, datadog
  • Log injection โ€” are log messages constructed with user input without sanitization? (Log4j CVE-2021-44228-style โ€” an attacker can inject ${env:AWS_SECRET_KEY} into a log message and exfiltrate secrets via the logging framework.)
  • PII in logs โ€” are emails, IPs, passwords, or request/response bodies logged verbatim? (GDPR violation โ€” logs become a data breach liability.)
  • No audit trail โ€” are sensitive operations (user deletion, role changes, payment actions) not logged?
  • No alerting โ€” are there no alerts for: repeated 401/403 errors, unusual traffic spikes, logins from new geographies?
  • Logs stored indefinitely โ€” are logs kept without a retention policy? (Storage cost + data breach liability.)
  • Sensitive data in error reports โ€” do error reporting services (Sentry, DataDog, Rollbar) capture request bodies or environment variables?
  • No structured logging โ€” are logs unstructured strings (harder to search, SIEM can't parse them)?
  • Centralized logging without auth โ€” is the log aggregation service (Kibana, Grafana Loki) accessible without authentication?
  • No monitoring for known attack patterns โ€” is there no WAF or IDS/IPS monitoring for SQLi, XSS, path traversal patterns?
  • Health check endpoints leak info โ€” do /health, /ready, or /metrics endpoints expose internal state, versions, or configuration?

Fix: Secure logging (Winston)

const winston = require('winston');

const PII_PATTERNS = [
  /\b[\w\.-]+@[\w\.-]+\.\w{2,}\b/g,  // email
  /\b\d{3}-\d{2}-\d{4}\b/g,          // SSN
  /\b(?:\d{4}[ -]?){4}\b/g,          // credit card
];

function sanitize(data) {
  let str = typeof data === 'string' ? data : JSON.stringify(data);
  for (const pattern of PII_PATTERNS) {
    str = str.replace(pattern, '[REDACTED]');
  }
  return str;
}

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json(),
    winston.format((info) => {
      // Never log request bodies on auth routes
      if (info.req?.url?.includes('/login') || info.req?.url?.includes('/reset')) {
        delete info.req.body;
      }
      // Sanitize any PII in the message
      info.message = sanitize(info.message);
      return info;
    })()
  ),
  transports: [
    new winston.transports.File({
      filename: 'logs/audit.log',
      maxsize: 10 * 1024 * 1024, // 10MB per file
      maxFiles: 10,               // keep 10 rotated files
    })
  ]
});

// Audit log middleware
function auditLog(req, res, next) {
  const start = Date.now();
  res.on('finish', () => {
    if (res.statusCode >= 400) {
      logger.warn({
        event: 'request',
        method: req.method,
        path: req.path,
        status: res.statusCode,
        duration: Date.now() - start,
        ip: req.ip,
        userId: req.user?.id || 'anonymous'
      });
    }
  });
  next();
}

Fix: Log injection prevention

// ๐Ÿšซ BAD: direct interpolation
logger.info(`User ${req.body.email} logged in`);

// โœ… GOOD: structured fields
logger.info('User login', {
  event: 'login',
  userId: user.id,
  ip: req.ip,
  timestamp: new Date().toISOString()
});

// โœ… GOOD: sanitize user input if you must include it
logger.info(`Failed login for ${sanitize(req.body.email)}`);

1. Authentication & Session Management

1.1 Login Endpoint

Search:  /login, /signin, /auth, authenticate, passport.authenticate
  • Rate limiting โ€” is there a rate limiter on the login route? (express-rate-limit, flask-limiter, django-ratelimit, etc.)
  • Account lockout โ€” are failed attempts tracked? Is there a lockout threshold + cooldown?
  • Brute-force protection โ€” exponential backoff, CAPTCHA after N failures, or similar.
  • Credential logging โ€” are passwords or raw credentials ever logged?
  • Password comparison โ€” is a constant-time comparison used? (crypto.timingSafeEqual, bcrypt.compare, hash_equals, etc.)
  • Error messages โ€” do login failures reveal whether the email or password was wrong? (must be generic: "Invalid credentials".)
  • Remember-me / persistent sessions โ€” if present, is the token securely generated and stored?
  • Username/email enumeration โ€” is the response identical in timing and content for existing vs non-existing accounts?

1.2 Session / Token Management

Search:  jwt, session, cookie, token, passport, express-session, connect-redis
  • JWT secret โ€” at least 256-bit (32+ random chars / env var)? Never hardcoded?
  • JWT expiration โ€” short exp claim (< 24h for access tokens)? Refresh tokens rotated?
  • JWT algorithm โ€” pinned to RS256 or HS256? alg header verified against an allowlist? (CVE-2015-9235 โ€” "none" algorithm.)
  • Session store โ€” server-side (Redis, DB)? httpOnly, secure, sameSite set on cookies?
  • Logout โ€” does logout invalidate the session/token server-side (not just client redirect)?
  • CSRF โ€” CSRF protection on state-changing endpoints? (csurf, double-submit cookie, SameSite=Strict/Lax.)
  • MFA / 2FA โ€” available? TOTP secret stored encrypted?

1.3 OAuth / Social Login

Search:  passport-google, passport-github, oauth, OAuth2Strategy, /auth/callback
  • State parameter โ€” cryptographically random state parameter used and verified in callback?
  • Redirect URI validation โ€” are redirect URIs whitelisted strictly?
  • Token leakage โ€” are access/refresh tokens from the provider ever logged or sent to the client?
  • Account linking โ€” if merging OAuth + email accounts, is there a verification step to prevent account takeover?
  • PKCE โ€” is PKCE (Proof Key for Code Exchange) used for public clients (mobile, SPA)? (Without PKCE, the authorization code can be intercepted.)

1.4 Magic Links & Email Login Links

Search:  magic-link, magiclink, sendSignInLink, signInWithEmailLink, actionHandler, verify, /verify-email, /confirm
  • Token generation โ€” is the magic link token generated with crypto.randomBytes (โ‰ฅ 32 bytes)? Not Math.random(), Date.now(), uuid.v4() alone?
  • Single-use โ€” is the link invalidated immediately after a successful login?
  • Expiry โ€” does the link expire in โ‰ค 15 minutes? (Magic links should be shorter-lived than password resets.)
  • Rate limiting โ€” is the "send magic link" endpoint rate-limited per email and per IP?
  • Enumeration protection โ€” does the endpoint return the same response whether or not the email exists?
  • Link injection in email body โ€” are magic link URLs properly escaped in email templates?
  • Deep-link hijacking โ€” are magic links restricted to the intended mobile app (Android App Links / iOS Universal Links) or does a custom URL scheme allow any app to intercept?
  • Replay prevention โ€” is the token checked against a server-side store, not just self-encoded in the JWT?
  • Cross-account reuse โ€” can user A use user B's magic link by modifying the email in the URL? (The token must be bound to the specific email/account.)

1.5 Login Timing Attack Protection

Search:  timingSafeEqual, constant-time, randomDelay, setTimeout(Math.random), bcrypt.compare, hash_equals, compareSync
  • Password comparison โ€” is a constant-time string comparison used? (crypto.timingSafeEqual in Node, hash_equals in PHP, hmac.compare_digest in Python, MessageDigest.isEqual in Java.)
    • Note: bcrypt.compare() / argon2.verify() are inherently constant-time.
  • User existence check โ€” when authenticating, is the user lookup followed by a constant-time credential comparison even if the user does not exist?
  • Forgot-password timing โ€” does the forgot-password endpoint use a constant-time lookup, or does it return immediately when the email is not found?
  • Random keystroke delay โ€” does the login endpoint add a stochastic delay (setTimeout(() => next(), 50 + Math.random() * 150))?
  • Response padding โ€” is the response body padded to a fixed length?
  • Login link timing โ€” does the magic-link / reset-link endpoint always sleep a minimum amount of time?

Fix: Add random delay to login endpoint

function timingSafeLogin(handler) {
  return async (req, res, next) => {
    const delay = 50 + Math.random() * 150; // 50โ€“200ms jitter
    await new Promise(r => setTimeout(r, delay));
    return handler(req, res, next);
  };
}
app.post('/login', rateLimiter, timingSafeLogin(loginHandler));

Fix: Constant-time comparison (Node.js)

// ๐Ÿšซ BAD:
if (user.password === inputPassword) { ... }

// โœ… GOOD:
if (crypto.timingSafeEqual(
  Buffer.from(user.password),
  Buffer.from(inputPassword)
)) { ... }

2. Password Reset Flow

Search:  reset, forgot-password, forgot_password, /reset-password, /forgot-password, token, resetToken

2.1 Token Generation

Search:  crypto.randomBytes, uuid, nanoid, token, secret, resetToken
  • Cryptographic randomness โ€” generated with crypto.randomBytes (or equivalent)? Not Math.random(), Date.now(), uuid() alone.
  • Token length โ€” โ‰ฅ 128 bits (โ‰ฅ 16 bytes / โ‰ฅ 32 hex chars)?
  • Token encoding โ€” URL-safe (base64url, hex)?

Fix: Secure token generation

const crypto = require('crypto');
const token = crypto.randomBytes(32).toString('hex');

2.2 Token Storage & Expiry

Search:  save, store, update, expiresIn, expiresAt, createdAt, tokenHash, bcrypt
  • Hashed in DB โ€” stored as a hash (sha256, bcrypt), not plaintext?
  • Expiry โ€” expires in โ‰ค 1 hour? Enforced server-side?
  • Single-use โ€” invalidated immediately after successful password change?
  • Invalidation on demand โ€” can a user invalidate all outstanding tokens by requesting a new one?

Fix: Hash token before storage

const tokenHash = crypto.createHash('sha256').update(token).digest('hex');
db.resetTokens.insertOne({ tokenHash, userId, expiresAt });

2.3 Enumeration Protection

  • Response consistency โ€” same status + body whether email exists or not?
  • Timing โ€” constant-time user lookup?
  • Rate limiting โ€” rate-limited per IP and/or per email?

Fix: Generic response + random delay

app.post('/forgot-password', async (req, res) => {
  res.status(200).json({ message: 'If that email exists, a reset link has been sent.' });
  const delay = 100 + Math.random() * 200;
  setTimeout(async () => {
    const user = await User.findOne({ email: req.body.email });
    if (user) {
      const token = crypto.randomBytes(32).toString('hex');
      await sendResetEmail(email, token);
    }
  }, delay);
});

2.4 Password Strength

Search:  password.length, minLength, validate, strength, zxcvbn, validator
  • Minimum length โ€” โ‰ฅ 8 characters (recommended โ‰ฅ 12)?
  • Strength check โ€” zxcvbn, haveibeenpwned API, or similar?
  • Confirmation โ€” two matching fields required?
  • Hashing โ€” hashed with bcrypt (โ‰ฅ 10 rounds) or argon2?

3. Connector Security

Search:  connector, webhook, apiKey, api_key, API_KEY, secretKey, clientSecret, database, mongoose, redis, stripe, sendgrid, twilio, slack, discord, webhookUrl

3.1 API Keys & Secrets

  • Environment variables โ€” all API keys, secrets, tokens from env vars?
  • Hardcoded keys โ€” any keys in source files? (Also check mobile: .env files in React Native, pubspec.yaml env vars.)
  • .env files โ€” is .env in .gitignore? Any .env files committed?
  • Key rotation โ€” mechanism to rotate keys without downtime?
  • Least privilege โ€” keys have minimum necessary scopes?
  • Mobile: Client-side secrets โ€” are API keys that MUST be secret present in mobile app code? (Mobile apps cannot hide secrets โ€” they must use a BFF / proxy layer.)

3.2 Webhooks

Search:  webhook, /webhook, stripe.webhooks, signature, secret
  • Signature verification โ€” payload signature verified (Stripe constructEvent, GitHub HMAC, etc.)?
  • Secret โ€” webhook signing secret stored securely (env var)?
  • Replay protection โ€” timestamp + tolerance window?
  • Idempotency โ€” handlers idempotent (process each event exactly once)?

Fix: Webhook signature verification (Node.js)

app.post('/stripe-webhook', (req, res) => {
  const sig = req.headers['stripe-signature'];
  const event = stripe.webhooks.constructEvent(
    req.body, sig, process.env.STRIPE_WEBHOOK_SECRET
  );
});

3.3 Database Connections

Search:  mongoose.connect, createConnection, Pool, sequelize, prisma, typeorm, redis.createClient
  • Connection string โ€” in env var? Contains credentials? Ever logged?
  • SSL/TLS โ€” TLS in production?
  • Query injection โ€” raw queries parameterized? Any $where, $eval, raw SQL fragments?
  • Connection pool โ€” pool size appropriate?

3.4 Third-party SDKs

Search:  stripe, sendgrid, twilio, openai, aws-sdk, @aws-sdk, google-cloud, firebase
  • Error handling โ€” errors caught and sanitized (no raw error objects to client)?
  • Secret exposure โ€” secrets from env vars, scoped correctly?

4. API & Input Handling

4.1 Injection Attacks

Search:  exec, eval, $where, $eval, dangerouslySetInnerHTML, innerHTML, serialize, JSON.parse, eval(), Function(, child_process
  • SQL/NoSQL injection โ€” all queries parameterized or using ORM with safe defaults? Watch $where in MongoDB, raw SQL in query(), template strings in queries.
  • Command injection โ€” child_process.exec / subprocess.run(shell=True) / os.system with user input?
  • SSRF โ€” does the app fetch URLs based on user input? Host allowlist?
  • XXE โ€” XML parsing with external entities disabled?
  • Template injection (SSTI) โ€” is render_template_string (Flask/Jinja2), render inline: (Rails), or {!! !!} (Blade) used with user input?

Fix: Parameterized queries

// ๐Ÿšซ BAD:
db.query(`SELECT * FROM users WHERE id = '${req.params.id}'`);
// โœ… GOOD:
db.query('SELECT * FROM users WHERE id = $1', [req.params.id]);

4.2 Input Validation

Search:  body, req.body, request.body, params, query, validator, Joi, zod, yup, express-validator, class-validator
  • Schema validation โ€” all inputs validated against a schema (Joi, Zod, Yup, Pydantic, etc.)?
  • Type coercion โ€” input types enforced (string, number, boolean)?
  • Allowlist approach โ€” deny-by-default (allowlist) rather than blocklist?
  • File uploads โ€” file type via magic bytes, size limit, virus scan? Stored outside web root?

4.3 CORS

  • Restrictive origin โ€” specific origin allowlist, not * in production?
  • Credentials โ€” if credentials: true, origins explicitly listed?
  • Pre-flight โ€” OPTIONS requests handled correctly?

4.4 Rate Limiting

Search:  rate-limit, RateLimiter, rateLimit, limiter, express-rate-limit, flask-limiter, throttle
  • Global limiter โ€” global rate limiter in place?
  • Per-route โ€” sensitive routes (login, register, reset-password, API) individually limited?
  • Per-IP โ€” rate limiting per-IP (or per-user for authenticated routes)?

4.5 HTTP Security Headers

Search:  helmet, security-headers, Content-Security-Policy, Strict-Transport-Security, X-Frame-Options, X-Content-Type-Options
  • Helmet / equivalent โ€” Helmet (Node), Talisman (Flask), Django SecurityMiddleware, or equivalent applied?
  • CSP โ€” Content-Security-Policy header set?
  • HSTS โ€” Strict-Transport-Security set for production?
  • X-Frame-Options โ€” clickjacking protection (DENY or SAMEORIGIN)?
  • X-Content-Type-Options โ€” nosniff set?

5. Secrets & Configuration

5.1 Env File Exposure

Search:  .env, .env.example, .env.local, .env.production, google-services.json, GoogleService-Info.plist
  • Gitignore โ€” is .env in .gitignore? Any .env* files committed?
  • Example env โ€” does .env.example exist with placeholder values (no real secrets)?
  • Fallback defaults โ€” hardcoded fallback defaults for secrets?
  • Mobile config files โ€” are google-services.json, GoogleService-Info.plist, or Firebase configs committed with unrestricted API keys?

5.2 Secrets in Source

Search:  secret, password, passwd, pwd, token, apiKey, api_key, private_key, privateKey, -----BEGIN
  • Hardcoded secrets โ€” regex for ['\"][A-Za-z0-9_\-]{32,}['\"] and -----BEGIN.*PRIVATE KEY-----.
  • Comments โ€” secrets in code comments or TODO strings?
  • Commit history โ€” scan .git/config and recent commits (read-only โ€” flag, don't rewrite).

5.3 Logging

Search:  console.log, logger.info, logger.debug, log.debug, log.info, debugPrint, print(
  • Credential logging โ€” request bodies logged on auth routes?
  • Token logging โ€” JWT tokens, reset tokens, or session IDs logged?
  • Error detail โ€” error responses include stack traces, DB dumps, or internal paths?

Fix: Sanitize error responses

app.use((err, req, res, next) => {
  console.error(err.stack);  // log server-side only
  res.status(500).json({ error: 'Internal server error' });
});

6. Dependencies & Infrastructure

6.1 Outdated Packages

Search:  package.json, requirements.txt, go.mod, Cargo.toml, Gemfile, composer.json, pubspec.yaml
  • Known vulnerabilities โ€” would npm audit, pip audit, go audit, mvn dependency-check, composer audit, flutter pub outdated surface critical vulns?
  • Deprecated packages โ€” any dependencies unmaintained or deprecated?
  • Unnecessary packages โ€” dev/test packages in production deps?

6.2 Transport Security

  • HTTPS enforcement โ€” HTTP โ†’ HTTPS redirect?
  • TLS version โ€” TLS 1.2+ enforced (not SSLv3, TLS 1.0, TLS 1.1)?

6.3 Error Handling

  • Global error handler โ€” prevents stack traces reaching client?
  • Catch-all 404 โ€” prevents path enumeration?
  • Unhandled rejections โ€” process.on('unhandledRejection') or equivalent?

Interactive Fix Workflow

Mode 2 โ€” Interactive

For each finding:

  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
  โ”‚ [C-1] Flutter API key hardcoded in Dart source              โ”‚
  โ”‚ File: lib/services/api.dart:8                                โ”‚
  โ”‚ Severity: ๐Ÿ”ด Critical                                       โ”‚
  โ”‚                                                              โ”‚
  โ”‚   final apiKey = 'AIzaSy...';                               โ”‚
  โ”‚                                                              โ”‚
  โ”‚ Fix: Move to .env + flutter_dotenv                          โ”‚
  โ”‚                                                              โ”‚
  โ”‚ Fix this? (y/n/skip-all/skip-severity)                       โ”‚
  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

  - y          โ†’ apply fix immediately
  - n          โ†’ skip, document in report
  - skip-all   โ†’ skip all remaining (proceed to report)
  - skip-{sev} โ†’ skip all remaining of this severity

Mode 3 โ€” Auto-fix all

  Found: 3 Critical, 5 High, 2 Medium, 1 Low

  Apply all fixes? (y/n)
  Show detailed diff first? (y/n)

Report Generation

Write the report to a timestamped file in the project's cicada/ directory.
This keeps audit history โ€” every run produces a new file.

Output path

cicada/report-YYYY-MM-DD-HHMMSS.md

The LLM should:

  1. Create cicada/ directory if it doesn't exist (never create the user's project root inside cicada/)
  2. Write the report using a timestamp in the filename
  3. If mode 2 or 3 fixed issues, append -fixed suffix: cicada/report-2026-06-29-143022-fixed.md
  4. Maintain a cicada/latest.md symlink that always points to the most recent report (ln -sf)

Template

# ๐Ÿ” Security Audit Report โ€” `<Project Name>`

<div align="center">

**Audit date:** YYYY-MM-DD HH:MM:SS  
**Audit mode:** Report only / Interactive fix / Auto-fix all  
**Framework(s) detected:** Node.js/Express, Flutter, Docker  
**Domains checked:** 16 / 16  
**Method:** Static code analysis (no runtime testing)  

</div>

---

## ๐Ÿ“‹ Executive Summary

| Severity | Count | Fixed | Critical examples |
|----------|-------|-------|-------------------|
| ๐Ÿ”ด **Critical** | 0 | 0 | Hardcoded secrets, SQLi, command injection, weak crypto |
| ๐ŸŸ  **High** | 0 | 0 | Missing rate limiting, plaintext tokens, wildcard CORS |
| ๐ŸŸก **Medium** | 0 | 0 | No CSP, verbose errors, no CSRF |
| ๐Ÿ”ต **Low** | 0 | 0 | No HSTS, no MFA, unsigned commits |
| โšช **Info** | 0 | โ€” | Architecture notes |

---

## ๐Ÿ”ด Critical Findings

### [C-1] Title
| Field | Value |
|-------|-------|
| **File** | `path/to/file.ts:42` |
| **Domain** | Secrets & Configuration |
| **Status** | ๐Ÿ”ด Unfixed / โœ… Fixed |
| **CWE** | CWE-312 โ€” Cleartext Storage of Sensitive Information |
| **Description** | What the issue is and why it matters. |
| **Impact** | An attacker with repo access can... |
| **Evidence** | ```\n// vulnerable code\n``` |
| **Fix applied** | ```\n// fixed code (if mode 2/3)\n``` |

### [C-2] ...

---

## ๐ŸŸ  High Findings

### [H-1] ...

---

## ๐ŸŸก Medium Findings

### [M-1] ...

---

## ๐Ÿ”ต Low Findings

### [L-1] ...

---

## โšช Informational

| ID | Observation |
|----|-------------|
| I-1 | Architecture note. |

---

## โœ… Verified Secure

| Check | Status |
|-------|--------|
| Firebase token verification (verifyIdToken) | โœ… Proper |
| .env in .gitignore | โœ… Excluded |
| Password hashing (bcrypt โ‰ฅ 10) | โœ… Proper |

---

> **Report path:** `cicada/report-YYYY-MM-DD-HHMMSS.md`  
> **Generated by:** Cicada Security Audit Skill โ€” https://github.com/Synthrun/Cicada

Severity Rubric

SeverityLabelDefinitionSLA
๐Ÿ”ด CriticalMust fixDirect, exploitable vulnerability (RCE, SQLi, account takeover, secrets leak).< 24 hours
๐ŸŸ  HighShould fixExploitable under realistic conditions (SSRF, weak crypto, missing rate limiting, timing leaks).Current sprint
๐ŸŸก MediumGood to fixWeakens security posture (missing CSP, verbose errors, no CSRF).Next sprint
๐Ÿ”ต LowNice to fixBest-practice deviation (no HSTS, no MFA, session timeout too long).When convenient
โšช InfoNoteObservation, architecture choice.โ€”

Meta-Instructions

  1. Detect first โ€” auto-detect all frameworks before running checks. Run checks for every detected framework.
  2. Mode first โ€” Always ask the user which mode before doing anything.
  3. Do not change code in report-only mode. Read-only. No exceptions.
  4. Be thorough. If unsure, flag with lower severity and a note.
  5. Cite file:line for every finding (path/file.ext:123).
  6. Include evidence โ€” show the vulnerable snippet in the report.
  7. Prioritize accuracy over speed. Triple-check before reporting.
  8. Ignore generated/test dirs unless they contain production config.
  9. Absence is a finding. If a protection is missing, state: "No rate limiter found."
  10. Fix responsibly โ€” read the file first, then edit with precise oldString/newString. Never overwrite a file without reading it.
  11. Track fixes โ€” after each fix, verify the change is correct by reading the modified lines.
  12. Mobile sensitivity โ€” for Flutter/React Native, prioritize: (1) API keys in source, (2) insecure local storage, (3) missing SSL pinning, (4) deep link hijacking.
  13. 16 domains โ€” run ALL applicable sections (1โ€“16). Skip sections only if framework detection confirms the technology is not used.
  14. Cloud/config awareness โ€” for cloud checks (section 9), flag missing IaC (Terraform, CloudFormation) as informational โ€” but flag hardcoded cloud secrets as critical.
  15. Supply chain checks โ€” always check for lockfiles and dependency confusion, even if CI/CD config is absent.
  16. Crypto audit โ€” when reviewing encryption code (section 14), test-verify: does the mode use an IV? Is it random? Is the key rotatable?
  17. Report output โ€” always write reports into cicada/ directory with timestamped filenames (cicada/report-2026-06-29-143022.md). Create cicada/ if it doesn't exist. Never dump raw report.md into the project root.

Quick Reference: Fix by Severity

SeverityFix this first
๐Ÿ”ด CriticalHardcoded secrets, SQL injection, command injection, weak reset tokens, JWT alg=none, ECB mode crypto, no SSL pinning, zip bombs, exposed S3 buckets, no WebSocket auth
๐ŸŸ  HighMissing rate limiting, plaintext reset tokens, wildcard CORS, missing webhook verification, no CSP, Log4j-style injection, no GraphQL depth limiting, cookie consent missing
๐ŸŸก MediumMissing CSRF, stack trace leaks, no HSTS, no file upload validation, no data retention policy, no audit trail, CI/CD secrets in logs
๐Ÿ”ต LowNo account lockout, long session timeout, no MFA, no SBOM, unsigned commits, no EXIF stripping

What ships with it: 11 files

97.7 KB alongside SKILL.md, 2 of them executable

docs/

templates/

Keep looking

Skills are one crate of 326,750. 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.