openhack 0.1.0__py3-none-any.whl
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.
- openhack/__init__.py +2 -0
- openhack/__main__.py +225 -0
- openhack/agents/__init__.py +30 -0
- openhack/agents/base.py +230 -0
- openhack/agents/browser_verifier.py +679 -0
- openhack/agents/browser_verifier_swarm.py +256 -0
- openhack/agents/checkpoint.py +89 -0
- openhack/agents/context_manager.py +356 -0
- openhack/agents/coordinator.py +1105 -0
- openhack/agents/endpoint_analyst.py +307 -0
- openhack/agents/feature_hunter.py +93 -0
- openhack/agents/hunter.py +481 -0
- openhack/agents/hunter_swarm.py +385 -0
- openhack/agents/llm.py +334 -0
- openhack/agents/recon.py +19 -0
- openhack/agents/sandbox_verifier.py +396 -0
- openhack/agents/sandbox_verifier_swarm.py +250 -0
- openhack/agents/session.py +286 -0
- openhack/agents/validator.py +217 -0
- openhack/agents/validator_swarm.py +106 -0
- openhack/auth.py +175 -0
- openhack/browser/__init__.py +12 -0
- openhack/browser/runner.py +385 -0
- openhack/categories.py +130 -0
- openhack/config.py +201 -0
- openhack/deterministic_recon.py +464 -0
- openhack/entry_points.py +745 -0
- openhack/framework_classifier.py +515 -0
- openhack/framework_detection.py +269 -0
- openhack/headless_scan.py +179 -0
- openhack/prompts/__init__.py +108 -0
- openhack/prompts/browser_verifier.py +171 -0
- openhack/prompts/coordinator.py +31 -0
- openhack/prompts/django/__init__.py +32 -0
- openhack/prompts/django/auth_bypass.py +76 -0
- openhack/prompts/django/csrf.py +62 -0
- openhack/prompts/django/data_exposure.py +67 -0
- openhack/prompts/django/idor.py +74 -0
- openhack/prompts/django/injection.py +67 -0
- openhack/prompts/django/misconfiguration.py +70 -0
- openhack/prompts/django/ssrf.py +64 -0
- openhack/prompts/endpoint_analyst.py +122 -0
- openhack/prompts/express/__init__.py +29 -0
- openhack/prompts/express/auth_bypass.py +71 -0
- openhack/prompts/express/data_exposure.py +77 -0
- openhack/prompts/express/idor.py +69 -0
- openhack/prompts/express/injection.py +75 -0
- openhack/prompts/express/misconfiguration.py +72 -0
- openhack/prompts/express/ssrf.py +63 -0
- openhack/prompts/feature_hunter.py +140 -0
- openhack/prompts/flask/__init__.py +29 -0
- openhack/prompts/flask/auth_bypass.py +86 -0
- openhack/prompts/flask/data_exposure.py +78 -0
- openhack/prompts/flask/idor.py +83 -0
- openhack/prompts/flask/injection.py +77 -0
- openhack/prompts/flask/misconfiguration.py +73 -0
- openhack/prompts/flask/ssrf.py +65 -0
- openhack/prompts/hunter.py +362 -0
- openhack/prompts/hunter_continuation_loop.py +12 -0
- openhack/prompts/hunter_continuation_no_findings.py +19 -0
- openhack/prompts/hunter_continuation_no_progress.py +22 -0
- openhack/prompts/hunter_tool_instructions.py +55 -0
- openhack/prompts/nextjs/__init__.py +42 -0
- openhack/prompts/nextjs/auth_bypass.py +80 -0
- openhack/prompts/nextjs/csrf.py +71 -0
- openhack/prompts/nextjs/data_exposure.py +88 -0
- openhack/prompts/nextjs/idor.py +64 -0
- openhack/prompts/nextjs/injection.py +65 -0
- openhack/prompts/nextjs/middleware_bypass.py +75 -0
- openhack/prompts/nextjs/misconfiguration.py +92 -0
- openhack/prompts/nextjs/server_actions.py +97 -0
- openhack/prompts/nextjs/ssrf.py +66 -0
- openhack/prompts/nextjs/xss.py +69 -0
- openhack/prompts/pr_analysis_system.py +80 -0
- openhack/prompts/pr_analysis_user.py +11 -0
- openhack/prompts/project_context.py +89 -0
- openhack/prompts/recon.py +199 -0
- openhack/prompts/reporter.py +88 -0
- openhack/prompts/researchers.py +434 -0
- openhack/prompts/sandbox_verifier.py +128 -0
- openhack/prompts/supabase/__init__.py +39 -0
- openhack/prompts/supabase/auth_tokens.py +131 -0
- openhack/prompts/supabase/edge_functions.py +150 -0
- openhack/prompts/supabase/graphql.py +102 -0
- openhack/prompts/supabase/postgrest.py +99 -0
- openhack/prompts/supabase/realtime.py +93 -0
- openhack/prompts/supabase/rls.py +110 -0
- openhack/prompts/supabase/rpc_functions.py +127 -0
- openhack/prompts/supabase/storage.py +110 -0
- openhack/prompts/supabase/tenant_isolation.py +118 -0
- openhack/prompts/validator.py +319 -0
- openhack/prompts/validator_continuation_incomplete.py +12 -0
- openhack/prompts/validator_tool_instructions.py +29 -0
- openhack/quality.py +231 -0
- openhack/sandbox/__init__.py +12 -0
- openhack/sandbox/orchestrator.py +517 -0
- openhack/sandbox/runner.py +177 -0
- openhack/scan_session.py +245 -0
- openhack/setup.py +452 -0
- openhack/static_validator.py +612 -0
- openhack/tools/__init__.py +1 -0
- openhack/tools/ast_tools.py +307 -0
- openhack/tools/coverage.py +1078 -0
- openhack/tools/filesystem.py +404 -0
- openhack/tools/nextjs.py +258 -0
- openhack/tools/registry.py +52 -0
- openhack/tui.py +3450 -0
- openhack/updates.py +170 -0
- openhack-0.1.0.dist-info/METADATA +189 -0
- openhack-0.1.0.dist-info/RECORD +113 -0
- openhack-0.1.0.dist-info/WHEEL +4 -0
- openhack-0.1.0.dist-info/entry_points.txt +2 -0
- openhack-0.1.0.dist-info/licenses/LICENSE +661 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Next.js CSRF (Cross-Site Request Forgery) detection prompt.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
NEXTJS_CSRF_PROMPT = """## CSRF (Cross-Site Request Forgery) Detection in Next.js
|
|
6
|
+
|
|
7
|
+
### What to Look For
|
|
8
|
+
|
|
9
|
+
1. **State-changing operations without CSRF tokens**
|
|
10
|
+
2. **Server Actions without proper validation**
|
|
11
|
+
3. **API routes accepting mutations without origin checks**
|
|
12
|
+
|
|
13
|
+
### Next.js Specific Patterns
|
|
14
|
+
|
|
15
|
+
**Server Actions (Next.js 14+)**:
|
|
16
|
+
Server Actions have built-in CSRF protection via the `next-action` header, BUT:
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
'use server'
|
|
20
|
+
// POTENTIALLY VULNERABLE: If called via direct POST without header check
|
|
21
|
+
async function deleteAccount() {
|
|
22
|
+
const session = await getSession();
|
|
23
|
+
await db.user.delete({ where: { id: session.userId } });
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**API Routes (Vulnerable)**:
|
|
28
|
+
```typescript
|
|
29
|
+
// pages/api/user/delete.ts
|
|
30
|
+
export default async function handler(req, res) {
|
|
31
|
+
if (req.method !== 'POST') return res.status(405).end();
|
|
32
|
+
|
|
33
|
+
// VULNERABLE: No CSRF token validation
|
|
34
|
+
const session = await getSession(req);
|
|
35
|
+
await db.user.delete({ where: { id: session.userId } });
|
|
36
|
+
res.json({ success: true });
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Route Handlers (App Router)**:
|
|
41
|
+
```typescript
|
|
42
|
+
// app/api/transfer/route.ts
|
|
43
|
+
export async function POST(req: Request) {
|
|
44
|
+
// VULNERABLE: No origin/referer check, no CSRF token
|
|
45
|
+
const { to, amount } = await req.json();
|
|
46
|
+
await transferMoney(to, amount);
|
|
47
|
+
return Response.json({ success: true });
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Protection Checks
|
|
52
|
+
|
|
53
|
+
1. Look for CSRF token validation in forms/API calls
|
|
54
|
+
2. Check for `SameSite` cookie attributes
|
|
55
|
+
3. Verify origin/referer header checks on sensitive endpoints
|
|
56
|
+
4. Check if using libraries like `csrf` or `next-auth` (which handles CSRF)
|
|
57
|
+
|
|
58
|
+
### Search Patterns
|
|
59
|
+
|
|
60
|
+
1. `grep` for: state-changing operations (delete, update, create, transfer)
|
|
61
|
+
2. Check if they validate CSRF tokens
|
|
62
|
+
3. Look for `SameSite` in cookie configuration
|
|
63
|
+
4. Check `next-auth` config for CSRF settings
|
|
64
|
+
|
|
65
|
+
### Severity Assessment
|
|
66
|
+
|
|
67
|
+
- **Critical**: Financial transactions, account deletion without CSRF
|
|
68
|
+
- **High**: Data modification affecting user security
|
|
69
|
+
- **Medium**: Non-sensitive data modification
|
|
70
|
+
- **Low**: Actions with limited impact
|
|
71
|
+
"""
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Next.js sensitive data exposure detection prompt.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
NEXTJS_DATA_EXPOSURE_PROMPT = """## Sensitive Data Exposure in Next.js
|
|
6
|
+
|
|
7
|
+
### What to Look For
|
|
8
|
+
|
|
9
|
+
1. **Secrets in client bundles**
|
|
10
|
+
2. **Sensitive data in server component props**
|
|
11
|
+
3. **Verbose error messages**
|
|
12
|
+
4. **Exposed environment variables**
|
|
13
|
+
|
|
14
|
+
### Client Bundle Leaks
|
|
15
|
+
|
|
16
|
+
**Exposed Env Variables**:
|
|
17
|
+
```typescript
|
|
18
|
+
// VULNERABLE: NEXT_PUBLIC_ exposes to client
|
|
19
|
+
// .env
|
|
20
|
+
NEXT_PUBLIC_API_KEY=secret123 // Exposed in browser!
|
|
21
|
+
DATABASE_URL=... // Safe, server only
|
|
22
|
+
|
|
23
|
+
// next.config.js
|
|
24
|
+
module.exports = {
|
|
25
|
+
env: {
|
|
26
|
+
SECRET_KEY: process.env.SECRET_KEY, // EXPOSED to client!
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Server-to-Client Data Leak**:
|
|
32
|
+
```tsx
|
|
33
|
+
// VULNERABLE: Server component passing sensitive data to client
|
|
34
|
+
async function Page() {
|
|
35
|
+
const user = await db.user.findUnique({
|
|
36
|
+
where: { id: session.userId },
|
|
37
|
+
include: { password: true } // Oops!
|
|
38
|
+
});
|
|
39
|
+
return <ClientComponent user={user} />; // Password sent to client!
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### API Response Leaks
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
// VULNERABLE: Returning full user object
|
|
47
|
+
export async function GET() {
|
|
48
|
+
const users = await db.user.findMany();
|
|
49
|
+
return Response.json(users); // Includes passwords, tokens, etc!
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// SAFE: Select specific fields
|
|
53
|
+
export async function GET() {
|
|
54
|
+
const users = await db.user.findMany({
|
|
55
|
+
select: { id: true, name: true, email: true }
|
|
56
|
+
});
|
|
57
|
+
return Response.json(users);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Error Information Leaks
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// VULNERABLE: Exposing stack traces
|
|
65
|
+
export async function GET() {
|
|
66
|
+
try {
|
|
67
|
+
// ...
|
|
68
|
+
} catch (error) {
|
|
69
|
+
return Response.json({ error: error.stack }); // Stack trace exposed!
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Search Patterns
|
|
75
|
+
|
|
76
|
+
1. `grep` for: `NEXT_PUBLIC_` env vars (check what's exposed)
|
|
77
|
+
2. Check `next.config.js` for `env` configuration
|
|
78
|
+
3. `grep` for: `.env` file reads
|
|
79
|
+
4. Look for full model objects passed to client components
|
|
80
|
+
5. Check error handlers for verbose messages
|
|
81
|
+
|
|
82
|
+
### Severity Assessment
|
|
83
|
+
|
|
84
|
+
- **Critical**: API keys, database credentials exposed
|
|
85
|
+
- **High**: User passwords, tokens, PII exposed
|
|
86
|
+
- **Medium**: Internal paths, versions exposed
|
|
87
|
+
- **Low**: Non-sensitive debug information
|
|
88
|
+
"""
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Next.js IDOR (Insecure Direct Object Reference) detection prompt.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
NEXTJS_IDOR_PROMPT = """## IDOR (Insecure Direct Object Reference) Detection in Next.js
|
|
6
|
+
|
|
7
|
+
### What to Look For
|
|
8
|
+
|
|
9
|
+
1. **Route parameters used directly in database queries**
|
|
10
|
+
- App Router: `params.id` in route handlers or server components
|
|
11
|
+
- Pages Router: `req.query.id` in API routes
|
|
12
|
+
|
|
13
|
+
2. **Missing ownership verification**
|
|
14
|
+
- User can access resources belonging to other users
|
|
15
|
+
- No check that `resource.userId === session.userId`
|
|
16
|
+
|
|
17
|
+
3. **Predictable IDs**
|
|
18
|
+
- Sequential numeric IDs (1, 2, 3...)
|
|
19
|
+
- UUIDs are safer but not sufficient alone
|
|
20
|
+
|
|
21
|
+
### Next.js Specific Patterns
|
|
22
|
+
|
|
23
|
+
**App Router (Vulnerable)**:
|
|
24
|
+
```typescript
|
|
25
|
+
// app/api/users/[id]/route.ts
|
|
26
|
+
export async function GET(req: Request, { params }: { params: { id: string } }) {
|
|
27
|
+
// VULNERABLE: No auth check, direct ID usage
|
|
28
|
+
const user = await db.user.findUnique({ where: { id: params.id } });
|
|
29
|
+
return Response.json(user);
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Pages Router (Vulnerable)**:
|
|
34
|
+
```typescript
|
|
35
|
+
// pages/api/posts/[id].ts
|
|
36
|
+
export default async function handler(req, res) {
|
|
37
|
+
// VULNERABLE: Anyone can access any post by ID
|
|
38
|
+
const post = await prisma.post.findUnique({ where: { id: req.query.id } });
|
|
39
|
+
res.json(post);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Server Actions (Vulnerable)**:
|
|
44
|
+
```typescript
|
|
45
|
+
'use server'
|
|
46
|
+
async function getDocument(documentId: string) {
|
|
47
|
+
// VULNERABLE: No ownership check
|
|
48
|
+
return await db.document.findUnique({ where: { id: documentId } });
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Search Patterns
|
|
53
|
+
|
|
54
|
+
1. `grep` for: `params\\.\\w+`, `req\\.query`, `searchParams\\.get`
|
|
55
|
+
2. Check if these values go directly to database queries
|
|
56
|
+
3. Look for missing session/auth checks before the query
|
|
57
|
+
|
|
58
|
+
### Severity Assessment
|
|
59
|
+
|
|
60
|
+
- **Critical**: Access to other users' sensitive data (PII, financial)
|
|
61
|
+
- **High**: Access to other users' content/resources
|
|
62
|
+
- **Medium**: Access to metadata or non-sensitive resources
|
|
63
|
+
- **Low**: Informational leaks with no security impact
|
|
64
|
+
"""
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Next.js injection vulnerabilities detection prompt.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
NEXTJS_INJECTION_PROMPT = """## Injection Vulnerabilities in Next.js
|
|
6
|
+
|
|
7
|
+
### SQL Injection
|
|
8
|
+
|
|
9
|
+
**Prisma (Usually Safe)**:
|
|
10
|
+
```typescript
|
|
11
|
+
// SAFE: Parameterized query
|
|
12
|
+
await prisma.user.findMany({ where: { email: userInput } });
|
|
13
|
+
|
|
14
|
+
// VULNERABLE: Raw query with interpolation
|
|
15
|
+
await prisma.$queryRaw`SELECT * FROM users WHERE email = '${userInput}'`;
|
|
16
|
+
await prisma.$executeRawUnsafe(`DELETE FROM users WHERE id = ${id}`);
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Raw Database Drivers**:
|
|
20
|
+
```typescript
|
|
21
|
+
// VULNERABLE: String concatenation
|
|
22
|
+
const result = await pool.query(`SELECT * FROM users WHERE id = '${userId}'`);
|
|
23
|
+
|
|
24
|
+
// SAFE: Parameterized
|
|
25
|
+
const result = await pool.query('SELECT * FROM users WHERE id = $1', [userId]);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### NoSQL Injection (MongoDB)
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// VULNERABLE: Object injection
|
|
32
|
+
const user = await User.findOne({ email: req.body.email, password: req.body.password });
|
|
33
|
+
// Attack: { "email": "admin@example.com", "password": { "$ne": "" } }
|
|
34
|
+
|
|
35
|
+
// SAFE: Type validation
|
|
36
|
+
const email = String(req.body.email);
|
|
37
|
+
const password = String(req.body.password);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Command Injection
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
// VULNERABLE
|
|
44
|
+
import { exec } from 'child_process';
|
|
45
|
+
exec(`convert ${userFilename} output.png`); // Command injection!
|
|
46
|
+
|
|
47
|
+
// SAFE: Use execFile with arguments array
|
|
48
|
+
import { execFile } from 'child_process';
|
|
49
|
+
execFile('convert', [userFilename, 'output.png']);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Search Patterns
|
|
53
|
+
|
|
54
|
+
1. `grep` for: `\\$queryRaw`, `\\$executeRaw`, `query\\(.*\\$\\{`
|
|
55
|
+
2. `grep` for: `exec\\(`, `execSync\\(`, `spawn\\(`
|
|
56
|
+
3. `grep` for: `eval\\(`, `new Function\\(`
|
|
57
|
+
4. Look for string interpolation with user input in queries
|
|
58
|
+
|
|
59
|
+
### Severity Assessment
|
|
60
|
+
|
|
61
|
+
- **Critical**: SQL injection allowing data extraction or modification
|
|
62
|
+
- **Critical**: Command injection allowing code execution
|
|
63
|
+
- **High**: NoSQL injection with auth bypass
|
|
64
|
+
- **Medium**: Limited injection with restricted impact
|
|
65
|
+
"""
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Next.js middleware bypass vulnerabilities detection prompt.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
NEXTJS_MIDDLEWARE_BYPASS_PROMPT = """## Next.js Middleware Bypass Vulnerabilities
|
|
6
|
+
|
|
7
|
+
### Path Normalization Issues
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
// middleware.ts
|
|
11
|
+
export function middleware(req: NextRequest) {
|
|
12
|
+
const path = req.nextUrl.pathname;
|
|
13
|
+
|
|
14
|
+
// VULNERABLE: Can be bypassed
|
|
15
|
+
if (path.startsWith('/admin')) {
|
|
16
|
+
// Bypass attempts:
|
|
17
|
+
// - /Admin (case sensitivity)
|
|
18
|
+
// - /admin/../admin (path traversal)
|
|
19
|
+
// - /%61dmin (URL encoding)
|
|
20
|
+
// - /admin. or /admin/ (trailing characters)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Matcher Pattern Gaps
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
export const config = {
|
|
29
|
+
// VULNERABLE patterns:
|
|
30
|
+
matcher: '/api/:path*', // Misses /api (no trailing path)
|
|
31
|
+
matcher: ['/dashboard', '/admin'], // Misses /dashboard/settings
|
|
32
|
+
|
|
33
|
+
// BETTER patterns:
|
|
34
|
+
matcher: ['/api/:path*', '/api'],
|
|
35
|
+
matcher: ['/(dashboard|admin)/:path*'],
|
|
36
|
+
};
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Static File Bypass
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
// middleware.ts
|
|
43
|
+
export function middleware(req) {
|
|
44
|
+
// VULNERABLE: Attackers can add _next/static to path
|
|
45
|
+
// Request: /admin?_next/static/bypass
|
|
46
|
+
if (req.nextUrl.pathname.includes('_next/static')) {
|
|
47
|
+
return NextResponse.next(); // Bypass!
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Rewrite/Redirect Issues
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
// VULNERABLE: Redirect without validation
|
|
56
|
+
export function middleware(req) {
|
|
57
|
+
const redirect = req.nextUrl.searchParams.get('redirect');
|
|
58
|
+
return NextResponse.redirect(redirect); // Open redirect!
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Search Patterns
|
|
63
|
+
|
|
64
|
+
1. Read `middleware.ts` completely
|
|
65
|
+
2. Check matcher patterns for gaps
|
|
66
|
+
3. Look for path-based auth logic
|
|
67
|
+
4. Check for redirect/rewrite with user input
|
|
68
|
+
|
|
69
|
+
### Severity Assessment
|
|
70
|
+
|
|
71
|
+
- **Critical**: Auth bypass to admin areas
|
|
72
|
+
- **High**: Auth bypass to user data
|
|
73
|
+
- **Medium**: Bypass to non-sensitive areas
|
|
74
|
+
- **Low**: Minor path handling issues
|
|
75
|
+
"""
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Next.js security misconfigurations detection prompt.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
NEXTJS_MISCONFIGURATION_PROMPT = """## Security Misconfigurations in Next.js
|
|
6
|
+
|
|
7
|
+
### Security Headers
|
|
8
|
+
|
|
9
|
+
**next.config.js**:
|
|
10
|
+
```javascript
|
|
11
|
+
// Check for security headers
|
|
12
|
+
module.exports = {
|
|
13
|
+
async headers() {
|
|
14
|
+
return [
|
|
15
|
+
{
|
|
16
|
+
source: '/:path*',
|
|
17
|
+
headers: [
|
|
18
|
+
// SHOULD HAVE:
|
|
19
|
+
{ key: 'X-Frame-Options', value: 'DENY' },
|
|
20
|
+
{ key: 'X-Content-Type-Options', value: 'nosniff' },
|
|
21
|
+
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
|
|
22
|
+
{ key: 'Content-Security-Policy', value: "default-src 'self'" },
|
|
23
|
+
{ key: 'Strict-Transport-Security', value: 'max-age=31536000; includeSubDomains' },
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### CORS Configuration
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// VULNERABLE: Wildcard CORS
|
|
35
|
+
export async function GET(req: Request) {
|
|
36
|
+
return new Response(data, {
|
|
37
|
+
headers: {
|
|
38
|
+
'Access-Control-Allow-Origin': '*', // Too permissive!
|
|
39
|
+
'Access-Control-Allow-Credentials': 'true', // Dangerous with *
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Exposed .next Directory
|
|
46
|
+
|
|
47
|
+
Check if `.next` directory is accessible:
|
|
48
|
+
- `/.next/server/pages-manifest.json`
|
|
49
|
+
- `/.next/BUILD_ID`
|
|
50
|
+
|
|
51
|
+
### Debug Mode in Production
|
|
52
|
+
|
|
53
|
+
```javascript
|
|
54
|
+
// next.config.js
|
|
55
|
+
module.exports = {
|
|
56
|
+
// VULNERABLE in production:
|
|
57
|
+
reactStrictMode: false,
|
|
58
|
+
productionBrowserSourceMaps: true, // Exposes source code!
|
|
59
|
+
};
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Insecure redirects/rewrites
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
// next.config.js
|
|
66
|
+
module.exports = {
|
|
67
|
+
async redirects() {
|
|
68
|
+
return [
|
|
69
|
+
{
|
|
70
|
+
source: '/redirect',
|
|
71
|
+
destination: '/:path*', // VULNERABLE: Open redirect potential
|
|
72
|
+
permanent: false,
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Search Patterns
|
|
80
|
+
|
|
81
|
+
1. Read `next.config.js` completely
|
|
82
|
+
2. Check for security headers configuration
|
|
83
|
+
3. Look for CORS settings in API routes
|
|
84
|
+
4. Check for `productionBrowserSourceMaps`
|
|
85
|
+
5. Review redirect/rewrite rules
|
|
86
|
+
|
|
87
|
+
### Severity Assessment
|
|
88
|
+
|
|
89
|
+
- **High**: Missing critical security headers, wildcard CORS with credentials
|
|
90
|
+
- **Medium**: Missing some headers, overly permissive CORS
|
|
91
|
+
- **Low**: Missing optional headers, minor misconfigurations
|
|
92
|
+
"""
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Next.js server actions security detection prompt.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
NEXTJS_SERVER_ACTIONS_PROMPT = """## Server Actions Security in Next.js
|
|
6
|
+
|
|
7
|
+
### What to Look For
|
|
8
|
+
|
|
9
|
+
1. **Missing input validation**
|
|
10
|
+
2. **Missing authentication checks**
|
|
11
|
+
3. **Mass assignment vulnerabilities**
|
|
12
|
+
4. **Race conditions**
|
|
13
|
+
|
|
14
|
+
### Authentication in Server Actions
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
'use server'
|
|
18
|
+
|
|
19
|
+
// VULNERABLE: No auth check
|
|
20
|
+
export async function deletePost(postId: string) {
|
|
21
|
+
await db.post.delete({ where: { id: postId } });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// SAFE: Auth check
|
|
25
|
+
export async function deletePost(postId: string) {
|
|
26
|
+
const session = await auth();
|
|
27
|
+
if (!session) throw new Error('Unauthorized');
|
|
28
|
+
|
|
29
|
+
const post = await db.post.findUnique({ where: { id: postId } });
|
|
30
|
+
if (post.authorId !== session.user.id) throw new Error('Forbidden');
|
|
31
|
+
|
|
32
|
+
await db.post.delete({ where: { id: postId } });
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Input Validation
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
'use server'
|
|
40
|
+
|
|
41
|
+
// VULNERABLE: No validation
|
|
42
|
+
export async function updateUser(data: FormData) {
|
|
43
|
+
const name = data.get('name');
|
|
44
|
+
const email = data.get('email');
|
|
45
|
+
await db.user.update({
|
|
46
|
+
where: { id: session.userId },
|
|
47
|
+
data: { name, email } // What if email is malicious?
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// SAFE: Validate with Zod
|
|
52
|
+
import { z } from 'zod';
|
|
53
|
+
const schema = z.object({
|
|
54
|
+
name: z.string().min(1).max(100),
|
|
55
|
+
email: z.string().email(),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
export async function updateUser(data: FormData) {
|
|
59
|
+
const validated = schema.parse({
|
|
60
|
+
name: data.get('name'),
|
|
61
|
+
email: data.get('email'),
|
|
62
|
+
});
|
|
63
|
+
// ...
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Mass Assignment
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
'use server'
|
|
71
|
+
|
|
72
|
+
// VULNERABLE: Spreading all form data
|
|
73
|
+
export async function updateProfile(data: FormData) {
|
|
74
|
+
const updates = Object.fromEntries(data);
|
|
75
|
+
await db.user.update({
|
|
76
|
+
where: { id: session.userId },
|
|
77
|
+
data: updates, // User could add: role: 'admin'!
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Search Patterns
|
|
83
|
+
|
|
84
|
+
1. `grep` for: `'use server'` and `"use server"`
|
|
85
|
+
2. Check each server action for:
|
|
86
|
+
- Session/auth validation
|
|
87
|
+
- Input validation (zod, yup, etc.)
|
|
88
|
+
- Ownership checks on resources
|
|
89
|
+
3. Look for `Object.fromEntries` or spread operators with form data
|
|
90
|
+
|
|
91
|
+
### Severity Assessment
|
|
92
|
+
|
|
93
|
+
- **Critical**: Unauthenticated server actions modifying data
|
|
94
|
+
- **High**: Missing authorization checks (IDOR via server actions)
|
|
95
|
+
- **Medium**: Missing input validation with limited impact
|
|
96
|
+
- **Low**: Minor validation gaps
|
|
97
|
+
"""
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Next.js SSRF (Server-Side Request Forgery) detection prompt.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
NEXTJS_SSRF_PROMPT = """## SSRF (Server-Side Request Forgery) Detection in Next.js
|
|
6
|
+
|
|
7
|
+
### What to Look For
|
|
8
|
+
|
|
9
|
+
1. **User-controlled URLs in server-side fetch/axios calls**
|
|
10
|
+
2. **URL parameters used in API requests**
|
|
11
|
+
3. **Image/file fetching from user-provided URLs**
|
|
12
|
+
|
|
13
|
+
### Next.js Specific Patterns
|
|
14
|
+
|
|
15
|
+
**Route Handlers / API Routes**:
|
|
16
|
+
```typescript
|
|
17
|
+
// VULNERABLE: User-controlled URL
|
|
18
|
+
export async function GET(req: Request) {
|
|
19
|
+
const url = new URL(req.url).searchParams.get('url');
|
|
20
|
+
const response = await fetch(url); // SSRF!
|
|
21
|
+
return Response.json(await response.json());
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Server Components**:
|
|
26
|
+
```typescript
|
|
27
|
+
// VULNERABLE: URL from searchParams used in fetch
|
|
28
|
+
async function Page({ searchParams }) {
|
|
29
|
+
const data = await fetch(searchParams.apiUrl); // SSRF!
|
|
30
|
+
return <div>{data}</div>;
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Image Optimization**:
|
|
35
|
+
```typescript
|
|
36
|
+
// next.config.js - Check remotePatterns
|
|
37
|
+
module.exports = {
|
|
38
|
+
images: {
|
|
39
|
+
// VULNERABLE: Too permissive
|
|
40
|
+
remotePatterns: [{ protocol: 'https', hostname: '**' }],
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Webhook Handlers**:
|
|
46
|
+
```typescript
|
|
47
|
+
// VULNERABLE: Fetching user-provided callback URL
|
|
48
|
+
async function handleWebhook(callbackUrl: string, data: any) {
|
|
49
|
+
await fetch(callbackUrl, { method: 'POST', body: JSON.stringify(data) });
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Search Patterns
|
|
54
|
+
|
|
55
|
+
1. `grep` for: `fetch\\(.*(?:req|params|query|searchParams)`
|
|
56
|
+
2. `grep` for: `axios\\.(?:get|post)\\(.*(?:req|params|query)`
|
|
57
|
+
3. `grep` for: URL construction with user input
|
|
58
|
+
4. Check `next.config.js` for `images.remotePatterns`
|
|
59
|
+
|
|
60
|
+
### Severity Assessment
|
|
61
|
+
|
|
62
|
+
- **Critical**: Can reach internal services, cloud metadata (169.254.169.254)
|
|
63
|
+
- **High**: Can scan internal network, access internal APIs
|
|
64
|
+
- **Medium**: Limited internal access, some filtering in place
|
|
65
|
+
- **Low**: External SSRF only, minimal impact
|
|
66
|
+
"""
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Next.js XSS (Cross-Site Scripting) detection prompt.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
NEXTJS_XSS_PROMPT = """## XSS (Cross-Site Scripting) Detection in Next.js
|
|
6
|
+
|
|
7
|
+
### What to Look For
|
|
8
|
+
|
|
9
|
+
1. **dangerouslySetInnerHTML with user input**
|
|
10
|
+
2. **Unescaped rendering in non-React contexts**
|
|
11
|
+
3. **DOM manipulation with user data**
|
|
12
|
+
4. **URL-based XSS via searchParams/query**
|
|
13
|
+
|
|
14
|
+
### Next.js Specific Patterns
|
|
15
|
+
|
|
16
|
+
**React (Usually Safe)**:
|
|
17
|
+
React auto-escapes by default, but watch for:
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
// VULNERABLE: dangerouslySetInnerHTML with user content
|
|
21
|
+
function Comment({ content }) {
|
|
22
|
+
return <div dangerouslySetInnerHTML={{ __html: content }} />;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// VULNERABLE: User input in href without validation
|
|
26
|
+
function Link({ url }) {
|
|
27
|
+
return <a href={url}>Click</a>; // javascript: URLs are XSS
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// VULNERABLE: User input in event handlers
|
|
31
|
+
function Button({ onClick }) {
|
|
32
|
+
return <button onClick={() => eval(onClick)}>Click</button>;
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Server Components (App Router)**:
|
|
37
|
+
```tsx
|
|
38
|
+
// Less XSS risk but watch for:
|
|
39
|
+
async function Page({ searchParams }) {
|
|
40
|
+
// If this HTML is rendered unsafely downstream
|
|
41
|
+
const userHtml = searchParams.content;
|
|
42
|
+
return <RenderMarkdown content={userHtml} />; // Depends on RenderMarkdown implementation
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**API Routes returning HTML**:
|
|
47
|
+
```typescript
|
|
48
|
+
// pages/api/preview.ts
|
|
49
|
+
export default function handler(req, res) {
|
|
50
|
+
// VULNERABLE: Reflecting user input as HTML
|
|
51
|
+
res.setHeader('Content-Type', 'text/html');
|
|
52
|
+
res.send(`<html><body>${req.query.content}</body></html>`);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Search Patterns
|
|
57
|
+
|
|
58
|
+
1. `grep` for: `dangerouslySetInnerHTML`, `innerHTML`, `__html`
|
|
59
|
+
2. `grep` for: `document\\.write`, `eval\\(`, `new Function\\(`
|
|
60
|
+
3. Look for user input flowing to these sinks
|
|
61
|
+
4. Check markdown/rich text renderers for sanitization
|
|
62
|
+
|
|
63
|
+
### Severity Assessment
|
|
64
|
+
|
|
65
|
+
- **Critical**: Stored XSS affecting all users
|
|
66
|
+
- **High**: Reflected XSS requiring social engineering
|
|
67
|
+
- **Medium**: Self-XSS or limited scope
|
|
68
|
+
- **Low**: XSS with significant barriers to exploitation
|
|
69
|
+
"""
|