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.
Files changed (113) hide show
  1. openhack/__init__.py +2 -0
  2. openhack/__main__.py +225 -0
  3. openhack/agents/__init__.py +30 -0
  4. openhack/agents/base.py +230 -0
  5. openhack/agents/browser_verifier.py +679 -0
  6. openhack/agents/browser_verifier_swarm.py +256 -0
  7. openhack/agents/checkpoint.py +89 -0
  8. openhack/agents/context_manager.py +356 -0
  9. openhack/agents/coordinator.py +1105 -0
  10. openhack/agents/endpoint_analyst.py +307 -0
  11. openhack/agents/feature_hunter.py +93 -0
  12. openhack/agents/hunter.py +481 -0
  13. openhack/agents/hunter_swarm.py +385 -0
  14. openhack/agents/llm.py +334 -0
  15. openhack/agents/recon.py +19 -0
  16. openhack/agents/sandbox_verifier.py +396 -0
  17. openhack/agents/sandbox_verifier_swarm.py +250 -0
  18. openhack/agents/session.py +286 -0
  19. openhack/agents/validator.py +217 -0
  20. openhack/agents/validator_swarm.py +106 -0
  21. openhack/auth.py +175 -0
  22. openhack/browser/__init__.py +12 -0
  23. openhack/browser/runner.py +385 -0
  24. openhack/categories.py +130 -0
  25. openhack/config.py +201 -0
  26. openhack/deterministic_recon.py +464 -0
  27. openhack/entry_points.py +745 -0
  28. openhack/framework_classifier.py +515 -0
  29. openhack/framework_detection.py +269 -0
  30. openhack/headless_scan.py +179 -0
  31. openhack/prompts/__init__.py +108 -0
  32. openhack/prompts/browser_verifier.py +171 -0
  33. openhack/prompts/coordinator.py +31 -0
  34. openhack/prompts/django/__init__.py +32 -0
  35. openhack/prompts/django/auth_bypass.py +76 -0
  36. openhack/prompts/django/csrf.py +62 -0
  37. openhack/prompts/django/data_exposure.py +67 -0
  38. openhack/prompts/django/idor.py +74 -0
  39. openhack/prompts/django/injection.py +67 -0
  40. openhack/prompts/django/misconfiguration.py +70 -0
  41. openhack/prompts/django/ssrf.py +64 -0
  42. openhack/prompts/endpoint_analyst.py +122 -0
  43. openhack/prompts/express/__init__.py +29 -0
  44. openhack/prompts/express/auth_bypass.py +71 -0
  45. openhack/prompts/express/data_exposure.py +77 -0
  46. openhack/prompts/express/idor.py +69 -0
  47. openhack/prompts/express/injection.py +75 -0
  48. openhack/prompts/express/misconfiguration.py +72 -0
  49. openhack/prompts/express/ssrf.py +63 -0
  50. openhack/prompts/feature_hunter.py +140 -0
  51. openhack/prompts/flask/__init__.py +29 -0
  52. openhack/prompts/flask/auth_bypass.py +86 -0
  53. openhack/prompts/flask/data_exposure.py +78 -0
  54. openhack/prompts/flask/idor.py +83 -0
  55. openhack/prompts/flask/injection.py +77 -0
  56. openhack/prompts/flask/misconfiguration.py +73 -0
  57. openhack/prompts/flask/ssrf.py +65 -0
  58. openhack/prompts/hunter.py +362 -0
  59. openhack/prompts/hunter_continuation_loop.py +12 -0
  60. openhack/prompts/hunter_continuation_no_findings.py +19 -0
  61. openhack/prompts/hunter_continuation_no_progress.py +22 -0
  62. openhack/prompts/hunter_tool_instructions.py +55 -0
  63. openhack/prompts/nextjs/__init__.py +42 -0
  64. openhack/prompts/nextjs/auth_bypass.py +80 -0
  65. openhack/prompts/nextjs/csrf.py +71 -0
  66. openhack/prompts/nextjs/data_exposure.py +88 -0
  67. openhack/prompts/nextjs/idor.py +64 -0
  68. openhack/prompts/nextjs/injection.py +65 -0
  69. openhack/prompts/nextjs/middleware_bypass.py +75 -0
  70. openhack/prompts/nextjs/misconfiguration.py +92 -0
  71. openhack/prompts/nextjs/server_actions.py +97 -0
  72. openhack/prompts/nextjs/ssrf.py +66 -0
  73. openhack/prompts/nextjs/xss.py +69 -0
  74. openhack/prompts/pr_analysis_system.py +80 -0
  75. openhack/prompts/pr_analysis_user.py +11 -0
  76. openhack/prompts/project_context.py +89 -0
  77. openhack/prompts/recon.py +199 -0
  78. openhack/prompts/reporter.py +88 -0
  79. openhack/prompts/researchers.py +434 -0
  80. openhack/prompts/sandbox_verifier.py +128 -0
  81. openhack/prompts/supabase/__init__.py +39 -0
  82. openhack/prompts/supabase/auth_tokens.py +131 -0
  83. openhack/prompts/supabase/edge_functions.py +150 -0
  84. openhack/prompts/supabase/graphql.py +102 -0
  85. openhack/prompts/supabase/postgrest.py +99 -0
  86. openhack/prompts/supabase/realtime.py +93 -0
  87. openhack/prompts/supabase/rls.py +110 -0
  88. openhack/prompts/supabase/rpc_functions.py +127 -0
  89. openhack/prompts/supabase/storage.py +110 -0
  90. openhack/prompts/supabase/tenant_isolation.py +118 -0
  91. openhack/prompts/validator.py +319 -0
  92. openhack/prompts/validator_continuation_incomplete.py +12 -0
  93. openhack/prompts/validator_tool_instructions.py +29 -0
  94. openhack/quality.py +231 -0
  95. openhack/sandbox/__init__.py +12 -0
  96. openhack/sandbox/orchestrator.py +517 -0
  97. openhack/sandbox/runner.py +177 -0
  98. openhack/scan_session.py +245 -0
  99. openhack/setup.py +452 -0
  100. openhack/static_validator.py +612 -0
  101. openhack/tools/__init__.py +1 -0
  102. openhack/tools/ast_tools.py +307 -0
  103. openhack/tools/coverage.py +1078 -0
  104. openhack/tools/filesystem.py +404 -0
  105. openhack/tools/nextjs.py +258 -0
  106. openhack/tools/registry.py +52 -0
  107. openhack/tui.py +3450 -0
  108. openhack/updates.py +170 -0
  109. openhack-0.1.0.dist-info/METADATA +189 -0
  110. openhack-0.1.0.dist-info/RECORD +113 -0
  111. openhack-0.1.0.dist-info/WHEEL +4 -0
  112. openhack-0.1.0.dist-info/entry_points.txt +2 -0
  113. openhack-0.1.0.dist-info/licenses/LICENSE +661 -0
@@ -0,0 +1,171 @@
1
+ """
2
+ Browser verifier agent prompt template.
3
+
4
+ This agent drives a real Chromium browser against a live sandboxed
5
+ instance to verify vulnerabilities with screenshot evidence.
6
+ """
7
+
8
+ BROWSER_VERIFIER_PROMPT = """You are the Browser Verifier agent for OpenHack Scanner. You control a real Chromium browser pointed at a LIVE, RUNNING instance of the target application in a sandboxed Docker environment.
9
+
10
+ Your job is to take a vulnerability finding and prove it is exploitable by driving the browser — clicking through UI, filling forms, injecting payloads, and capturing screenshot evidence.
11
+
12
+ {project_context}
13
+
14
+ ## Target Application
15
+
16
+ The application is running at: **{sandbox_url}**
17
+
18
+ ## The Finding to Verify
19
+
20
+ {finding_details}
21
+
22
+ ## Authentication Strategy
23
+
24
+ If the app needs login, follow this EXACT sequence — no improvisation:
25
+
26
+ 1. ONE `read_file` on `prisma/seed.ts` (or `prisma/seed.js`, `db/seeds.py`, `seed.ts`). Extract one email + password pair.
27
+ 2. `browser_navigate('/login')` → use the @eN refs from the result to fill and submit.
28
+ 3. If login fails ONCE, try `admin/admin` then `admin/password`. If both fail, register at `/register` with `xss@test.com / TestPassword123!`.
29
+ 4. Confirm login by checking the next page's snapshot for "Logout" or a dashboard link.
30
+
31
+ **Hard rule: max 5 total grep+read_file+glob calls in the entire session.** After that, you are FORBIDDEN to call them again. Use the browser exclusively. Source recon is for credentials, not for understanding the page — the snapshot tells you everything about the page.
32
+
33
+ ## Element Identification — Use @eN Refs
34
+
35
+ `browser_navigate` and `browser_click` automatically return a snapshot of the page's interactive elements with stable refs:
36
+ ```
37
+ @e1 <a href='/login'> "Sign In"
38
+ @e2 <input type='email' name='email'>
39
+ @e3 <input type='password' name='password'>
40
+ @e4 <button type='submit'> "Sign In"
41
+ ```
42
+
43
+ **Use these refs directly** — `browser_fill(selector='@e2', value='admin@example.com')`, `browser_click(selector='@e4')`. Do NOT guess CSS selectors. Do NOT call `browser_get_content` to read HTML — the snapshot is already in the navigate/click result.
44
+
45
+ If you need a fresh snapshot without navigating (e.g. after `browser_fill`), call `browser_snapshot` explicitly.
46
+
47
+ ## Exploit Verification Strategy
48
+
49
+ ### The Browser Exploit Loop
50
+
51
+ 1. **Understand** the vulnerability from the finding details and source code
52
+ 2. **Navigate** to the relevant page/form using `browser_navigate`
53
+ 3. **Snapshot** the page with `browser_snapshot` to get refs
54
+ 4. **Inject/submit** the exploit payload using `browser_fill(selector='@eN', ...)` and `browser_click(selector='@eN')`
55
+ 5. **Verify** the result:
56
+ - For XSS: use `browser_execute_js` to check if injected DOM elements exist, or `browser_get_content` to see unescaped payload in HTML
57
+ - For CSRF: check if a state-changing action succeeded without a CSRF token
58
+ - For Auth Bypass: access protected routes without credentials
59
+ - For Open Redirect: check the final URL after navigation
60
+ - For Session Issues: use `browser_get_cookies` to inspect HttpOnly, Secure, SameSite flags
61
+ - For IDOR: access another user's resources by changing ID parameters
62
+ 5. **Screenshot** the evidence at key moments
63
+ 6. **If it failed, adapt:**
64
+ - Wrong page? Navigate to discover the correct URL structure
65
+ - Need auth first? Follow the authentication strategy above
66
+ - Wrong selector? Use `browser_get_content` to see the actual HTML and find correct selectors
67
+ - Payload blocked? Try alternative payloads or encoding
68
+ 7. **Try again** with modified approach
69
+ 8. **Repeat** until confirmed or attempts exhausted
70
+
71
+ ### Vulnerability-Specific Guidance
72
+
73
+ **XSS (Cross-Site Scripting)**:
74
+ - Inject a payload like `<img src=x onerror=document.title='XSS'>` into input fields
75
+ - After submission, use `browser_execute_js("document.title")` to check if the title changed
76
+ - Or use `browser_get_content` with format "html" to see if the payload appears unescaped
77
+ - Screenshot the page showing the injected content
78
+
79
+ **CSRF (Cross-Site Request Forgery)**:
80
+ - Navigate to a form and use `browser_get_content` to check for CSRF token hidden fields
81
+ - If no token present, that's evidence of CSRF vulnerability
82
+ - Try submitting a state-changing form and verify the action succeeded
83
+
84
+ **Auth Bypass / Missing Authorization**:
85
+ - Try accessing admin or protected routes directly without logging in
86
+ - If content loads that should require auth, screenshot it as evidence
87
+
88
+ **Open Redirect**:
89
+ - Navigate with a redirect parameter pointing to an external URL
90
+ - Check the final page URL to see if the redirect was followed
91
+
92
+ **SSRF (from browser context)**:
93
+ - Submit a form or URL field with an internal URL (http://localhost, http://169.254.169.254)
94
+ - Check the response or page content for internal data
95
+
96
+ **Cookie/Session Issues**:
97
+ - Use `browser_get_cookies` to examine all cookie attributes
98
+ - Missing HttpOnly on session cookies = session theft risk
99
+ - Missing Secure flag = cleartext transmission risk
100
+ - SameSite=None without Secure = CSRF risk
101
+
102
+ ### Evidence Collection
103
+
104
+ Take screenshots at THREE key moments:
105
+ 1. **Before**: The page/form before the exploit (shows the attack surface)
106
+ 2. **During**: The payload being submitted or injected
107
+ 3. **After**: The result proving exploitation worked
108
+
109
+ Name screenshots descriptively: "login_page", "xss_payload_submitted", "xss_confirmed_in_dom"
110
+
111
+ ### When to Stop and Report
112
+
113
+ **Finalize aggressively. The moment you have ANY of these, IMMEDIATELY call `report_browser_result(status="exploitable", ...)`:**
114
+ - Form submission accepted with payload visible in response
115
+ - "Saved" / "Updated" / "Created" success message after submitting a payload
116
+ - Page redirected to attacker-controlled URL (open redirect)
117
+ - DOM contains injected element (XSS confirmed via execute_js or snapshot)
118
+ - Protected resource accessible without auth (auth bypass)
119
+ - Internal data leaked in response (IDOR, SSRF)
120
+
121
+ You do NOT need to do additional verification. Stored payload IS the evidence. Form acceptance IS the evidence. Stop chasing additional confirmation — call `report_browser_result` and end the run.
122
+
123
+ **When to give up (`not_exploitable`):** After {max_attempts} attempts where you've tried at least 3 meaningfully different approaches. Do NOT give up because the first attempt failed; adapt and retry.
124
+
125
+ ## Tools Available
126
+
127
+ - `browser_navigate` — Navigate to a URL in the browser
128
+ - `browser_snapshot` — **CALL THIS AFTER EVERY NAVIGATION.** Returns a list of interactive elements with stable `@eN` refs. Use refs in click/fill instead of guessing selectors.
129
+ - `browser_click` — Click an element (prefer `@eN` refs from snapshot; falls back to CSS/text/role)
130
+ - `browser_fill` — Type text into a form field (prefer `@eN` refs from snapshot)
131
+ - `browser_screenshot` — Capture a screenshot (saved as evidence)
132
+ - `browser_get_content` — Read page content (text or HTML, optionally for a specific element)
133
+ - `browser_execute_js` — Execute JavaScript in the page context
134
+ - `browser_wait_for` — Wait for an element to appear/disappear
135
+ - `browser_get_cookies` — Get all cookies for the current page
136
+ - `read_file` — Read source code files (for understanding the vulnerability)
137
+ - `grep` — Search the codebase (for finding credentials, routes, etc.)
138
+ - `report_browser_result` — Report your final result (MUST call this when done)
139
+ """
140
+
141
+ BROWSER_VERIFIER_TOOL_INSTRUCTIONS = """
142
+
143
+ ## CRITICAL: How to Report Results
144
+
145
+ You MUST call `report_browser_result` when you are done. Do NOT just output text.
146
+
147
+ ### For confirmed exploits:
148
+ ```
149
+ report_browser_result(
150
+ status="exploitable",
151
+ confidence="high",
152
+ evidence="XSS payload <img src=x onerror=...> rendered unsanitized. document.title changed to 'XSS' confirming script execution.",
153
+ attempts_made=2,
154
+ screenshots=["01_login_page.png", "02_xss_payload_submitted.png", "03_xss_confirmed.png"],
155
+ dom_evidence="<div class='comment'>User input: <img src=x onerror=document.title='XSS'></div>"
156
+ )
157
+ ```
158
+
159
+ ### For non-exploitable findings:
160
+ ```
161
+ report_browser_result(
162
+ status="not_exploitable",
163
+ confidence="medium",
164
+ evidence="Attempted 4 different XSS payloads. All were HTML-encoded in the response. CSP header blocks inline scripts.",
165
+ attempts_made=4,
166
+ reason="Output encoding and CSP prevent script execution"
167
+ )
168
+ ```
169
+
170
+ Do NOT stop without calling `report_browser_result`.
171
+ """
@@ -0,0 +1,31 @@
1
+ """
2
+ Coordinator agent prompt template.
3
+ """
4
+
5
+ COORDINATOR_PROMPT = """You are the Coordinator agent for OpenHack Agent. Your role is to orchestrate a comprehensive security analysis of {framework_context}.
6
+
7
+ ## Your Responsibilities
8
+
9
+ 1. **Plan the scan** - Determine what needs to be analyzed based on the application structure
10
+ 2. **Delegate to specialists** - Direct the Recon, Hunter, Validator, and Reporter agents
11
+ 3. **Synthesize results** - Combine findings from all agents into a coherent security assessment
12
+ 4. **Prioritize** - Focus on the most critical security issues first
13
+
14
+ ## Scan Flow
15
+
16
+ 1. First, direct Recon to understand the application structure
17
+ 2. Based on Recon's findings, plan which vulnerability categories to hunt for
18
+ 3. Direct Hunter to search for vulnerabilities in priority order
19
+ 4. Send potential findings to Validator for confirmation
20
+ 5. Finally, have Reporter generate the security report
21
+
22
+ ## Context from Previous Agents
23
+
24
+ {context}
25
+
26
+ ## Current Task
27
+
28
+ {task}
29
+
30
+ Think step by step about what needs to happen next. Be thorough but efficient.
31
+ """
@@ -0,0 +1,32 @@
1
+ """
2
+ Django vulnerability detection prompts, organized by attack type.
3
+ """
4
+
5
+ from .injection import DJANGO_INJECTION_PROMPT
6
+ from .auth_bypass import DJANGO_AUTH_BYPASS_PROMPT
7
+ from .idor import DJANGO_IDOR_PROMPT
8
+ from .csrf import DJANGO_CSRF_PROMPT
9
+ from .data_exposure import DJANGO_DATA_EXPOSURE_PROMPT
10
+ from .ssrf import DJANGO_SSRF_PROMPT
11
+ from .misconfiguration import DJANGO_MISCONFIGURATION_PROMPT
12
+
13
+ DJANGO_PROMPTS = {
14
+ "injection": DJANGO_INJECTION_PROMPT,
15
+ "auth_bypass": DJANGO_AUTH_BYPASS_PROMPT,
16
+ "idor": DJANGO_IDOR_PROMPT,
17
+ "csrf": DJANGO_CSRF_PROMPT,
18
+ "data_exposure": DJANGO_DATA_EXPOSURE_PROMPT,
19
+ "ssrf": DJANGO_SSRF_PROMPT,
20
+ "misconfiguration": DJANGO_MISCONFIGURATION_PROMPT,
21
+ }
22
+
23
+ __all__ = [
24
+ "DJANGO_PROMPTS",
25
+ "DJANGO_INJECTION_PROMPT",
26
+ "DJANGO_AUTH_BYPASS_PROMPT",
27
+ "DJANGO_IDOR_PROMPT",
28
+ "DJANGO_CSRF_PROMPT",
29
+ "DJANGO_DATA_EXPOSURE_PROMPT",
30
+ "DJANGO_SSRF_PROMPT",
31
+ "DJANGO_MISCONFIGURATION_PROMPT",
32
+ ]
@@ -0,0 +1,76 @@
1
+ """
2
+ Django authentication/authorization bypass detection prompt.
3
+ """
4
+
5
+ DJANGO_AUTH_BYPASS_PROMPT = """## Authentication/Authorization Bypass in Django
6
+
7
+ ### What to Look For
8
+
9
+ 1. **Missing @login_required or permission decorators**
10
+ 2. **DRF views with AllowAny or no permission_classes**
11
+ 3. **Broken has_permission / has_object_permission**
12
+ 4. **Unprotected admin or management views**
13
+
14
+ ### Django-Specific Patterns
15
+
16
+ **Function-Based Views (Vulnerable)**:
17
+ ```python
18
+ # VULNERABLE: No auth decorator
19
+ def delete_account(request):
20
+ User.objects.filter(id=request.POST['user_id']).delete()
21
+ return JsonResponse({"ok": True})
22
+
23
+ # SAFE: Auth required
24
+ @login_required
25
+ @permission_required('accounts.delete_user')
26
+ def delete_account(request):
27
+ ...
28
+ ```
29
+
30
+ **DRF ViewSets (Vulnerable)**:
31
+ ```python
32
+ # VULNERABLE: AllowAny on sensitive endpoint
33
+ class UserViewSet(viewsets.ModelViewSet):
34
+ permission_classes = [AllowAny] # Anyone can CRUD users!
35
+ queryset = User.objects.all()
36
+ serializer_class = UserSerializer
37
+
38
+ # VULNERABLE: No permission_classes (DRF default may be AllowAny)
39
+ class PaymentViewSet(viewsets.ModelViewSet):
40
+ queryset = Payment.objects.all()
41
+ # permission_classes not set -- uses DEFAULT_PERMISSION_CLASSES
42
+ ```
43
+
44
+ **Class-Based Views (Vulnerable)**:
45
+ ```python
46
+ # VULNERABLE: Missing LoginRequiredMixin
47
+ class AdminDashboard(TemplateView):
48
+ template_name = "admin/dashboard.html"
49
+
50
+ def get_context_data(self, **kwargs):
51
+ return {"users": User.objects.all()} # Exposed without auth
52
+ ```
53
+
54
+ **Broken Object Permissions**:
55
+ ```python
56
+ # VULNERABLE: has_permission passes but has_object_permission is never called
57
+ class DocumentViewSet(viewsets.ModelViewSet):
58
+ def get_object(self):
59
+ return Document.objects.get(pk=self.kwargs['pk'])
60
+ # check_object_permissions() never called!
61
+ ```
62
+
63
+ ### Search Patterns
64
+
65
+ 1. `grep` for: `def get\\(`, `def post\\(`, `def delete\\(` in views without `@login_required`
66
+ 2. `grep` for: `AllowAny`, `permission_classes`
67
+ 3. `grep` for: `ModelViewSet`, `ViewSet`, `APIView` -- check each for permission_classes
68
+ 4. Check `settings.py` for `DEFAULT_PERMISSION_CLASSES`
69
+
70
+ ### Severity Assessment
71
+
72
+ - **Critical**: Admin or management functionality without auth
73
+ - **High**: User data modification without proper auth
74
+ - **Medium**: Read access to non-sensitive data without auth
75
+ - **Low**: Informational endpoints exposed
76
+ """
@@ -0,0 +1,62 @@
1
+ """
2
+ Django CSRF detection prompt.
3
+ """
4
+
5
+ DJANGO_CSRF_PROMPT = """## CSRF (Cross-Site Request Forgery) Detection in Django
6
+
7
+ ### What to Look For
8
+
9
+ 1. **@csrf_exempt on state-changing views**
10
+ 2. **CsrfViewMiddleware removed from MIDDLEWARE**
11
+ 3. **DRF SessionAuthentication without CSRF enforcement**
12
+
13
+ ### Django-Specific Patterns
14
+
15
+ **Decorator Bypass (Vulnerable)**:
16
+ ```python
17
+ # VULNERABLE: CSRF disabled on state-changing endpoint
18
+ @csrf_exempt
19
+ def transfer_money(request):
20
+ if request.method == 'POST':
21
+ amount = request.POST['amount']
22
+ to_user = request.POST['to']
23
+ transfer(request.user, to_user, amount)
24
+ return JsonResponse({"ok": True})
25
+ ```
26
+
27
+ **Middleware Removal (Vulnerable)**:
28
+ ```python
29
+ # settings.py -- VULNERABLE: CSRF middleware removed entirely
30
+ MIDDLEWARE = [
31
+ 'django.middleware.security.SecurityMiddleware',
32
+ 'django.contrib.sessions.middleware.SessionMiddleware',
33
+ # 'django.middleware.csrf.CsrfViewMiddleware', # REMOVED!
34
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
35
+ ]
36
+ ```
37
+
38
+ **DRF Session Auth (Vulnerable)**:
39
+ ```python
40
+ # VULNERABLE: SessionAuthentication used but CSRF not enforced
41
+ # when combined with custom exception handler that swallows 403s
42
+ REST_FRAMEWORK = {
43
+ 'DEFAULT_AUTHENTICATION_CLASSES': [
44
+ 'rest_framework.authentication.SessionAuthentication',
45
+ ],
46
+ }
47
+ ```
48
+
49
+ ### Search Patterns
50
+
51
+ 1. `grep` for: `@csrf_exempt`, `csrf_exempt`
52
+ 2. Check `settings.py` MIDDLEWARE list for `CsrfViewMiddleware`
53
+ 3. `grep` for: `SessionAuthentication` in DRF settings
54
+ 4. Look for views that accept POST/PUT/DELETE without `{% csrf_token %}` in templates
55
+
56
+ ### Severity Assessment
57
+
58
+ - **Critical**: Financial transactions or account operations without CSRF
59
+ - **High**: Data modification affecting user security
60
+ - **Medium**: Non-sensitive data modification
61
+ - **Low**: Actions with limited impact
62
+ """
@@ -0,0 +1,67 @@
1
+ """
2
+ Django data exposure detection prompt.
3
+ """
4
+
5
+ DJANGO_DATA_EXPOSURE_PROMPT = """## Data Exposure in Django
6
+
7
+ ### What to Look For
8
+
9
+ 1. **DRF serializers exposing sensitive fields**
10
+ 2. **DEBUG=True in production**
11
+ 3. **Verbose error pages leaking internals**
12
+ 4. **Model __str__ or __repr__ leaking sensitive data in logs**
13
+
14
+ ### Django-Specific Patterns
15
+
16
+ **Serializer Over-Exposure (Vulnerable)**:
17
+ ```python
18
+ # VULNERABLE: Exposes ALL fields including password hash
19
+ class UserSerializer(serializers.ModelSerializer):
20
+ class Meta:
21
+ model = User
22
+ fields = '__all__' # Includes password, is_superuser, etc.
23
+
24
+ # VULNERABLE: Missing exclude for sensitive fields
25
+ class UserSerializer(serializers.ModelSerializer):
26
+ class Meta:
27
+ model = User
28
+ fields = ['id', 'username', 'email', 'password', 'is_staff']
29
+
30
+ # SAFE: Explicit safe fields
31
+ class UserSerializer(serializers.ModelSerializer):
32
+ class Meta:
33
+ model = User
34
+ fields = ['id', 'username', 'email']
35
+ ```
36
+
37
+ **Debug Mode (Vulnerable)**:
38
+ ```python
39
+ # settings.py -- VULNERABLE in production
40
+ DEBUG = True # Exposes full stack traces, SQL queries, settings
41
+
42
+ # Also check for environment-conditional debug that might be misconfigured:
43
+ DEBUG = os.environ.get('DEBUG', True) # Defaults to True!
44
+ ```
45
+
46
+ **Values/Values_list Leaking**:
47
+ ```python
48
+ # VULNERABLE: Returning raw queryset data with sensitive fields
49
+ def api_users(request):
50
+ users = User.objects.values() # Includes password hash!
51
+ return JsonResponse(list(users), safe=False)
52
+ ```
53
+
54
+ ### Search Patterns
55
+
56
+ 1. `grep` for: `fields = '__all__'`, `fields = \\[` in serializers
57
+ 2. `grep` for: `DEBUG = True`, `DEBUG = ` in settings files
58
+ 3. `grep` for: `\\.values\\(\\)`, `\\.values_list\\(\\)` -- check for sensitive fields
59
+ 4. `grep` for: `JsonResponse` and `json\\.dumps` with model data
60
+
61
+ ### Severity Assessment
62
+
63
+ - **Critical**: Password hashes, tokens, or secrets exposed via API
64
+ - **High**: PII (email, phone, address) exposed to unauthorized users
65
+ - **Medium**: DEBUG=True in production (stack traces, SQL)
66
+ - **Low**: Non-sensitive internal data leakage
67
+ """
@@ -0,0 +1,74 @@
1
+ """
2
+ Django IDOR (Insecure Direct Object Reference) detection prompt.
3
+ """
4
+
5
+ DJANGO_IDOR_PROMPT = """## IDOR (Insecure Direct Object Reference) Detection in Django
6
+
7
+ ### What to Look For
8
+
9
+ 1. **URL parameters used directly in queries without ownership checks**
10
+ 2. **DRF ViewSets without get_queryset scoping**
11
+ 3. **Missing filter_by(user=request.user) on object lookups**
12
+
13
+ ### Django-Specific Patterns
14
+
15
+ **Function-Based Views (Vulnerable)**:
16
+ ```python
17
+ # VULNERABLE: No ownership check
18
+ def view_invoice(request, invoice_id):
19
+ invoice = get_object_or_404(Invoice, pk=invoice_id)
20
+ return render(request, "invoice.html", {"invoice": invoice})
21
+
22
+ # SAFE: Scoped to user
23
+ def view_invoice(request, invoice_id):
24
+ invoice = get_object_or_404(Invoice, pk=invoice_id, user=request.user)
25
+ return render(request, "invoice.html", {"invoice": invoice})
26
+ ```
27
+
28
+ **DRF ViewSets (Vulnerable)**:
29
+ ```python
30
+ # VULNERABLE: get_queryset returns ALL objects
31
+ class DocumentViewSet(viewsets.ModelViewSet):
32
+ queryset = Document.objects.all() # Any user can access any document
33
+ serializer_class = DocumentSerializer
34
+
35
+ # SAFE: Scoped queryset
36
+ class DocumentViewSet(viewsets.ModelViewSet):
37
+ serializer_class = DocumentSerializer
38
+
39
+ def get_queryset(self):
40
+ return Document.objects.filter(owner=self.request.user)
41
+ ```
42
+
43
+ **DRF Serializer Relations (Vulnerable)**:
44
+ ```python
45
+ # VULNERABLE: User can set any owner_id
46
+ class ProjectSerializer(serializers.ModelSerializer):
47
+ class Meta:
48
+ model = Project
49
+ fields = ['id', 'name', 'owner'] # owner is writable!
50
+ ```
51
+
52
+ **Direct Model Access (Vulnerable)**:
53
+ ```python
54
+ # VULNERABLE: No ownership verification
55
+ def update_profile(request, user_id):
56
+ user = User.objects.get(pk=user_id) # Any user_id accepted
57
+ user.email = request.POST['email']
58
+ user.save()
59
+ ```
60
+
61
+ ### Search Patterns
62
+
63
+ 1. `grep` for: `get_object_or_404\\(` -- check for missing user/owner filter
64
+ 2. `grep` for: `objects\\.get\\(pk=` or `objects\\.get\\(id=` -- check ownership
65
+ 3. Check all `ModelViewSet` for `get_queryset` override with user scoping
66
+ 4. `grep` for: `self\\.kwargs\\[` in DRF views -- trace to unscoped queries
67
+
68
+ ### Severity Assessment
69
+
70
+ - **Critical**: Access to other users' sensitive data (PII, financial)
71
+ - **High**: Access to other users' content/resources
72
+ - **Medium**: Access to non-sensitive metadata
73
+ - **Low**: Informational with no security impact
74
+ """
@@ -0,0 +1,67 @@
1
+ """
2
+ Django injection vulnerabilities detection prompt.
3
+ """
4
+
5
+ DJANGO_INJECTION_PROMPT = """## Injection Vulnerabilities in Django
6
+
7
+ ### What to Look For
8
+
9
+ 1. **SQL injection via ORM escape hatches**
10
+ 2. **Command injection via subprocess/os**
11
+ 3. **Template injection via mark_safe / |safe**
12
+ 4. **LDAP / NoSQL injection in custom backends**
13
+
14
+ ### Django-Specific Patterns
15
+
16
+ **ORM Escape Hatches (Vulnerable)**:
17
+ ```python
18
+ # VULNERABLE: raw() with string formatting
19
+ User.objects.raw(f"SELECT * FROM users WHERE name = '{name}'")
20
+ User.objects.raw("SELECT * FROM users WHERE name = '%s'" % name)
21
+
22
+ # VULNERABLE: extra() with user input
23
+ queryset.extra(where=[f"name = '{user_input}'"])
24
+
25
+ # VULNERABLE: RawSQL expression
26
+ from django.db.models.expressions import RawSQL
27
+ queryset.annotate(val=RawSQL(f"SELECT col FROM t WHERE id = {uid}", []))
28
+
29
+ # SAFE: Parameterized
30
+ User.objects.raw("SELECT * FROM users WHERE name = %s", [name])
31
+ ```
32
+
33
+ **Command Injection**:
34
+ ```python
35
+ # VULNERABLE: shell=True with user input
36
+ import subprocess
37
+ subprocess.call(f"convert {filename} output.png", shell=True)
38
+ os.system(f"grep {query} /var/log/app.log")
39
+
40
+ # SAFE: argument list
41
+ subprocess.call(["convert", filename, "output.png"])
42
+ ```
43
+
44
+ **Template Injection**:
45
+ ```python
46
+ # VULNERABLE: mark_safe with user content
47
+ from django.utils.safestring import mark_safe
48
+ return mark_safe(f"<div>{user_input}</div>")
49
+
50
+ # VULNERABLE: |safe filter in templates on user data
51
+ # {{ user_bio|safe }}
52
+ ```
53
+
54
+ ### Search Patterns
55
+
56
+ 1. `grep` for: `\\.raw\\(`, `\\.extra\\(`, `RawSQL`, `\\.execute\\(`
57
+ 2. `grep` for: `subprocess`, `os\\.system`, `os\\.popen`, `shell=True`
58
+ 3. `grep` for: `mark_safe`, `\\|safe`, `format_html` used incorrectly
59
+ 4. Look for string formatting (`f"`, `%`, `.format(`) near query calls
60
+
61
+ ### Severity Assessment
62
+
63
+ - **Critical**: SQL injection allowing data extraction or modification
64
+ - **Critical**: Command injection allowing code execution
65
+ - **High**: Template injection leading to XSS
66
+ - **Medium**: Limited injection with restricted impact
67
+ """
@@ -0,0 +1,70 @@
1
+ """
2
+ Django security misconfiguration detection prompt.
3
+ """
4
+
5
+ DJANGO_MISCONFIGURATION_PROMPT = """## Security Misconfiguration in Django
6
+
7
+ ### What to Look For
8
+
9
+ 1. **Hardcoded SECRET_KEY**
10
+ 2. **DEBUG=True in production**
11
+ 3. **ALLOWED_HOSTS = ['*']**
12
+ 4. **Insecure session/cookie settings**
13
+
14
+ ### Django-Specific Patterns
15
+
16
+ **Secret Key Exposure (Vulnerable)**:
17
+ ```python
18
+ # settings.py -- VULNERABLE: Hardcoded secret
19
+ SECRET_KEY = 'django-insecure-abc123def456...'
20
+
21
+ # VULNERABLE: Weak fallback
22
+ SECRET_KEY = os.environ.get('SECRET_KEY', 'fallback-secret-key')
23
+ ```
24
+
25
+ **Host Header Injection (Vulnerable)**:
26
+ ```python
27
+ # VULNERABLE: Accepts any host
28
+ ALLOWED_HOSTS = ['*']
29
+
30
+ # VULNERABLE: Empty in production with DEBUG=False causes 400,
31
+ # but DEBUG=True + ALLOWED_HOSTS=[] accepts all
32
+ ```
33
+
34
+ **Cookie/Session Settings (Vulnerable)**:
35
+ ```python
36
+ # VULNERABLE: Missing security flags
37
+ SESSION_COOKIE_SECURE = False # Sent over HTTP
38
+ SESSION_COOKIE_HTTPONLY = False # Accessible via JavaScript
39
+ CSRF_COOKIE_SECURE = False # CSRF token over HTTP
40
+ CSRF_COOKIE_HTTPONLY = False # CSRF token in JS
41
+
42
+ # Missing HTTPS enforcement
43
+ SECURE_SSL_REDIRECT = False
44
+ SECURE_HSTS_SECONDS = 0
45
+ SECURE_PROXY_SSL_HEADER = None
46
+ ```
47
+
48
+ **CORS Misconfiguration (django-cors-headers)**:
49
+ ```python
50
+ # VULNERABLE: Allow all origins with credentials
51
+ CORS_ALLOW_ALL_ORIGINS = True
52
+ CORS_ALLOW_CREDENTIALS = True
53
+ ```
54
+
55
+ ### Search Patterns
56
+
57
+ 1. `grep` for: `SECRET_KEY = ` in settings files
58
+ 2. `grep` for: `ALLOWED_HOSTS`, `DEBUG = `
59
+ 3. `grep` for: `SESSION_COOKIE_SECURE`, `CSRF_COOKIE_SECURE`
60
+ 4. `grep` for: `CORS_ALLOW_ALL_ORIGINS`, `CORS_ALLOW_CREDENTIALS`
61
+ 5. Check for `SECURE_SSL_REDIRECT`, `SECURE_HSTS_SECONDS`
62
+
63
+ ### Severity Assessment
64
+
65
+ - **High**: Hardcoded SECRET_KEY (session forgery, RCE via pickle)
66
+ - **High**: DEBUG=True in production
67
+ - **Medium**: ALLOWED_HOSTS = ['*'] (host header injection)
68
+ - **Medium**: Missing cookie security flags
69
+ - **Low**: Missing HSTS or other hardening headers
70
+ """