π 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
| Tool | Setup |
|---|---|
| OPENCODE | Place opencode.json + AGENTS.md in project root. Run /cicada. |
| CLAUDE | Place AGENTS.md in project root or .claude/. Run /cicada. |
| CODEX | Load SKILL.md directly: /load-skill /path/to/SKILL.md then run. |
| Cursor / Windsurf | Load 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.
| Option | What happens |
|---|---|
| 1 β Report only | Read-only audit. Generate report.md. No code changes. |
| 2 β Interactive fix | For each finding, ask: "Fix this? (y/n/skip all)". Generate report after. |
| 3 β Auto-fix all | Fix 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
| # | Domain | Key Focus |
|---|---|---|
| 1 | Auth & Session Mgmt | login, logout, JWT, OAuth, magic links, timing attacks |
| 2 | Password Reset Flow | token generation, expiry, enumeration protection |
| 3 | Connector Security | API keys, webhooks, DB connections, third-party SDKs |
| 4 | API & Input Handling | injection, rate limiting, CORS, validation, security headers |
| 5 | Secrets & Config | env vars, hardcoded secrets, .env exposure, logging |
| 6 | Dependencies & Infrastructure | outdated packages, HTTPS, TLS, error handling |
| 7 | Web Framework Security | Express, Next.js, NestJS, Django, Flask, FastAPI, Gin, Rails, Laravel, Spring Boot |
| 8 | Mobile App Security | Flutter, React Native β deep links, storage, SSL pinning, obfuscation |
| 9 | Cloud & Infrastructure | AWS/Azure/GCP configs, S3 buckets, IAM roles, Docker, K8s |
| 10 | GraphQL Security | introspection depth, query cost, auth per resolver, batching |
| 11 | WebSocket Security | origin validation, WS auth, message rate limiting, replay |
| 12 | File Upload Security | magic bytes, size limits, virus scan, path traversal, zip bombs |
| 13 | Data Privacy & Compliance | PII handling, GDPR/CCPA, encryption at rest, data retention |
| 14 | Cryptography & Key Mgmt | ciphers, key rotation, RNG, IVs, certificate lifecycle |
| 15 | CI/CD & Supply Chain | pipeline secrets, typosquatting, dep confusion, signed commits |
| 16 | Logging & Monitoring | audit logs, log injection, retention, alerting gaps |
Check Methodology
- Detect framework(s) used (see Framework Detection below).
- Search the codebase for relevant patterns (grep, glob).
- Read surrounding context (20β40 lines) to understand the implementation.
- Assess severity using the rubric at the end of this document.
- Log every finding β even low-severity β into an internal findings list.
- 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
| Framework | Files to read | Key imports / configs to search |
|---|---|---|
| Node.js / Express | package.json |
express, cors, helmet, express-rate-limit |
| Next.js | package.json, next.config.js, next.config.mjs |
next, next/server, middleware.ts |
| NestJS | package.json, nest-cli.json |
@nestjs/core, @nestjs/common, @UseGuards |
| Python / Django | requirements.txt, Pipfile, pyproject.toml, manage.py, settings.py |
django, SECRET_KEY, DEBUG |
| Python / Flask | requirements.txt, app.py, config.py |
flask, Flask(__name__), secret_key |
| Python / FastAPI | requirements.txt, main.py |
fastapi, FastAPI(), CORSMiddleware |
| Go / Gin | go.mod, main.go |
gin-gonic/gin, gin.Default() |
| Ruby / Rails | Gemfile, config/application.rb, config/secrets.yml |
rails, secret_key_base, config.force_ssl |
| PHP / Laravel | composer.json, .env, config/app.php |
laravel/framework, APP_KEY, APP_DEBUG |
| Java / Spring Boot | pom.xml, build.gradle, application.properties, application.yml |
spring-boot-starter-web, @SpringBootApplication |
| Flutter | pubspec.yaml, android/, ios/, lib/ |
flutter, flutter_secure_storage, http, webview_flutter |
| React Native | package.json, android/, ios/, app.json |
react-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-limitapplied 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, ...), orfor...inpatterns? - 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 from127.0.0.1. - Directory listing β is
express.staticconfigured withoutdotfiles: '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.tsprotect all sensitive routes? Check for missingmatcherconfig. - API route exposure β are internal API routes behind authentication middleware? Check
pages/api/orapp/api/for unprotected handlers. -
getServerSidePropsdata leakage β doesgetServerSidePropspass sensitive data (tokens, DB records) to the client without filtering? -
next/imageSSRF β are remote image URLs user-controllable without a host allowlist? (CVE-2023-34247) -
next.config.jsexposure β ispublicRuntimeConfigleaking secrets to the client bundle? - Incremental Static Regeneration (ISR) β are secret revalidation URLs predictable or unprotected?
- App Router:
useSearchParamsXSS β are search params rendered without sanitization in client components? -
next/scriptCSP bypass β are external scripts loaded withstrategy: '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-validatordecorators? (@IsEmail(),@IsString(),@MinLength(8)) - GraphQL introspection enabled in production β is
introspection: trueset inGraphQLModule.forRoot()? (Leaks entire schema.) -
@Serialize/ class-serializer exposure β does@Serializeexpose sensitive fields likepassword,ssn? - Rate limiting missing β is
@nestjs/throttlerconfigured globally? - CORS misconfigured β is
cors: true/origin: '*'inNestFactory.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_KEYhardcoded or committed β is the DjangoSECRET_KEYinsettings.pyinstead of an env var? -
DEBUG = Truein production β isDEBUGset toTruein production settings? (Leaks stack traces, settings, queries.) -
ALLOWED_HOSTSmisconfigured β 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()/safefilter XSS β ismark_safe()used on user input in templates? - CSRF middleware missing β is
CsrfViewMiddlewareinMIDDLEWAREsettings? - Session cookie config β are
SESSION_COOKIE_HTTPONLY,SESSION_COOKIE_SECURE,CSRF_COOKIE_SECUREset? - File upload validation β is
FILE_UPLOAD_MAX_MEMORY_SIZEset? Are uploaded file types validated? - Django REST Framework throttle β is
DEFAULT_THROTTLE_CLASSESconfigured for auth endpoints? - CORS headers β is
django-cors-headersconfigured with a specificCORS_ALLOWED_ORIGINS, notCORS_ALLOW_ALL_ORIGINS = True? - Admin panel exposure β is
django.contrib.adminaccessible 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_keyhardcoded β isapp.secret_keyset to a static string in source? -
debug=Truein production β doesapp.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-WTForflask-seasurfinstalled and enabled? - Session cookies β are
SESSION_COOKIE_HTTPONLY,SESSION_COOKIE_SECURE,SESSION_COOKIE_SAMESITEconfigured? - CORS wildcard β is
flask-corsconfigured withorigins='*'? - Rate limiting β is
flask-limiterapplied 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
CORSMiddlewareconfigured withallow_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_sizeonUploadFile? - Rate limiting β is
slowapiorfastapi-limiterconfigured? - OpenAPI / Swagger exposure β is
/docsor/redocexposed in production? (Leaks full API structure.) - Server info leakage β does
uvicornrun 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/corsconfigured withAllowAllOrigins: true? - Missing recovery middleware β is
gin.Recovery()included? (Without it, panics crash the server.) - No rate limiting β is
gin-limiteror similar applied to auth routes? - Raw SQL injection β are there
db.Query(fmt.Sprintf(...))calls with user input? - No
TrustedPlatformβ isgin.TrustedPlatformset 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.MaxMultipartMemoryandgin.MaxMultipartMemoryconfigured?
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_basehardcoded or weak β issecret_key_baseinconfig/secrets.ymlorcredentials.yml.encexposed? -
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_protectedbypass β are sensitive model attributes protected from mass assignment? - SQL injection via
where()strings β are thereModel.where("name = '#{params[:name]}'")calls? - Missing CSRF token β is
protect_from_forgery with: :exceptioninApplicationController? - 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,samesiteinconfig/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_KEYexposed β isAPP_KEYin.envcommitted to the repo? -
APP_DEBUG=truein production β is debug mode enabled? (Leaks full stack traces and env vars.) - Mass assignment β are Eloquent models missing
$fillableor 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
@csrfexcluded from forms? IsVerifyCsrfTokenmiddleware removed? - CORS misconfigured β is
laravel-corsset to'allowed_origins' => ['*']? - Rate limiting β is
throttlemiddleware 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-debugbarinstalled and visible? - Artisan console exposure β is
routes/console.phpexposing 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/heapdumpaccessible without authentication? (Leaks env vars β including AWS keys, DB passwords.) -
@CrossOrigin(origins = "*")β are any controllers using wildcard CORS? -
@PathVariableinjection β are path variables used in SQL queries without parameterization? - H2 console in production β is
spring.h2.console.enabled=trueset? (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=alwaysset? (Leaks internal paths and framework details.) - Unvalidated file uploads β is
spring.servlet.multipart.max-file-sizeunset or too large? - Spring Boot DevTools in production β is
spring-boot-devtoolson the classpath? (Remote restart and debug endpoints.) - Sensitive fields in JSON β are
@JsonIgnoreannotations missing onpassword,secret,tokenfields?
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
SharedPreferencesinstead offlutter_secure_storage? (SharedPreferences is plaintext on disk.) - No SSL pinning β is HTTP client created without certificate pinning? (
http.Client()vs pinneddioorhttp_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_flutterhavejavascriptMode: JavascriptMode.unrestricted? DoesJavaScriptChannelexpose sensitive native APIs? -
obscureText: falseon password fields β are passwordTextFields missingobscureText: true? - Sensitive logging β is
debugPrint()orprint()used for sensitive data? (Release builds can still have debug logging.) - Android: Allow cleartext traffic β is
android:usesCleartextTraffic="true"inAndroidManifest.xml? - iOS: ATS bypass β is
NSAllowsArbitraryLoads = trueinInfo.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
--obfuscateand--split-debug-info? (Without obfuscation, Dart code retains class/method names.) - Firebase config files β are
google-services.json(Android) orGoogleService-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/Keychainintegration (vialocal_auth+flutter_secure_storage)? - Android: Exported components β are
Activity,Service, orBroadcastReceiverexported without permission? (android:exported="true"without intent filters.) - iOS: Keychain accessibility β is
kSecAttrAccessibleset tokSecAttrAccessibleWhenUnlockedThisDeviceOnlyfor 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
.envor hardcoded β are API keys inreact-native-config.envfiles committed? Are they hardcoded in JS source? (JS bundle is unencrypted on device.) - AsyncStorage for sensitive data β is
AsyncStorageused for tokens, secrets, or PII? (AsyncStorage is unencrypted plaintext β usereact-native-keychainorexpo-secure-store.) - No SSL pinning β does
fetch()oraxiosconnect without certificate validation? (Usereact-native-ssl-pinningoraxioswithhttpsAgent.) - 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-webviewhaveallowFileAccess={true},allowUniversalAccessFromFileURLs={true}, orjavaScriptEnabled={true}without a content allowlist? -
secureTextEntry: falseon password fields β are passwordTextInputs missingsecureTextEntry={true}? -
console.login production β areconsole.log,console.warn,console.errorstatements present in production code? (They can leak data to logs accessible by other apps on device.) - Android: Allow cleartext traffic β is
android:usesCleartextTraffic="true"inAndroidManifest.xml? - iOS: ATS bypass β is
NSAllowsArbitraryLoads = trueinInfo.plist? - Firebase / Google Services β are
google-services.jsonorGoogleService-Info.plistcommitted 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-flipperor Metro bundler enabled in release builds? (Exposes debugging endpoints.) - Android: Exported activities β are
Activitys exported without permission? - iOS: Keychain accessibility β is
react-native-keychainconfigured withaccessControl: 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"
=> {
// 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
DockerfileuseUSER nobodyorUSER 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:18vsFROM node:18.17.1-slim) - Secrets in Dockerfile β are
ENVorARGdirectives used for secrets? (They persist in image layers.) -
.dockerignoremissing β is there a.dockerignore? Without it,.envand 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-adminor wildcard resource access? - K8s: Secrets not encrypted β are
Secretsused without encryption at rest? (K8s Secrets are base64 only by default.) - K8s: No network policy β is there a
NetworkPolicyrestricting pod-to-pod traffic? (Default is allow-all.) - K8s: Host network / host PID β are pods using
hostNetwork: trueorhostPID: 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-readorpublic-read-writeACLs? (Data exposure.) - S3 bucket block public access β is
BlockPublicAccessenabled 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/0for 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({
β¦(truncated)