ginskill-init 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -0
- package/agents/developer.md +56 -0
- package/agents/frontend-design.md +69 -0
- package/agents/mobile-reviewer.md +36 -0
- package/agents/review-code.md +49 -0
- package/agents/security-scanner.md +50 -0
- package/agents/tester.md +72 -0
- package/bin/cli.js +226 -0
- package/package.json +20 -0
- package/skills/ai-asset-generator/SKILL.md +255 -0
- package/skills/ai-asset-generator/docs/gen-image.md +274 -0
- package/skills/ai-asset-generator/docs/genvideo.md +341 -0
- package/skills/ai-asset-generator/docs/remove-background.md +19 -0
- package/skills/ai-asset-generator/generate-credit-assets.mjs +180 -0
- package/skills/ai-asset-generator/generate-ginbrowser-assets.mjs +242 -0
- package/skills/ai-asset-generator/generate-sty-icon.mjs +149 -0
- package/skills/ai-asset-generator/lib/bg-remove.mjs +34 -0
- package/skills/ai-asset-generator/lib/env.mjs +38 -0
- package/skills/ai-asset-generator/lib/kie-client.mjs +88 -0
- package/skills/ai-asset-generator/scripts/scaffold-generator.mjs +203 -0
- package/skills/ai-build-ai/SKILL.md +124 -0
- package/skills/ai-build-ai/docs/agent-teams.md +293 -0
- package/skills/ai-build-ai/docs/checkpointing.md +161 -0
- package/skills/ai-build-ai/docs/create-agent.md +399 -0
- package/skills/ai-build-ai/docs/create-mcp.md +395 -0
- package/skills/ai-build-ai/docs/create-skill.md +299 -0
- package/skills/ai-build-ai/docs/headless-mode.md +614 -0
- package/skills/ai-build-ai/docs/hooks.md +578 -0
- package/skills/ai-build-ai/docs/memory-claude-md.md +375 -0
- package/skills/ai-build-ai/docs/output-styles.md +208 -0
- package/skills/ai-build-ai/docs/overview.md +162 -0
- package/skills/ai-build-ai/docs/permissions.md +391 -0
- package/skills/ai-build-ai/docs/plugins.md +396 -0
- package/skills/ai-build-ai/docs/sandbox.md +262 -0
- package/skills/ai-build-ai/scripts/load-tutorial.sh +54 -0
- package/skills/icon-generator/SKILL.md +270 -0
- package/skills/mobile-app-review/SKILL.md +321 -0
- package/skills/mobile-app-review/references/apple-review.md +132 -0
- package/skills/mobile-app-review/references/google-play-review.md +203 -0
- package/skills/mongodb/SKILL.md +667 -0
- package/skills/mongodb/references/mongoose-patterns.md +368 -0
- package/skills/nestjs-architecture/SKILL.md +1086 -0
- package/skills/nestjs-architecture/references/advanced-patterns.md +590 -0
- package/skills/performance/SKILL.md +509 -0
- package/skills/react-fsd-architecture/SKILL.md +693 -0
- package/skills/react-fsd-architecture/references/fsd-patterns.md +747 -0
- package/skills/react-query/SKILL.md +685 -0
- package/skills/react-query/references/query-patterns.md +365 -0
- package/skills/review-code/SKILL.md +321 -0
- package/skills/review-code/references/clean-code-principles.md +395 -0
- package/skills/review-code/references/frontend-patterns.md +136 -0
- package/skills/review-code/references/nestjs-patterns.md +184 -0
- package/skills/review-code/scripts/check-module.sh +201 -0
- package/skills/review-code/scripts/deep-scan.sh +604 -0
- package/skills/review-code/scripts/dep-check.sh +522 -0
- package/skills/review-code/scripts/detect-duplicates.sh +466 -0
- package/skills/review-code/scripts/format-check.sh +577 -0
- package/skills/review-code/scripts/run-review.sh +167 -0
- package/skills/review-code/scripts/scan-codebase.sh +152 -0
- package/skills/security-scanner/SKILL.md +327 -0
- package/skills/security-scanner/references/nestjs-security.md +260 -0
- package/skills/security-scanner/references/nextjs-security.md +201 -0
- package/skills/security-scanner/references/react-native-security.md +199 -0
- package/skills/security-scanner/scripts/security-scan.sh +478 -0
- package/skills/ui-ux-pro-max/SKILL.md +377 -0
- package/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/skills/ui-ux-pro-max/data/styles.csv +68 -0
- package/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/skills/ui-ux-pro-max/scripts/core.py +253 -0
- package/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
- package/skills/ui-ux-pro-max/scripts/search.py +114 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# NestJS Backend Security Checklist
|
|
2
|
+
|
|
3
|
+
Deep-dive security checklist for the NestJS backend. Read this when scanning the backend.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
1. [Authentication & JWT](#authentication--jwt)
|
|
7
|
+
2. [Authorization & RBAC](#authorization--rbac)
|
|
8
|
+
3. [Input Validation & Injection](#input-validation--injection)
|
|
9
|
+
4. [Rate Limiting & DoS](#rate-limiting--dos)
|
|
10
|
+
5. [File Upload](#file-upload)
|
|
11
|
+
6. [Error Handling & Info Disclosure](#error-handling--info-disclosure)
|
|
12
|
+
7. [Database Security](#database-security)
|
|
13
|
+
8. [Cache & Session Security](#cache--session-security)
|
|
14
|
+
9. [Third-Party API Security](#third-party-api-security)
|
|
15
|
+
10. [LLM/AI Agent Security](#llmai-agent-security)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Authentication & JWT
|
|
20
|
+
|
|
21
|
+
### Token Configuration
|
|
22
|
+
- File: `core/config/jwt.config.ts`
|
|
23
|
+
- Access token: 15min expiry (good)
|
|
24
|
+
- Refresh token: 7d / 30d with "remember me"
|
|
25
|
+
|
|
26
|
+
### Checklist
|
|
27
|
+
- [ ] JWT secret loaded from env, not hardcoded
|
|
28
|
+
- [ ] Token expiration enforced (`ignoreExpiration: false`)
|
|
29
|
+
- [ ] Refresh token rotation on use (old token invalidated)
|
|
30
|
+
- [ ] Refresh token stored server-side (Redis/DB) for revocation
|
|
31
|
+
- [ ] Logout invalidates refresh token
|
|
32
|
+
- [ ] Token extraction order: Bearer header → signed cookie → regular cookie
|
|
33
|
+
- [ ] No token in URL query parameters
|
|
34
|
+
- [ ] JWE (encrypted JWT) considered for sensitive claims
|
|
35
|
+
|
|
36
|
+
### Common Vulnerabilities
|
|
37
|
+
```typescript
|
|
38
|
+
// BAD: JWT algorithm confusion
|
|
39
|
+
jwt.verify(token, secret) // No algorithm specified — attacker could use 'none'
|
|
40
|
+
|
|
41
|
+
// GOOD: Specify algorithm
|
|
42
|
+
jwt.verify(token, secret, { algorithms: ['HS256'] })
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Authorization & RBAC
|
|
46
|
+
|
|
47
|
+
### Checklist
|
|
48
|
+
- [ ] All endpoints have `@UseGuards(JwtAuthGuard)` unless intentionally public
|
|
49
|
+
- [ ] Public endpoints documented with `@Public()` decorator
|
|
50
|
+
- [ ] Role guard (`roles.guard.ts`) checks resource ownership, not just role
|
|
51
|
+
- [ ] Admin bypass is restricted to verified admin accounts
|
|
52
|
+
- [ ] No horizontal privilege escalation (user A accessing user B's data)
|
|
53
|
+
- [ ] Bulk endpoints check ownership for each item
|
|
54
|
+
|
|
55
|
+
### IDOR Check Pattern
|
|
56
|
+
```typescript
|
|
57
|
+
// BAD: No ownership check
|
|
58
|
+
@Get(':id')
|
|
59
|
+
findOne(@Param('id') id: string) {
|
|
60
|
+
return this.service.findById(id); // Any user can access any record
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// GOOD: Ownership check
|
|
64
|
+
@Get(':id')
|
|
65
|
+
findOne(@Param('id') id: string, @CurrentUser() user: User) {
|
|
66
|
+
return this.service.findByIdAndUser(id, user._id);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Input Validation & Injection
|
|
71
|
+
|
|
72
|
+
### Global Validation (already configured in main.ts)
|
|
73
|
+
- `whitelist: true` — strips unknown properties
|
|
74
|
+
- `forbidNonWhitelisted: true` — rejects unknown properties
|
|
75
|
+
- `transform: true` — auto-transforms types
|
|
76
|
+
|
|
77
|
+
### NoSQL Injection Checklist
|
|
78
|
+
- [ ] No raw `$where` queries with user input
|
|
79
|
+
- [ ] No `$regex` with unescaped user input
|
|
80
|
+
- [ ] No `JSON.parse()` of user input used directly in queries
|
|
81
|
+
- [ ] Mongoose `.lean()` used where possible (prevents prototype pollution)
|
|
82
|
+
- [ ] ObjectId params validated with `@IsMongoId()`
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// BAD: NoSQL injection possible
|
|
86
|
+
const users = await this.userModel.find({ name: req.body.name });
|
|
87
|
+
// If req.body.name = { "$gt": "" }, returns all users
|
|
88
|
+
|
|
89
|
+
// GOOD: Validate type first
|
|
90
|
+
@IsString() name: string; // class-validator ensures string type
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Prototype Pollution
|
|
94
|
+
- [ ] No `Object.assign()` or spread with unchecked user input into query objects
|
|
95
|
+
- [ ] `JSON.parse()` outputs validated before use
|
|
96
|
+
|
|
97
|
+
## Rate Limiting & DoS
|
|
98
|
+
|
|
99
|
+
### Checklist
|
|
100
|
+
- [ ] Rate limiting on auth endpoints (login, register, forgot-password)
|
|
101
|
+
- [ ] Rate limiting on API endpoints (especially AI/LLM which are expensive)
|
|
102
|
+
- [ ] File upload size limits configured
|
|
103
|
+
- [ ] Request body size limit set
|
|
104
|
+
- [ ] Pagination enforced (no unbounded `find()`)
|
|
105
|
+
- [ ] Bull queue jobs have timeout limits
|
|
106
|
+
- [ ] LLM API calls have timeout and token limits
|
|
107
|
+
|
|
108
|
+
### Implementation
|
|
109
|
+
```typescript
|
|
110
|
+
// NestJS throttler
|
|
111
|
+
@Throttle({ default: { limit: 5, ttl: 60000 } })
|
|
112
|
+
@Post('login')
|
|
113
|
+
login() { ... }
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## File Upload
|
|
117
|
+
|
|
118
|
+
### Checklist
|
|
119
|
+
- [ ] File type validated (not just extension — check magic bytes)
|
|
120
|
+
- [ ] File size limited
|
|
121
|
+
- [ ] Uploaded files stored outside webroot (S3, not `/public`)
|
|
122
|
+
- [ ] Filenames sanitized (no path traversal `../`)
|
|
123
|
+
- [ ] Image files re-encoded to strip EXIF/metadata
|
|
124
|
+
- [ ] No server-side file execution possible
|
|
125
|
+
|
|
126
|
+
## Error Handling & Info Disclosure
|
|
127
|
+
|
|
128
|
+
### Checklist
|
|
129
|
+
- [ ] Production mode strips stack traces (`HttpExceptionFilter`)
|
|
130
|
+
- [ ] No internal paths leaked in error messages
|
|
131
|
+
- [ ] No database error details in API responses
|
|
132
|
+
- [ ] No technology fingerprinting (remove `X-Powered-By`)
|
|
133
|
+
- [ ] Mongoose validation errors don't expose schema structure
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
// BAD: Leaks internal details
|
|
137
|
+
catch (error) {
|
|
138
|
+
throw new InternalServerErrorException(error.message);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// GOOD: Generic message, log details internally
|
|
142
|
+
catch (error) {
|
|
143
|
+
this.logger.error('Operation failed', error.stack);
|
|
144
|
+
throw new InternalServerErrorException('An unexpected error occurred');
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Database Security
|
|
149
|
+
|
|
150
|
+
### MongoDB Checklist
|
|
151
|
+
- [ ] Connection string uses authentication
|
|
152
|
+
- [ ] TLS/SSL enabled for database connections
|
|
153
|
+
- [ ] Database user has minimal required permissions
|
|
154
|
+
- [ ] Indexes exist on fields used in auth queries (email, userId)
|
|
155
|
+
- [ ] No `$where` or `$expr` with user-controlled input
|
|
156
|
+
- [ ] Backup encryption enabled
|
|
157
|
+
|
|
158
|
+
## Cache & Session Security
|
|
159
|
+
|
|
160
|
+
### Redis Checklist
|
|
161
|
+
- [ ] Redis requires authentication (`REDIS_PASSWORD`)
|
|
162
|
+
- [ ] Redis connection uses TLS in production
|
|
163
|
+
- [ ] Cache keys don't contain sensitive data
|
|
164
|
+
- [ ] Cache invalidation on permission changes
|
|
165
|
+
- [ ] Session data encrypted at rest
|
|
166
|
+
|
|
167
|
+
## Third-Party API Security
|
|
168
|
+
|
|
169
|
+
### Checklist
|
|
170
|
+
- [ ] All API keys loaded from environment variables
|
|
171
|
+
- [ ] API keys have minimal required permissions/scopes
|
|
172
|
+
- [ ] Webhook endpoints validate request signatures
|
|
173
|
+
- [ ] External API responses validated before use
|
|
174
|
+
- [ ] Timeout configured for all HTTP clients
|
|
175
|
+
- [ ] Circuit breaker on external service calls
|
|
176
|
+
|
|
177
|
+
### Known External Services
|
|
178
|
+
Check for these common integrations:
|
|
179
|
+
- Image generation APIs — API key management
|
|
180
|
+
- LLM providers (OpenAI, Google/Vertex AI, Anthropic) — API keys
|
|
181
|
+
- Cloud storage (AWS S3, GCS) — credentials and IAM
|
|
182
|
+
- Vector databases (Qdrant, Pinecone, Weaviate) — access control
|
|
183
|
+
- Payment processors — webhook signature verification
|
|
184
|
+
|
|
185
|
+
## LLM/AI Agent Security (OWASP LLM Top 10:2025)
|
|
186
|
+
|
|
187
|
+
This project uses LangChain + LangGraph with multi-provider LLMs (OpenAI, Gemini, Vertex AI) and Qdrant vector DB. AI agent security is a critical surface.
|
|
188
|
+
|
|
189
|
+
### Prompt Injection (LLM01) — #1 Risk
|
|
190
|
+
- [ ] User input sanitized before inclusion in LLM prompts
|
|
191
|
+
- [ ] System prompts not exposed to users (check for leakage via prompt tricks)
|
|
192
|
+
- [ ] Tool calls validated and sandboxed
|
|
193
|
+
- [ ] LLM output not trusted for authorization decisions
|
|
194
|
+
- [ ] Rate limiting on AI endpoints (expensive operations)
|
|
195
|
+
- [ ] Multi-modal inputs (images) checked for embedded prompt injections
|
|
196
|
+
- [ ] Indirect injection: external documents processed by RAG checked for injected instructions
|
|
197
|
+
|
|
198
|
+
**Mitigation reality check:** Prompt injection cannot be fully prevented with current LLM architecture. Focus on containment — least privilege, output validation, logging, and separating instructions from data.
|
|
199
|
+
|
|
200
|
+
### Sensitive Information Disclosure (LLM02)
|
|
201
|
+
- [ ] PII not sent to external LLM providers unnecessarily
|
|
202
|
+
- [ ] Conversation history access restricted to conversation owner
|
|
203
|
+
- [ ] Knowledge base doesn't contain user PII
|
|
204
|
+
- [ ] LLM responses sanitized before storing/displaying
|
|
205
|
+
- [ ] Model responses don't echo back system prompts or internal config
|
|
206
|
+
|
|
207
|
+
### Improper Output Handling (LLM05)
|
|
208
|
+
- [ ] AI-generated HTML/markdown sanitized before frontend rendering
|
|
209
|
+
- [ ] AI-suggested actions validated before execution
|
|
210
|
+
- [ ] No `dangerouslySetInnerHTML` with raw AI output
|
|
211
|
+
- [ ] URLs in AI responses validated (no `javascript:` links)
|
|
212
|
+
|
|
213
|
+
### Excessive Agency (LLM06)
|
|
214
|
+
- [ ] LangGraph tools scoped to minimum required permissions
|
|
215
|
+
- [ ] Agent can't access resources outside current user's scope
|
|
216
|
+
- [ ] Human-in-the-loop for destructive or irreversible actions
|
|
217
|
+
- [ ] Tool execution timeouts prevent runaway agents
|
|
218
|
+
- [ ] Cross-agent trust: agents can't escalate each other's permissions
|
|
219
|
+
|
|
220
|
+
### System Prompt Leakage (LLM07)
|
|
221
|
+
- [ ] System prompts not retrievable via "ignore previous instructions" attacks
|
|
222
|
+
- [ ] No system prompt content in error messages
|
|
223
|
+
- [ ] Prompt templates don't contain sensitive business logic that would be harmful if exposed
|
|
224
|
+
|
|
225
|
+
### Vector/Embedding Weaknesses (LLM08)
|
|
226
|
+
- [ ] Qdrant vector DB requires authentication
|
|
227
|
+
- [ ] Access to knowledge base restricted by user/tenant
|
|
228
|
+
- [ ] Embedding poisoning: can users inject malicious content into the knowledge base?
|
|
229
|
+
- [ ] Retrieval results validated before inclusion in prompts
|
|
230
|
+
|
|
231
|
+
### Unbounded Consumption (LLM10)
|
|
232
|
+
- [ ] Max token limits on LLM API calls
|
|
233
|
+
- [ ] Rate limiting per user on AI endpoints
|
|
234
|
+
- [ ] Timeout on LangGraph agent execution
|
|
235
|
+
- [ ] Cost alerting for LLM provider API usage
|
|
236
|
+
- [ ] Queue-based processing with bounded concurrency for AI jobs
|
|
237
|
+
|
|
238
|
+
### Tool Execution
|
|
239
|
+
- [ ] LangGraph tools have input validation
|
|
240
|
+
- [ ] Tools can't access resources outside their scope
|
|
241
|
+
- [ ] Tool errors don't leak internal state
|
|
242
|
+
- [ ] Tool call chains have maximum depth limit
|
|
243
|
+
|
|
244
|
+
## Known NestJS Vulnerabilities
|
|
245
|
+
|
|
246
|
+
### CVE-2025-54782 — RCE in @nestjs/devtools-integration
|
|
247
|
+
- **Affected:** `@nestjs/devtools-integration` ≤ 0.2.0
|
|
248
|
+
- **Impact:** Remote code execution on developer machines via unsafe `vm.runInNewContext()` + missing CORS
|
|
249
|
+
- **Fix:** Upgrade to ≥ 0.2.1
|
|
250
|
+
- [ ] Check if `@nestjs/devtools-integration` is in dependencies and version is ≥ 0.2.1
|
|
251
|
+
|
|
252
|
+
## Security Logging & Alerting (OWASP A09:2025)
|
|
253
|
+
|
|
254
|
+
- [ ] Auth events logged (login success/failure, token refresh, logout)
|
|
255
|
+
- [ ] Admin actions logged with actor + target + timestamp
|
|
256
|
+
- [ ] Failed access control attempts logged and alerted
|
|
257
|
+
- [ ] Rate limit violations logged
|
|
258
|
+
- [ ] Suspicious AI usage patterns detected (repeated prompt injection attempts)
|
|
259
|
+
- [ ] Logs don't contain PII or secrets (sanitize before logging)
|
|
260
|
+
- [ ] Log aggregation configured (Pino → structured JSON → log service)
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# Next.js Frontend Security Checklist
|
|
2
|
+
|
|
3
|
+
Deep-dive security checklist for the Next.js frontend. Read this when scanning the frontend.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
1. [Server/Client Boundary](#serverclient-boundary)
|
|
7
|
+
2. [API Routes](#api-routes)
|
|
8
|
+
3. [Authentication & Session](#authentication--session)
|
|
9
|
+
4. [XSS Prevention](#xss-prevention)
|
|
10
|
+
5. [Environment Variables](#environment-variables)
|
|
11
|
+
6. [Middleware & Headers](#middleware--headers)
|
|
12
|
+
7. [Dependencies](#dependencies)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Server/Client Boundary
|
|
17
|
+
|
|
18
|
+
Next.js 15 App Router has a critical server/client boundary. Mistakes here cause security issues.
|
|
19
|
+
|
|
20
|
+
### Checklist
|
|
21
|
+
- [ ] Server Components don't pass secrets to Client Components via props
|
|
22
|
+
- [ ] `"use client"` files don't import server-only modules
|
|
23
|
+
- [ ] Server Actions validate input (they're public HTTP endpoints!)
|
|
24
|
+
- [ ] No `process.env.SECRET_*` accessed in client components
|
|
25
|
+
- [ ] `server-only` package used to prevent accidental client imports
|
|
26
|
+
|
|
27
|
+
### Dangerous Pattern
|
|
28
|
+
```typescript
|
|
29
|
+
// BAD: Server component passes secret to client
|
|
30
|
+
// page.tsx (Server Component)
|
|
31
|
+
export default function Page() {
|
|
32
|
+
return <ClientComponent apiKey={process.env.SECRET_API_KEY} />;
|
|
33
|
+
// Secret ends up in client bundle!
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// GOOD: Server component uses secret server-side only
|
|
37
|
+
export default async function Page() {
|
|
38
|
+
const data = await fetchWithSecret(process.env.SECRET_API_KEY);
|
|
39
|
+
return <ClientComponent data={data} />;
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## API Routes
|
|
44
|
+
|
|
45
|
+
### Location: `src/app/api/`
|
|
46
|
+
|
|
47
|
+
### Checklist
|
|
48
|
+
- [ ] All API routes check authentication before processing
|
|
49
|
+
- [ ] Input validated with Zod or similar
|
|
50
|
+
- [ ] Error responses don't leak internal details
|
|
51
|
+
- [ ] Rate limiting on sensitive endpoints
|
|
52
|
+
- [ ] CORS headers set correctly (or inherited from middleware)
|
|
53
|
+
- [ ] No secrets returned in API responses
|
|
54
|
+
- [ ] POST/PUT/DELETE routes check CSRF token
|
|
55
|
+
|
|
56
|
+
### Current Pattern
|
|
57
|
+
```typescript
|
|
58
|
+
// src/app/api/me/route.ts — proxies to backend
|
|
59
|
+
// Check: Is auth token validated before proxying?
|
|
60
|
+
// Check: Are error responses generic?
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Authentication & Session
|
|
64
|
+
|
|
65
|
+
### Checklist
|
|
66
|
+
- [ ] JWT stored in httpOnly cookie (not localStorage)
|
|
67
|
+
- [ ] Cookie has `Secure` flag (HTTPS only)
|
|
68
|
+
- [ ] Cookie has `SameSite=Strict` or `SameSite=Lax`
|
|
69
|
+
- [ ] Cookie `Path` is restricted (not `/`)
|
|
70
|
+
- [ ] Token refresh handled transparently
|
|
71
|
+
- [ ] Logout clears all auth cookies
|
|
72
|
+
- [ ] CSRF protection on state-changing requests
|
|
73
|
+
- [ ] Session timeout after inactivity
|
|
74
|
+
|
|
75
|
+
### Token Storage Safety
|
|
76
|
+
```typescript
|
|
77
|
+
// BAD: Token in localStorage (XSS accessible)
|
|
78
|
+
localStorage.setItem('token', jwt);
|
|
79
|
+
|
|
80
|
+
// BAD: Token in client-side state (lost on refresh, XSS accessible)
|
|
81
|
+
const [token, setToken] = useState(jwt);
|
|
82
|
+
|
|
83
|
+
// GOOD: httpOnly cookie (not accessible via JavaScript)
|
|
84
|
+
// Set by backend, sent automatically by browser
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## XSS Prevention
|
|
88
|
+
|
|
89
|
+
### Checklist
|
|
90
|
+
- [ ] No `dangerouslySetInnerHTML` with user content
|
|
91
|
+
- [ ] Markdown rendering sanitized (DOMPurify or similar)
|
|
92
|
+
- [ ] AI-generated content sanitized before display
|
|
93
|
+
- [ ] SVG uploads sanitized (can contain inline scripts)
|
|
94
|
+
- [ ] URL parameters not reflected in HTML without encoding
|
|
95
|
+
- [ ] Rich text editor output sanitized
|
|
96
|
+
|
|
97
|
+
### React's Built-in Protection
|
|
98
|
+
React auto-escapes JSX expressions, but these bypass it:
|
|
99
|
+
```typescript
|
|
100
|
+
// DANGEROUS: Direct HTML insertion
|
|
101
|
+
<div dangerouslySetInnerHTML={{ __html: userContent }} />
|
|
102
|
+
|
|
103
|
+
// DANGEROUS: javascript: URLs
|
|
104
|
+
<a href={userProvidedUrl}>Click</a> // href="javascript:alert(1)"
|
|
105
|
+
|
|
106
|
+
// SAFE: React auto-escapes
|
|
107
|
+
<div>{userContent}</div> // HTML entities escaped
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### AI Content Rendering
|
|
111
|
+
```typescript
|
|
112
|
+
// When displaying AI stylist responses:
|
|
113
|
+
// 1. Sanitize HTML if rendering as rich text
|
|
114
|
+
// 2. Strip script tags, event handlers
|
|
115
|
+
// 3. Validate URLs in generated content
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Environment Variables
|
|
119
|
+
|
|
120
|
+
### Next.js Rules
|
|
121
|
+
- `NEXT_PUBLIC_*` — bundled into client JavaScript (NEVER put secrets here)
|
|
122
|
+
- All other env vars — server-only
|
|
123
|
+
|
|
124
|
+
### Checklist
|
|
125
|
+
- [ ] No secrets in `NEXT_PUBLIC_*` variables
|
|
126
|
+
- [ ] `.env.local` in `.gitignore`
|
|
127
|
+
- [ ] `NEXT_PUBLIC_*` values are safe to expose (API URLs, feature flags)
|
|
128
|
+
- [ ] Server-side env vars not accessed in `"use client"` files
|
|
129
|
+
- [ ] `.env.example` doesn't contain real values
|
|
130
|
+
|
|
131
|
+
### Verify
|
|
132
|
+
```bash
|
|
133
|
+
# Find all NEXT_PUBLIC_ usages
|
|
134
|
+
grep -rn "NEXT_PUBLIC_" src/ --include="*.ts" --include="*.tsx"
|
|
135
|
+
# Verify none contain sensitive data
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Middleware & Headers
|
|
139
|
+
|
|
140
|
+
### Checklist
|
|
141
|
+
- [ ] Security headers set in `middleware.ts` or `next.config.js`
|
|
142
|
+
- [ ] `Content-Security-Policy` configured
|
|
143
|
+
- [ ] `X-Frame-Options: DENY` (prevent clickjacking)
|
|
144
|
+
- [ ] `X-Content-Type-Options: nosniff`
|
|
145
|
+
- [ ] `Referrer-Policy: strict-origin-when-cross-origin`
|
|
146
|
+
- [ ] Auth middleware protects `(dashboard)` route group
|
|
147
|
+
|
|
148
|
+
### next.config.js Headers
|
|
149
|
+
```javascript
|
|
150
|
+
// Verify these are set:
|
|
151
|
+
const securityHeaders = [
|
|
152
|
+
{ key: 'X-DNS-Prefetch-Control', value: 'on' },
|
|
153
|
+
{ key: 'X-Frame-Options', value: 'DENY' },
|
|
154
|
+
{ key: 'X-Content-Type-Options', value: 'nosniff' },
|
|
155
|
+
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
|
|
156
|
+
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
|
|
157
|
+
];
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Dependencies & Supply Chain (OWASP A03:2025)
|
|
161
|
+
|
|
162
|
+
### Dependency Vulnerability Scanning
|
|
163
|
+
- [ ] `npm audit` shows no critical/high vulnerabilities
|
|
164
|
+
- [ ] `npm audit signatures` — verify package signatures (npm 9+)
|
|
165
|
+
- [ ] Dependencies pinned (lock file committed and reviewed on changes)
|
|
166
|
+
- [ ] No `eval()` or `Function()` in dependencies
|
|
167
|
+
- [ ] shadcn/ui components from trusted source
|
|
168
|
+
- [ ] Image optimization libraries up to date (sharp, next/image)
|
|
169
|
+
|
|
170
|
+
### Supply Chain Hardening
|
|
171
|
+
- [ ] No `preinstall`/`postinstall` scripts that download or execute code
|
|
172
|
+
- [ ] Lifecycle scripts disabled by default (`npm config set ignore-scripts true`)
|
|
173
|
+
- [ ] `package-lock.json` committed and integrity verified on CI
|
|
174
|
+
- [ ] No typosquatted dependencies (verify package names match intended)
|
|
175
|
+
- [ ] Dependabot or Snyk configured for automatic vulnerability alerts
|
|
176
|
+
- [ ] SBOM generated for compliance audits (`npm sbom --sbom-format cyclonedx`)
|
|
177
|
+
|
|
178
|
+
### Regular Audit
|
|
179
|
+
```bash
|
|
180
|
+
cd <frontend-dir>
|
|
181
|
+
npm audit --production # production deps only
|
|
182
|
+
npm audit fix # auto-fix where possible
|
|
183
|
+
npm audit signatures # verify package signatures
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### AI-Generated Code Warning
|
|
187
|
+
If using AI coding assistants (Copilot, Claude, Cursor), review generated code for:
|
|
188
|
+
- [ ] Hardcoded secrets or placeholder credentials
|
|
189
|
+
- [ ] Insecure patterns (eval, innerHTML, unsafe-inline)
|
|
190
|
+
- [ ] Outdated API usage from training data
|
|
191
|
+
- [ ] Missing input validation or error handling
|
|
192
|
+
|
|
193
|
+
## Mishandling Exceptional Conditions (OWASP A10:2025)
|
|
194
|
+
|
|
195
|
+
New in OWASP 2025 — how the frontend handles edge cases:
|
|
196
|
+
- [ ] API error responses don't expose stack traces to users
|
|
197
|
+
- [ ] Auth token refresh failure redirects to login (doesn't fail-open)
|
|
198
|
+
- [ ] Network failures show user-friendly errors (no raw error objects)
|
|
199
|
+
- [ ] Server Action errors handled gracefully (no unhandled promise rejections)
|
|
200
|
+
- [ ] Image/asset loading failures have fallback UI
|
|
201
|
+
- [ ] Rate limit responses (429) handled with retry logic, not crashes
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# React Native Mobile Security Checklist
|
|
2
|
+
|
|
3
|
+
Deep-dive security checklist for the React Native mobile app. Aligned with **OWASP Mobile Top 10 2024**. Read this when scanning the mobile app.
|
|
4
|
+
|
|
5
|
+
## OWASP Mobile Top 10 Mapping
|
|
6
|
+
|
|
7
|
+
| OWASP ID | Risk | Primary Section |
|
|
8
|
+
|----------|------|-----------------|
|
|
9
|
+
| M1 | Improper Credential Usage | Secure Storage, Authentication Flow |
|
|
10
|
+
| M2 | Inadequate Supply Chain Security | Third-Party SDKs |
|
|
11
|
+
| M3 | Insecure Authentication/Authorization | Authentication Flow |
|
|
12
|
+
| M4 | Insufficient Input/Output Validation | Deep Links, Data Leakage |
|
|
13
|
+
| M5 | Insecure Communication | Network Security |
|
|
14
|
+
| M8 | Security Misconfiguration | Binary Protection |
|
|
15
|
+
| M9 | Insecure Data Storage | Secure Storage |
|
|
16
|
+
| M10 | Insufficient Cryptography | Secure Storage, Network Security |
|
|
17
|
+
|
|
18
|
+
## Table of Contents
|
|
19
|
+
1. [Secure Storage](#secure-storage) (M1, M9)
|
|
20
|
+
2. [Network Security](#network-security) (M5, M10)
|
|
21
|
+
3. [Authentication Flow](#authentication-flow) (M1, M3)
|
|
22
|
+
4. [Deep Links & URL Schemes](#deep-links--url-schemes) (M4)
|
|
23
|
+
5. [Binary Protection](#binary-protection) (M8)
|
|
24
|
+
6. [Data Leakage](#data-leakage) (M4)
|
|
25
|
+
7. [Third-Party SDKs](#third-party-sdks) (M2)
|
|
26
|
+
8. [Hermes Engine Security](#hermes-engine-security)
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Secure Storage
|
|
31
|
+
|
|
32
|
+
### Current Implementation (GOOD)
|
|
33
|
+
- File: `shared/libs/token-storage.ts`
|
|
34
|
+
- Uses `react-native-keychain` (Keychain on iOS, Keystore on Android)
|
|
35
|
+
- Separate service names for access and refresh tokens
|
|
36
|
+
|
|
37
|
+
### Checklist
|
|
38
|
+
- [ ] Tokens stored in Keychain/Keystore (NOT AsyncStorage) ✅ already done
|
|
39
|
+
- [ ] AsyncStorage only used for non-sensitive data (preferences, UI state)
|
|
40
|
+
- [ ] No sensitive data in `MMKV`, `SecureStore`, or custom solutions without encryption
|
|
41
|
+
- [ ] Biometric lock for sensitive operations (account deletion, payment)
|
|
42
|
+
- [ ] Data cleared on logout (tokens, cached user data)
|
|
43
|
+
- [ ] No sensitive data in app logs (check `console.log` in release builds)
|
|
44
|
+
|
|
45
|
+
### What NOT to store insecurely
|
|
46
|
+
```typescript
|
|
47
|
+
// BAD: AsyncStorage is NOT encrypted
|
|
48
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
49
|
+
await AsyncStorage.setItem('token', accessToken); // INSECURE
|
|
50
|
+
|
|
51
|
+
// GOOD: Keychain is encrypted by OS
|
|
52
|
+
import * as Keychain from 'react-native-keychain';
|
|
53
|
+
await Keychain.setGenericPassword('accessToken', token, {
|
|
54
|
+
service: 'AppTokens',
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Network Security
|
|
59
|
+
|
|
60
|
+
### Certificate Pinning
|
|
61
|
+
- [ ] Certificate pinning implemented for production API
|
|
62
|
+
- [ ] Pinning includes backup certificates
|
|
63
|
+
- [ ] Pinning gracefully handles certificate rotation
|
|
64
|
+
|
|
65
|
+
### Network Checklist
|
|
66
|
+
- [ ] All API calls use HTTPS (no HTTP fallback)
|
|
67
|
+
- [ ] No `NSAppTransportSecurity` exceptions for production domains (iOS)
|
|
68
|
+
- [ ] `android:usesCleartextTraffic="false"` in AndroidManifest
|
|
69
|
+
- [ ] API base URL loaded from config, not hardcoded
|
|
70
|
+
- [ ] Proxy detection (optional — detect MITM tools like Charles/Fiddler)
|
|
71
|
+
- [ ] Sensitive headers not logged in development interceptors
|
|
72
|
+
|
|
73
|
+
### Check in API Client
|
|
74
|
+
```typescript
|
|
75
|
+
// File: shared/libs/api-client.ts
|
|
76
|
+
// Verify:
|
|
77
|
+
// 1. Base URL is HTTPS
|
|
78
|
+
// 2. Token not logged in request interceptor
|
|
79
|
+
// 3. Error interceptor doesn't leak tokens in error messages
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Authentication Flow
|
|
83
|
+
|
|
84
|
+
### Token Refresh Pattern (Current — GOOD)
|
|
85
|
+
- Single-flight refresh prevents race conditions
|
|
86
|
+
- 401 responses trigger automatic refresh
|
|
87
|
+
- Failed refresh → logout and clear tokens
|
|
88
|
+
|
|
89
|
+
### Checklist
|
|
90
|
+
- [ ] Access token refreshed silently before expiry
|
|
91
|
+
- [ ] Refresh token rotation (new refresh token on each use)
|
|
92
|
+
- [ ] Failed refresh clears all auth state
|
|
93
|
+
- [ ] Login screen shown immediately on auth failure (no stale UI)
|
|
94
|
+
- [ ] Biometric re-authentication for sensitive actions
|
|
95
|
+
- [ ] Session timeout after inactivity
|
|
96
|
+
|
|
97
|
+
### Background State
|
|
98
|
+
- [ ] App clears sensitive data from memory when backgrounded
|
|
99
|
+
- [ ] Screenshot prevention on sensitive screens (iOS: `UIApplicationDelegate`, Android: `FLAG_SECURE`)
|
|
100
|
+
- [ ] Clipboard cleared after copying sensitive data (if applicable)
|
|
101
|
+
|
|
102
|
+
## Deep Links & URL Schemes
|
|
103
|
+
|
|
104
|
+
### Checklist
|
|
105
|
+
- [ ] Deep link URLs validated before navigation
|
|
106
|
+
- [ ] No sensitive data in deep link parameters
|
|
107
|
+
- [ ] Deep link handlers sanitize all parameters
|
|
108
|
+
- [ ] Custom URL scheme can't be hijacked (use Universal Links / App Links)
|
|
109
|
+
- [ ] OAuth redirect URIs validated against whitelist
|
|
110
|
+
|
|
111
|
+
### Vulnerability Pattern
|
|
112
|
+
```typescript
|
|
113
|
+
// BAD: Unvalidated deep link navigation
|
|
114
|
+
Linking.addEventListener('url', ({ url }) => {
|
|
115
|
+
navigation.navigate(url.split('/').pop()); // Attacker controls destination
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// GOOD: Validate against known routes
|
|
119
|
+
const ALLOWED_ROUTES = ['wardrobe', 'outfit', 'settings'];
|
|
120
|
+
Linking.addEventListener('url', ({ url }) => {
|
|
121
|
+
const route = parseRoute(url);
|
|
122
|
+
if (ALLOWED_ROUTES.includes(route.name)) {
|
|
123
|
+
navigation.navigate(route.name, route.params);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Binary Protection
|
|
129
|
+
|
|
130
|
+
### Checklist
|
|
131
|
+
- [ ] ProGuard/R8 obfuscation enabled (Android release)
|
|
132
|
+
- [ ] Hermes bytecode compilation (reduces reverse engineering)
|
|
133
|
+
- [ ] No debug flags in release builds
|
|
134
|
+
- [ ] No sensitive strings in binary (use env vars or remote config)
|
|
135
|
+
- [ ] Root/jailbreak detection (optional, but recommended for financial features)
|
|
136
|
+
- [ ] Tamper detection (optional)
|
|
137
|
+
|
|
138
|
+
### Expo/EAS Build
|
|
139
|
+
- [ ] `expo-updates` configured with code signing
|
|
140
|
+
- [ ] OTA updates use HTTPS
|
|
141
|
+
- [ ] Update manifest signed to prevent MITM
|
|
142
|
+
|
|
143
|
+
## Data Leakage
|
|
144
|
+
|
|
145
|
+
### Checklist
|
|
146
|
+
- [ ] No sensitive data in `console.log` (strip in production with babel plugin)
|
|
147
|
+
- [ ] No sensitive data in crash reports (Sentry, Crashlytics)
|
|
148
|
+
- [ ] Keyboard caching disabled on sensitive inputs (`secureTextEntry`, `autoCorrect={false}`)
|
|
149
|
+
- [ ] WebView content not cached (if WebView used)
|
|
150
|
+
- [ ] Images with PII not cached to disk unencrypted
|
|
151
|
+
- [ ] Clipboard data cleared after sensitive copy operations
|
|
152
|
+
|
|
153
|
+
### Production Logging
|
|
154
|
+
```javascript
|
|
155
|
+
// babel.config.js — strip console in production
|
|
156
|
+
module.exports = {
|
|
157
|
+
plugins: [
|
|
158
|
+
['transform-remove-console', { exclude: ['error', 'warn'] }],
|
|
159
|
+
],
|
|
160
|
+
};
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Third-Party SDKs
|
|
164
|
+
|
|
165
|
+
### Checklist
|
|
166
|
+
- [ ] SDKs reviewed for data collection practices
|
|
167
|
+
- [ ] Minimal permissions requested
|
|
168
|
+
- [ ] Analytics SDKs don't collect PII without consent
|
|
169
|
+
- [ ] Adapty SDK (subscriptions) — ensure payment data handled securely
|
|
170
|
+
- [ ] Expo modules — check for known vulnerabilities
|
|
171
|
+
|
|
172
|
+
### Data Flow Review
|
|
173
|
+
Map where user data flows:
|
|
174
|
+
1. User input → App → Backend API (encrypted in transit?)
|
|
175
|
+
2. User input → App → Analytics SDK (what's collected?)
|
|
176
|
+
3. User input → App → LLM API (PII in prompts?)
|
|
177
|
+
4. User photos → App → Image generation API (stored? for how long?)
|
|
178
|
+
|
|
179
|
+
### Supply Chain Scanning (OWASP M2)
|
|
180
|
+
- [ ] `npm audit` / `yarn audit` run regularly on the mobile app directory
|
|
181
|
+
- [ ] Native dependency versions checked for known CVEs
|
|
182
|
+
- [ ] Expo SDK version up to date
|
|
183
|
+
- [ ] No deprecated or unmaintained RN packages
|
|
184
|
+
|
|
185
|
+
## Hermes Engine Security
|
|
186
|
+
|
|
187
|
+
React Native uses the Hermes JS engine (from Facebook/Meta). Key considerations:
|
|
188
|
+
|
|
189
|
+
### Checklist
|
|
190
|
+
- [ ] Hermes bytecode compilation enabled for release builds (harder to reverse-engineer than plain JS)
|
|
191
|
+
- [ ] Hermes version updated — check for known Hermes vulnerabilities
|
|
192
|
+
- [ ] No eval-like patterns that could be exploited through the JS engine
|
|
193
|
+
- [ ] Source maps NOT included in release builds (would expose original code)
|
|
194
|
+
|
|
195
|
+
### Threat Model
|
|
196
|
+
- Native JS engines make extracting minified JS from app bundles easy
|
|
197
|
+
- Hermes compiles to bytecode which is harder to decompile but NOT impossible
|
|
198
|
+
- Hermes has had several reported vulnerabilities — keep it updated
|
|
199
|
+
- Application logic in the entry file is visible; protect sensitive business logic server-side
|