strix-agent 0.4.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.
- strix/__init__.py +0 -0
- strix/agents/StrixAgent/__init__.py +4 -0
- strix/agents/StrixAgent/strix_agent.py +89 -0
- strix/agents/StrixAgent/system_prompt.jinja +404 -0
- strix/agents/__init__.py +10 -0
- strix/agents/base_agent.py +518 -0
- strix/agents/state.py +163 -0
- strix/interface/__init__.py +4 -0
- strix/interface/assets/tui_styles.tcss +694 -0
- strix/interface/cli.py +230 -0
- strix/interface/main.py +500 -0
- strix/interface/tool_components/__init__.py +39 -0
- strix/interface/tool_components/agents_graph_renderer.py +123 -0
- strix/interface/tool_components/base_renderer.py +62 -0
- strix/interface/tool_components/browser_renderer.py +120 -0
- strix/interface/tool_components/file_edit_renderer.py +99 -0
- strix/interface/tool_components/finish_renderer.py +31 -0
- strix/interface/tool_components/notes_renderer.py +108 -0
- strix/interface/tool_components/proxy_renderer.py +255 -0
- strix/interface/tool_components/python_renderer.py +34 -0
- strix/interface/tool_components/registry.py +72 -0
- strix/interface/tool_components/reporting_renderer.py +53 -0
- strix/interface/tool_components/scan_info_renderer.py +64 -0
- strix/interface/tool_components/terminal_renderer.py +131 -0
- strix/interface/tool_components/thinking_renderer.py +29 -0
- strix/interface/tool_components/user_message_renderer.py +43 -0
- strix/interface/tool_components/web_search_renderer.py +28 -0
- strix/interface/tui.py +1274 -0
- strix/interface/utils.py +559 -0
- strix/llm/__init__.py +15 -0
- strix/llm/config.py +20 -0
- strix/llm/llm.py +465 -0
- strix/llm/memory_compressor.py +212 -0
- strix/llm/request_queue.py +87 -0
- strix/llm/utils.py +87 -0
- strix/prompts/README.md +64 -0
- strix/prompts/__init__.py +109 -0
- strix/prompts/cloud/.gitkeep +0 -0
- strix/prompts/coordination/root_agent.jinja +41 -0
- strix/prompts/custom/.gitkeep +0 -0
- strix/prompts/frameworks/fastapi.jinja +142 -0
- strix/prompts/frameworks/nextjs.jinja +126 -0
- strix/prompts/protocols/graphql.jinja +215 -0
- strix/prompts/reconnaissance/.gitkeep +0 -0
- strix/prompts/technologies/firebase_firestore.jinja +177 -0
- strix/prompts/technologies/supabase.jinja +189 -0
- strix/prompts/vulnerabilities/authentication_jwt.jinja +147 -0
- strix/prompts/vulnerabilities/broken_function_level_authorization.jinja +146 -0
- strix/prompts/vulnerabilities/business_logic.jinja +171 -0
- strix/prompts/vulnerabilities/csrf.jinja +174 -0
- strix/prompts/vulnerabilities/idor.jinja +195 -0
- strix/prompts/vulnerabilities/information_disclosure.jinja +222 -0
- strix/prompts/vulnerabilities/insecure_file_uploads.jinja +188 -0
- strix/prompts/vulnerabilities/mass_assignment.jinja +141 -0
- strix/prompts/vulnerabilities/open_redirect.jinja +177 -0
- strix/prompts/vulnerabilities/path_traversal_lfi_rfi.jinja +142 -0
- strix/prompts/vulnerabilities/race_conditions.jinja +164 -0
- strix/prompts/vulnerabilities/rce.jinja +154 -0
- strix/prompts/vulnerabilities/sql_injection.jinja +151 -0
- strix/prompts/vulnerabilities/ssrf.jinja +135 -0
- strix/prompts/vulnerabilities/subdomain_takeover.jinja +155 -0
- strix/prompts/vulnerabilities/xss.jinja +169 -0
- strix/prompts/vulnerabilities/xxe.jinja +184 -0
- strix/runtime/__init__.py +19 -0
- strix/runtime/docker_runtime.py +399 -0
- strix/runtime/runtime.py +29 -0
- strix/runtime/tool_server.py +205 -0
- strix/telemetry/__init__.py +4 -0
- strix/telemetry/tracer.py +337 -0
- strix/tools/__init__.py +64 -0
- strix/tools/agents_graph/__init__.py +16 -0
- strix/tools/agents_graph/agents_graph_actions.py +621 -0
- strix/tools/agents_graph/agents_graph_actions_schema.xml +226 -0
- strix/tools/argument_parser.py +121 -0
- strix/tools/browser/__init__.py +4 -0
- strix/tools/browser/browser_actions.py +236 -0
- strix/tools/browser/browser_actions_schema.xml +183 -0
- strix/tools/browser/browser_instance.py +533 -0
- strix/tools/browser/tab_manager.py +342 -0
- strix/tools/executor.py +305 -0
- strix/tools/file_edit/__init__.py +4 -0
- strix/tools/file_edit/file_edit_actions.py +141 -0
- strix/tools/file_edit/file_edit_actions_schema.xml +128 -0
- strix/tools/finish/__init__.py +4 -0
- strix/tools/finish/finish_actions.py +174 -0
- strix/tools/finish/finish_actions_schema.xml +45 -0
- strix/tools/notes/__init__.py +14 -0
- strix/tools/notes/notes_actions.py +191 -0
- strix/tools/notes/notes_actions_schema.xml +150 -0
- strix/tools/proxy/__init__.py +20 -0
- strix/tools/proxy/proxy_actions.py +101 -0
- strix/tools/proxy/proxy_actions_schema.xml +267 -0
- strix/tools/proxy/proxy_manager.py +785 -0
- strix/tools/python/__init__.py +4 -0
- strix/tools/python/python_actions.py +47 -0
- strix/tools/python/python_actions_schema.xml +131 -0
- strix/tools/python/python_instance.py +172 -0
- strix/tools/python/python_manager.py +131 -0
- strix/tools/registry.py +196 -0
- strix/tools/reporting/__init__.py +6 -0
- strix/tools/reporting/reporting_actions.py +63 -0
- strix/tools/reporting/reporting_actions_schema.xml +30 -0
- strix/tools/terminal/__init__.py +4 -0
- strix/tools/terminal/terminal_actions.py +35 -0
- strix/tools/terminal/terminal_actions_schema.xml +146 -0
- strix/tools/terminal/terminal_manager.py +151 -0
- strix/tools/terminal/terminal_session.py +447 -0
- strix/tools/thinking/__init__.py +4 -0
- strix/tools/thinking/thinking_actions.py +18 -0
- strix/tools/thinking/thinking_actions_schema.xml +52 -0
- strix/tools/web_search/__init__.py +4 -0
- strix/tools/web_search/web_search_actions.py +80 -0
- strix/tools/web_search/web_search_actions_schema.xml +83 -0
- strix_agent-0.4.0.dist-info/LICENSE +201 -0
- strix_agent-0.4.0.dist-info/METADATA +282 -0
- strix_agent-0.4.0.dist-info/RECORD +118 -0
- strix_agent-0.4.0.dist-info/WHEEL +4 -0
- strix_agent-0.4.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import threading
|
|
5
|
+
import time
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import litellm
|
|
9
|
+
from litellm import ModelResponse, completion
|
|
10
|
+
from tenacity import retry, retry_if_exception, stop_after_attempt, wait_exponential
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def should_retry_exception(exception: Exception) -> bool:
|
|
17
|
+
status_code = None
|
|
18
|
+
|
|
19
|
+
if hasattr(exception, "status_code"):
|
|
20
|
+
status_code = exception.status_code
|
|
21
|
+
elif hasattr(exception, "response") and hasattr(exception.response, "status_code"):
|
|
22
|
+
status_code = exception.response.status_code
|
|
23
|
+
|
|
24
|
+
if status_code is not None:
|
|
25
|
+
return bool(litellm._should_retry(status_code))
|
|
26
|
+
return True
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class LLMRequestQueue:
|
|
30
|
+
def __init__(self, max_concurrent: int = 6, delay_between_requests: float = 5.0):
|
|
31
|
+
rate_limit_delay = os.getenv("LLM_RATE_LIMIT_DELAY")
|
|
32
|
+
if rate_limit_delay:
|
|
33
|
+
delay_between_requests = float(rate_limit_delay)
|
|
34
|
+
|
|
35
|
+
rate_limit_concurrent = os.getenv("LLM_RATE_LIMIT_CONCURRENT")
|
|
36
|
+
if rate_limit_concurrent:
|
|
37
|
+
max_concurrent = int(rate_limit_concurrent)
|
|
38
|
+
|
|
39
|
+
self.max_concurrent = max_concurrent
|
|
40
|
+
self.delay_between_requests = delay_between_requests
|
|
41
|
+
self._semaphore = threading.BoundedSemaphore(max_concurrent)
|
|
42
|
+
self._last_request_time = 0.0
|
|
43
|
+
self._lock = threading.Lock()
|
|
44
|
+
|
|
45
|
+
async def make_request(self, completion_args: dict[str, Any]) -> ModelResponse:
|
|
46
|
+
try:
|
|
47
|
+
while not self._semaphore.acquire(timeout=0.2):
|
|
48
|
+
await asyncio.sleep(0.1)
|
|
49
|
+
|
|
50
|
+
with self._lock:
|
|
51
|
+
now = time.time()
|
|
52
|
+
time_since_last = now - self._last_request_time
|
|
53
|
+
sleep_needed = max(0, self.delay_between_requests - time_since_last)
|
|
54
|
+
self._last_request_time = now + sleep_needed
|
|
55
|
+
|
|
56
|
+
if sleep_needed > 0:
|
|
57
|
+
await asyncio.sleep(sleep_needed)
|
|
58
|
+
|
|
59
|
+
return await self._reliable_request(completion_args)
|
|
60
|
+
finally:
|
|
61
|
+
self._semaphore.release()
|
|
62
|
+
|
|
63
|
+
@retry( # type: ignore[misc]
|
|
64
|
+
stop=stop_after_attempt(7),
|
|
65
|
+
wait=wait_exponential(multiplier=6, min=12, max=150),
|
|
66
|
+
retry=retry_if_exception(should_retry_exception),
|
|
67
|
+
reraise=True,
|
|
68
|
+
)
|
|
69
|
+
async def _reliable_request(self, completion_args: dict[str, Any]) -> ModelResponse:
|
|
70
|
+
response = completion(**completion_args, stream=False)
|
|
71
|
+
if isinstance(response, ModelResponse):
|
|
72
|
+
return response
|
|
73
|
+
self._raise_unexpected_response()
|
|
74
|
+
raise RuntimeError("Unreachable code")
|
|
75
|
+
|
|
76
|
+
def _raise_unexpected_response(self) -> None:
|
|
77
|
+
raise RuntimeError("Unexpected response type")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
_global_queue: LLMRequestQueue | None = None
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_global_queue() -> LLMRequestQueue:
|
|
84
|
+
global _global_queue # noqa: PLW0603
|
|
85
|
+
if _global_queue is None:
|
|
86
|
+
_global_queue = LLMRequestQueue()
|
|
87
|
+
return _global_queue
|
strix/llm/utils.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import html
|
|
2
|
+
import re
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _truncate_to_first_function(content: str) -> str:
|
|
7
|
+
if not content:
|
|
8
|
+
return content
|
|
9
|
+
|
|
10
|
+
function_starts = [match.start() for match in re.finditer(r"<function=", content)]
|
|
11
|
+
|
|
12
|
+
if len(function_starts) >= 2:
|
|
13
|
+
second_function_start = function_starts[1]
|
|
14
|
+
|
|
15
|
+
return content[:second_function_start].rstrip()
|
|
16
|
+
|
|
17
|
+
return content
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def parse_tool_invocations(content: str) -> list[dict[str, Any]] | None:
|
|
21
|
+
content = _fix_stopword(content)
|
|
22
|
+
|
|
23
|
+
tool_invocations: list[dict[str, Any]] = []
|
|
24
|
+
|
|
25
|
+
fn_regex_pattern = r"<function=([^>]+)>\n?(.*?)</function>"
|
|
26
|
+
fn_param_regex_pattern = r"<parameter=([^>]+)>(.*?)</parameter>"
|
|
27
|
+
|
|
28
|
+
fn_matches = re.finditer(fn_regex_pattern, content, re.DOTALL)
|
|
29
|
+
|
|
30
|
+
for fn_match in fn_matches:
|
|
31
|
+
fn_name = fn_match.group(1)
|
|
32
|
+
fn_body = fn_match.group(2)
|
|
33
|
+
|
|
34
|
+
param_matches = re.finditer(fn_param_regex_pattern, fn_body, re.DOTALL)
|
|
35
|
+
|
|
36
|
+
args = {}
|
|
37
|
+
for param_match in param_matches:
|
|
38
|
+
param_name = param_match.group(1)
|
|
39
|
+
param_value = param_match.group(2).strip()
|
|
40
|
+
|
|
41
|
+
param_value = html.unescape(param_value)
|
|
42
|
+
args[param_name] = param_value
|
|
43
|
+
|
|
44
|
+
tool_invocations.append({"toolName": fn_name, "args": args})
|
|
45
|
+
|
|
46
|
+
return tool_invocations if tool_invocations else None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _fix_stopword(content: str) -> str:
|
|
50
|
+
if "<function=" in content and content.count("<function=") == 1:
|
|
51
|
+
if content.endswith("</"):
|
|
52
|
+
content = content.rstrip() + "function>"
|
|
53
|
+
elif not content.rstrip().endswith("</function>"):
|
|
54
|
+
content = content + "\n</function>"
|
|
55
|
+
return content
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def format_tool_call(tool_name: str, args: dict[str, Any]) -> str:
|
|
59
|
+
xml_parts = [f"<function={tool_name}>"]
|
|
60
|
+
|
|
61
|
+
for key, value in args.items():
|
|
62
|
+
xml_parts.append(f"<parameter={key}>{value}</parameter>")
|
|
63
|
+
|
|
64
|
+
xml_parts.append("</function>")
|
|
65
|
+
|
|
66
|
+
return "\n".join(xml_parts)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def clean_content(content: str) -> str:
|
|
70
|
+
if not content:
|
|
71
|
+
return ""
|
|
72
|
+
|
|
73
|
+
content = _fix_stopword(content)
|
|
74
|
+
|
|
75
|
+
tool_pattern = r"<function=[^>]+>.*?</function>"
|
|
76
|
+
cleaned = re.sub(tool_pattern, "", content, flags=re.DOTALL)
|
|
77
|
+
|
|
78
|
+
hidden_xml_patterns = [
|
|
79
|
+
r"<inter_agent_message>.*?</inter_agent_message>",
|
|
80
|
+
r"<agent_completion_report>.*?</agent_completion_report>",
|
|
81
|
+
]
|
|
82
|
+
for pattern in hidden_xml_patterns:
|
|
83
|
+
cleaned = re.sub(pattern, "", cleaned, flags=re.DOTALL | re.IGNORECASE)
|
|
84
|
+
|
|
85
|
+
cleaned = re.sub(r"\n\s*\n", "\n\n", cleaned)
|
|
86
|
+
|
|
87
|
+
return cleaned.strip()
|
strix/prompts/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# 📚 Strix Prompt Modules
|
|
2
|
+
|
|
3
|
+
## 🎯 Overview
|
|
4
|
+
|
|
5
|
+
Prompt modules are specialized knowledge packages that enhance Strix agents with deep expertise in specific vulnerability types, technologies, and testing methodologies. Each module provides advanced techniques, practical examples, and validation methods that go beyond baseline security knowledge.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 🏗️ Architecture
|
|
10
|
+
|
|
11
|
+
### How Prompts Work
|
|
12
|
+
|
|
13
|
+
When an agent is created, it can load up to 5 specialized prompt modules relevant to the specific subtask and context at hand:
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
# Agent creation with specialized modules
|
|
17
|
+
create_agent(
|
|
18
|
+
task="Test authentication mechanisms in API",
|
|
19
|
+
name="Auth Specialist",
|
|
20
|
+
prompt_modules="authentication_jwt,business_logic"
|
|
21
|
+
)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The modules are dynamically injected into the agent's system prompt, allowing it to operate with deep expertise tailored to the specific vulnerability types or technologies required for the task at hand.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 📁 Module Categories
|
|
29
|
+
|
|
30
|
+
| Category | Purpose |
|
|
31
|
+
|----------|---------|
|
|
32
|
+
| **`/vulnerabilities`** | Advanced testing techniques for core vulnerability classes like authentication bypasses, business logic flaws, and race conditions |
|
|
33
|
+
| **`/frameworks`** | Specific testing methods for popular frameworks e.g. Django, Express, FastAPI, and Next.js |
|
|
34
|
+
| **`/technologies`** | Specialized techniques for third-party services such as Supabase, Firebase, Auth0, and payment gateways |
|
|
35
|
+
| **`/protocols`** | Protocol-specific testing patterns for GraphQL, WebSocket, OAuth, and other communication standards |
|
|
36
|
+
| **`/cloud`** | Cloud provider security testing for AWS, Azure, GCP, and Kubernetes environments |
|
|
37
|
+
| **`/reconnaissance`** | Advanced information gathering and enumeration techniques for comprehensive attack surface mapping |
|
|
38
|
+
| **`/custom`** | Community-contributed modules for specialized or industry-specific testing scenarios |
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 🎨 Creating New Modules
|
|
43
|
+
|
|
44
|
+
### What Should a Module Contain?
|
|
45
|
+
|
|
46
|
+
A good prompt module is a structured knowledge package that typically includes:
|
|
47
|
+
|
|
48
|
+
- **Advanced techniques** - Non-obvious methods specific to the task and domain
|
|
49
|
+
- **Practical examples** - Working payloads, commands, or test cases with variations
|
|
50
|
+
- **Validation methods** - How to confirm findings and avoid false positives
|
|
51
|
+
- **Context-specific insights** - Environment and version nuances, configuration-dependent behavior, and edge cases
|
|
52
|
+
|
|
53
|
+
Modules use XML-style tags for structure and focus on deep, specialized knowledge that significantly enhances agent capabilities for that specific context.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 🤝 Contributing
|
|
58
|
+
|
|
59
|
+
Community contributions are more than welcome — contribute new modules via [pull requests](https://github.com/usestrix/strix/pulls) or [GitHub issues](https://github.com/usestrix/strix/issues) to help expand the collection and improve extensibility for Strix agents.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
> [!NOTE]
|
|
64
|
+
> **Work in Progress** - We're actively expanding the prompt module collection with specialized techniques and new categories.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from jinja2 import Environment
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_available_prompt_modules() -> dict[str, list[str]]:
|
|
7
|
+
modules_dir = Path(__file__).parent
|
|
8
|
+
available_modules = {}
|
|
9
|
+
|
|
10
|
+
for category_dir in modules_dir.iterdir():
|
|
11
|
+
if category_dir.is_dir() and not category_dir.name.startswith("__"):
|
|
12
|
+
category_name = category_dir.name
|
|
13
|
+
modules = []
|
|
14
|
+
|
|
15
|
+
for file_path in category_dir.glob("*.jinja"):
|
|
16
|
+
module_name = file_path.stem
|
|
17
|
+
modules.append(module_name)
|
|
18
|
+
|
|
19
|
+
if modules:
|
|
20
|
+
available_modules[category_name] = sorted(modules)
|
|
21
|
+
|
|
22
|
+
return available_modules
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_all_module_names() -> set[str]:
|
|
26
|
+
all_modules = set()
|
|
27
|
+
for category_modules in get_available_prompt_modules().values():
|
|
28
|
+
all_modules.update(category_modules)
|
|
29
|
+
return all_modules
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def validate_module_names(module_names: list[str]) -> dict[str, list[str]]:
|
|
33
|
+
available_modules = get_all_module_names()
|
|
34
|
+
valid_modules = []
|
|
35
|
+
invalid_modules = []
|
|
36
|
+
|
|
37
|
+
for module_name in module_names:
|
|
38
|
+
if module_name in available_modules:
|
|
39
|
+
valid_modules.append(module_name)
|
|
40
|
+
else:
|
|
41
|
+
invalid_modules.append(module_name)
|
|
42
|
+
|
|
43
|
+
return {"valid": valid_modules, "invalid": invalid_modules}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def generate_modules_description() -> str:
|
|
47
|
+
available_modules = get_available_prompt_modules()
|
|
48
|
+
|
|
49
|
+
if not available_modules:
|
|
50
|
+
return "No prompt modules available"
|
|
51
|
+
|
|
52
|
+
all_module_names = get_all_module_names()
|
|
53
|
+
|
|
54
|
+
if not all_module_names:
|
|
55
|
+
return "No prompt modules available"
|
|
56
|
+
|
|
57
|
+
sorted_modules = sorted(all_module_names)
|
|
58
|
+
modules_str = ", ".join(sorted_modules)
|
|
59
|
+
|
|
60
|
+
description = (
|
|
61
|
+
f"List of prompt modules to load for this agent (max 5). Available modules: {modules_str}. "
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
example_modules = sorted_modules[:2]
|
|
65
|
+
if example_modules:
|
|
66
|
+
example = f"Example: {', '.join(example_modules)} for specialized agent"
|
|
67
|
+
description += example
|
|
68
|
+
|
|
69
|
+
return description
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def load_prompt_modules(module_names: list[str], jinja_env: Environment) -> dict[str, str]:
|
|
73
|
+
import logging
|
|
74
|
+
|
|
75
|
+
logger = logging.getLogger(__name__)
|
|
76
|
+
module_content = {}
|
|
77
|
+
prompts_dir = Path(__file__).parent
|
|
78
|
+
|
|
79
|
+
available_modules = get_available_prompt_modules()
|
|
80
|
+
|
|
81
|
+
for module_name in module_names:
|
|
82
|
+
try:
|
|
83
|
+
module_path = None
|
|
84
|
+
|
|
85
|
+
if "/" in module_name:
|
|
86
|
+
module_path = f"{module_name}.jinja"
|
|
87
|
+
else:
|
|
88
|
+
for category, modules in available_modules.items():
|
|
89
|
+
if module_name in modules:
|
|
90
|
+
module_path = f"{category}/{module_name}.jinja"
|
|
91
|
+
break
|
|
92
|
+
|
|
93
|
+
if not module_path:
|
|
94
|
+
root_candidate = f"{module_name}.jinja"
|
|
95
|
+
if (prompts_dir / root_candidate).exists():
|
|
96
|
+
module_path = root_candidate
|
|
97
|
+
|
|
98
|
+
if module_path and (prompts_dir / module_path).exists():
|
|
99
|
+
template = jinja_env.get_template(module_path)
|
|
100
|
+
var_name = module_name.split("/")[-1]
|
|
101
|
+
module_content[var_name] = template.render()
|
|
102
|
+
logger.info(f"Loaded prompt module: {module_name} -> {var_name}")
|
|
103
|
+
else:
|
|
104
|
+
logger.warning(f"Prompt module not found: {module_name}")
|
|
105
|
+
|
|
106
|
+
except (FileNotFoundError, OSError, ValueError) as e:
|
|
107
|
+
logger.warning(f"Failed to load prompt module {module_name}: {e}")
|
|
108
|
+
|
|
109
|
+
return module_content
|
|
File without changes
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<coordination_role>
|
|
2
|
+
You are a COORDINATION AGENT ONLY. You do NOT perform any security testing, vulnerability assessment, or technical work yourself.
|
|
3
|
+
|
|
4
|
+
Your ONLY responsibilities:
|
|
5
|
+
1. Create specialized agents for specific security tasks
|
|
6
|
+
2. Monitor agent progress and coordinate between them
|
|
7
|
+
3. Compile final scan reports from agent findings
|
|
8
|
+
4. Manage agent communication and dependencies
|
|
9
|
+
|
|
10
|
+
CRITICAL RESTRICTIONS:
|
|
11
|
+
- NEVER perform vulnerability testing or security assessments
|
|
12
|
+
- NEVER write detailed vulnerability reports (only compile final summaries)
|
|
13
|
+
- ONLY use agent_graph and finish tools for coordination
|
|
14
|
+
- You can create agents throughout the scan process, depending on the task and findings, not just at the beginning!
|
|
15
|
+
</coordination_role>
|
|
16
|
+
|
|
17
|
+
<agent_management>
|
|
18
|
+
BEFORE CREATING AGENTS:
|
|
19
|
+
1. Analyze the target scope and break into independent tasks
|
|
20
|
+
2. Check existing agents to avoid duplication
|
|
21
|
+
3. Create agents with clear, specific objectives to avoid duplication
|
|
22
|
+
|
|
23
|
+
AGENT TYPES YOU CAN CREATE:
|
|
24
|
+
- Reconnaissance: subdomain enum, port scanning, tech identification, etc.
|
|
25
|
+
- Vulnerability Testing: SQL injection, XSS, auth bypass, IDOR, RCE, SSRF, etc. Can be black-box or white-box.
|
|
26
|
+
- Direct vulnerability testing agents to implement hierarchical workflow (per finding: discover, verify, report, fix): each one should create validation agents for findings verification, which spawn reporting agents for documentation, which create fix agents for remediation
|
|
27
|
+
|
|
28
|
+
COORDINATION GUIDELINES:
|
|
29
|
+
- Ensure clear task boundaries and success criteria
|
|
30
|
+
- Terminate redundant agents when objectives overlap
|
|
31
|
+
- Use message passing only when essential (requests/answers or critical handoffs); avoid routine status messages and prefer batched updates
|
|
32
|
+
</agent_management>
|
|
33
|
+
|
|
34
|
+
<final_responsibilities>
|
|
35
|
+
When all agents complete:
|
|
36
|
+
1. Collect findings from all agents
|
|
37
|
+
2. Compile a final scan summary report
|
|
38
|
+
3. Use finish tool to complete the assessment
|
|
39
|
+
|
|
40
|
+
Your value is in orchestration, not execution.
|
|
41
|
+
</final_responsibilities>
|
|
File without changes
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
<fastapi_security_testing_guide>
|
|
2
|
+
<title>FASTAPI — ADVERSARIAL TESTING PLAYBOOK</title>
|
|
3
|
+
|
|
4
|
+
<critical>FastAPI (on Starlette) spans HTTP, WebSocket, and background tasks with powerful dependency injection and automatic OpenAPI. Security breaks where identity, authorization, and validation drift across routers, middlewares, proxies, and channels. Treat every dependency, header, and object reference as untrusted until bound to the caller and tenant.</critical>
|
|
5
|
+
|
|
6
|
+
<surface_map>
|
|
7
|
+
- ASGI stack: Starlette middlewares (CORS, TrustedHost, ProxyHeaders, Session), exception handlers, lifespan events
|
|
8
|
+
- Routers/sub-apps: APIRouter with prefixes/tags, mounted apps (StaticFiles, admin subapps), `include_router`, versioned paths
|
|
9
|
+
- Security and DI: `Depends`, `Security`, `OAuth2PasswordBearer`, `HTTPBearer`, scopes, per-router vs per-route dependencies
|
|
10
|
+
- Models and validation: Pydantic v1/v2 models, unions/Annotated, custom validators, extra fields policy, coercion
|
|
11
|
+
- Docs and schema: `/openapi.json`, `/docs`, `/redoc`, alternative docs_url/redoc_url, schema extensions
|
|
12
|
+
- Files and static: `UploadFile`, `File`, `FileResponse`, `StaticFiles` mounts, template engines (`Jinja2Templates`)
|
|
13
|
+
- Channels: HTTP (sync/async), WebSocket, StreamingResponse/SSE, BackgroundTasks/Task queues
|
|
14
|
+
- Deployment: Uvicorn/Gunicorn, reverse proxies/CDN, TLS termination, header trust
|
|
15
|
+
</surface_map>
|
|
16
|
+
|
|
17
|
+
<methodology>
|
|
18
|
+
1. Enumerate routes from OpenAPI and via crawling; diff with 404-fuzzing for hidden endpoints (`include_in_schema=False`).
|
|
19
|
+
2. Build a Principal × Channel × Content-Type matrix (unauth, user, staff/admin; HTTP vs WebSocket; JSON/form/multipart) and capture baselines.
|
|
20
|
+
3. For each route, identify dependencies (router-level and route-level). Attempt to satisfy security dependencies minimally, then mutate context (tokens, scopes, tenant headers) and object IDs.
|
|
21
|
+
4. Compare behavior across deployments: dev/stage/prod often differ in middlewares (CORS, TrustedHost, ProxyHeaders) and docs exposure.
|
|
22
|
+
</methodology>
|
|
23
|
+
|
|
24
|
+
<high_value_targets>
|
|
25
|
+
- `/openapi.json`, `/docs`, `/redoc` in production (full attack surface map; securitySchemes and server URLs)
|
|
26
|
+
- Auth flows: token endpoints, session/cookie bridges, OAuth device/PKCE, scope checks
|
|
27
|
+
- Admin/staff routers, feature-flagged routes, `include_in_schema=False` endpoints
|
|
28
|
+
- File upload/download, import/export/report endpoints, signed URL generators
|
|
29
|
+
- WebSocket endpoints carrying notifications, admin channels, or commands
|
|
30
|
+
- Background job creation/fetch (`/jobs/{id}`, `/tasks/{id}/result`)
|
|
31
|
+
- Mounted subapps (admin UI, storage browsers, metrics/health endpoints)
|
|
32
|
+
</high_value_targets>
|
|
33
|
+
|
|
34
|
+
<advanced_techniques>
|
|
35
|
+
<openapi_and_docs>
|
|
36
|
+
- Try default and alternate locations: `/openapi.json`, `/docs`, `/redoc`, `/api/openapi.json`, `/internal/openapi.json`.
|
|
37
|
+
- If OpenAPI is exposed, mine: paths, parameter names, securitySchemes, scopes, servers; find endpoints hidden in UI but present in schema.
|
|
38
|
+
- Schema drift: endpoints with `include_in_schema=False` won’t appear—use wordlists based on tags/prefixes and common admin/debug names.
|
|
39
|
+
</openapi_and_docs>
|
|
40
|
+
|
|
41
|
+
<dependency_injection_and_security>
|
|
42
|
+
- Router vs route dependencies: routes may miss security dependencies present elsewhere; check for unprotected variants of protected actions.
|
|
43
|
+
- Minimal satisfaction: `OAuth2PasswordBearer` only yields a token string—verify if any route treats token presence as auth without verification.
|
|
44
|
+
- Scope checks: ensure scopes are enforced by the dependency (e.g., `Security(...)`); routes using `Depends` instead may ignore requested scopes.
|
|
45
|
+
- Header/param aliasing: DI sources headers/cookies/query by name; try case variations and duplicates to influence which value binds.
|
|
46
|
+
</dependency_injection_and_security>
|
|
47
|
+
|
|
48
|
+
<auth_and_jwt>
|
|
49
|
+
- Token misuse: developers may decode JWTs without verifying signature/issuer/audience; attempt unsigned/attacker-signed tokens and cross-service audiences.
|
|
50
|
+
- Algorithm/key confusion: try HS/RS cross-use if verification is not pinned; inject `kid` header targeting local files/paths where custom key lookup exists.
|
|
51
|
+
- Session bridges: check cookies set via SessionMiddleware or custom cookies. Attempt session fixation and forging if weak `secret_key` or predictable signing is used.
|
|
52
|
+
- Device/PKCE flows: verify strict PKCE S256 and state/nonce enforcement if OAuth/OIDC is integrated.
|
|
53
|
+
</auth_and_jwt>
|
|
54
|
+
|
|
55
|
+
<cors_and_csrf>
|
|
56
|
+
- CORS reflection: broad `allow_origin_regex` or mis-specified origins can permit cross-site reads; test arbitrary Origins and credentialed requests.
|
|
57
|
+
- CSRF: FastAPI/Starlette lack built-in CSRF. If cookies carry auth, attempt state-changing requests via cross-site forms/XHR; validate origin header checks and same-site settings.
|
|
58
|
+
</cors_and_csrf>
|
|
59
|
+
|
|
60
|
+
<proxy_and_host_trust>
|
|
61
|
+
- ProxyHeadersMiddleware: if enabled without network boundary, spoof `X-Forwarded-For/Proto` to influence auth/IP gating and secure redirects.
|
|
62
|
+
- TrustedHostMiddleware absent or lax: perform Host header poisoning; attempt password reset links / absolute URL generation under attacker host.
|
|
63
|
+
- Upstream/CDN cache keys: ensure Vary on Authorization/Cookie/Tenant; try cache key confusion to leak personalized responses.
|
|
64
|
+
</proxy_and_host_trust>
|
|
65
|
+
|
|
66
|
+
<static_and_uploads>
|
|
67
|
+
- UploadFile.filename: attempt path traversal and control characters; verify server joins/sanitizes and enforces storage roots.
|
|
68
|
+
- FileResponse/StaticFiles: confirm directory boundaries and index/auto-listing; probe symlinks and case/encoding variants.
|
|
69
|
+
- Parser differentials: send JSON vs multipart for the same route to hit divergent code paths/validators.
|
|
70
|
+
</static_and_uploads>
|
|
71
|
+
|
|
72
|
+
<template_injection>
|
|
73
|
+
- Jinja2 templates via `TemplateResponse`: search for unescaped injection in variables and filters. Probe with minimal expressions:
|
|
74
|
+
{% raw %}- `{{7*7}}` → arithmetic confirmation
|
|
75
|
+
- `{{cycler.__init__.__globals__['os'].popen('id').read()}}` for RCE in unsafe contexts{% endraw %}
|
|
76
|
+
- Confirm autoescape and strict sandboxing; inspect custom filters/globals.
|
|
77
|
+
</template_injection>
|
|
78
|
+
|
|
79
|
+
<ssrf_and_outbound>
|
|
80
|
+
- Endpoints fetching user-supplied URLs (imports, previews, webhooks validation): test loopback/RFC1918/IPv6, redirects, DNS rebinding, and header control.
|
|
81
|
+
- Library behavior (httpx/requests): examine redirect policy, header forwarding, and protocol support; try `file://`, `ftp://`, or gopher-like shims if custom clients are used.
|
|
82
|
+
</ssrf_and_outbound>
|
|
83
|
+
|
|
84
|
+
<websockets>
|
|
85
|
+
- Authenticate each connection (query/header/cookie). Attempt cross-origin handshakes and cookie-bearing WS from untrusted origins.
|
|
86
|
+
- Topic naming and authorization: if using user/tenant IDs in channels, subscribe/publish to foreign IDs.
|
|
87
|
+
- Message-level checks: ensure per-message authorization, not only at handshake.
|
|
88
|
+
</websockets>
|
|
89
|
+
|
|
90
|
+
<background_tasks_and_jobs>
|
|
91
|
+
- BackgroundTasks that act on IDs must re-enforce ownership/tenant at execution time. Attempt to fetch/cancel others’ jobs by referencing their IDs.
|
|
92
|
+
- Export/import pipelines: test job/result endpoints for IDOR and cross-tenant leaks.
|
|
93
|
+
</background_tasks_and_jobs>
|
|
94
|
+
|
|
95
|
+
<multi_app_mounting>
|
|
96
|
+
- Mounted subapps (e.g., `/admin`, `/static`, `/metrics`) may bypass global middlewares. Confirm middleware parity and auth on mounts.
|
|
97
|
+
</multi_app_mounting>
|
|
98
|
+
</advanced_techniques>
|
|
99
|
+
|
|
100
|
+
<bypass_techniques>
|
|
101
|
+
- Content-type switching: `application/json` ↔ `application/x-www-form-urlencoded` ↔ `multipart/form-data` to traverse alternate validators/handlers.
|
|
102
|
+
- Parameter duplication and case variants to exploit DI precedence.
|
|
103
|
+
- Method confusion via proxies (e.g., `X-HTTP-Method-Override`) if upstream respects it while app does not.
|
|
104
|
+
- Race windows around dependency-validated state transitions (issue token then mutate with parallel requests).
|
|
105
|
+
</bypass_techniques>
|
|
106
|
+
|
|
107
|
+
<special_contexts>
|
|
108
|
+
<pydantic_edges>
|
|
109
|
+
- Coercion: strings to ints/bools, empty strings to None; exploit truthiness and boundary conditions.
|
|
110
|
+
- Extra fields: if models allow/ignore extras, sneak in control fields for downstream logic (scope/role/ownerId) that are later trusted.
|
|
111
|
+
- Unions and `Annotated`: craft shapes hitting unintended branches.
|
|
112
|
+
</pydantic_edges>
|
|
113
|
+
|
|
114
|
+
<graphql_and_alt_stacks>
|
|
115
|
+
- If GraphQL (Strawberry/Graphene) is mounted, validate resolver-level authorization and IDOR on node/global IDs.
|
|
116
|
+
- If SQLModel/SQLAlchemy present, probe for raw query usage and row-level authorization gaps.
|
|
117
|
+
</graphql_and_alt_stacks>
|
|
118
|
+
</special_contexts>
|
|
119
|
+
|
|
120
|
+
<validation>
|
|
121
|
+
1. Show unauthorized data access or action with side-by-side owner vs non-owner requests (or different tenants).
|
|
122
|
+
2. Demonstrate cross-channel consistency (HTTP and WebSocket) for the same rule.
|
|
123
|
+
3. Include proof where proxies/headers/caches alter outcomes (Host/XFF/CORS).
|
|
124
|
+
4. Provide minimal payloads confirming template/SSRF execution or token misuse, with safe or OAST-based oracles.
|
|
125
|
+
5. Document exact dependency paths (router-level, route-level) that missed enforcement.
|
|
126
|
+
</validation>
|
|
127
|
+
|
|
128
|
+
<pro_tips>
|
|
129
|
+
1. Always fetch `/openapi.json` first; it’s the blueprint. If hidden, brute-force likely admin/report/export routes.
|
|
130
|
+
2. Trace dependencies per route; map which ones enforce auth/scopes vs merely parse input.
|
|
131
|
+
3. Treat tokens returned by `OAuth2PasswordBearer` as untrusted strings—verify actual signature and claims on the server.
|
|
132
|
+
4. Test CORS with arbitrary Origins and with credentials; verify preflight and actual request deltas.
|
|
133
|
+
5. Add Host and X-Forwarded-* fuzzing when behind proxies; watch for redirect/absolute URL differences.
|
|
134
|
+
6. For uploads, vary filename encodings, dot segments, and NUL-like bytes; verify storage paths and served URLs.
|
|
135
|
+
7. Use content-type toggling to hit alternate validators and code paths.
|
|
136
|
+
8. For WebSockets, test cookie-based auth, origin restrictions, and per-message authorization.
|
|
137
|
+
9. Mine client bundles/env for secret paths and preview/admin flags; many teams hide routes via UI only.
|
|
138
|
+
10. Keep PoCs minimal and durable (IDs, headers, small payloads) and prefer reproducible diffs over noisy payloads.
|
|
139
|
+
</pro_tips>
|
|
140
|
+
|
|
141
|
+
<remember>Authorization and validation must be enforced in the dependency graph and at the resource boundary for every path and channel. If any route, middleware, or mount skips binding subject, action, and object/tenant, expect cross-user and cross-tenant breakage.</remember>
|
|
142
|
+
</fastapi_security_testing_guide>
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
<nextjs_security_testing_guide>
|
|
2
|
+
<title>NEXT.JS — ADVERSARIAL TESTING PLAYBOOK</title>
|
|
3
|
+
|
|
4
|
+
<critical>Modern Next.js combines multiple execution contexts (Edge, Node, RSC, client) with smart caching (ISR/RSC fetch cache), middleware, and server actions. Authorization and cache boundaries must be enforced consistently across all paths or attackers will cross tenants, leak data, or invoke privileged actions.</critical>
|
|
5
|
+
|
|
6
|
+
<surface_map>
|
|
7
|
+
- Routers: App Router (`app/`) and Pages Router (`pages/`) coexist; test both
|
|
8
|
+
- Runtimes: Node.js vs Edge (V8 isolates with restricted APIs)
|
|
9
|
+
- Data paths: RSC (server components), Client components, Route Handlers (`app/api/**`), API routes (`pages/api/**`)
|
|
10
|
+
- Middleware: `middleware.ts`/`_middleware.ts`
|
|
11
|
+
- Rendering modes: SSR, SSG, ISR, on-demand revalidation, draft/preview mode
|
|
12
|
+
- Images: `next/image` optimization and remote loader
|
|
13
|
+
- Auth: NextAuth.js (callbacks, CSRF/state, callbackUrl), custom JWT/session bridges
|
|
14
|
+
- Server Actions: streamed POST with `Next-Action` header and action IDs
|
|
15
|
+
</surface_map>
|
|
16
|
+
|
|
17
|
+
<methodology>
|
|
18
|
+
1. Inventory routes (pages + app), static vs dynamic segments, and params. Map middleware coverage and runtime per path.
|
|
19
|
+
2. Capture baseline for each role (unauth, user, admin) across SSR, API routes, Route Handlers, Server Actions, and streaming data.
|
|
20
|
+
3. Diff responses while toggling runtime (Edge/Node), content-type, fetch cache directives, and preview/draft mode.
|
|
21
|
+
4. Probe caching and revalidation boundaries (ISR, RSC fetch, CDN) for cross-user/tenant leaks.
|
|
22
|
+
</methodology>
|
|
23
|
+
|
|
24
|
+
<high_value_targets>
|
|
25
|
+
- Middleware-protected routes (auth, geo, A/B)
|
|
26
|
+
- Admin/staff paths, draft/preview content, on-demand revalidate endpoints
|
|
27
|
+
- RSC payloads and flight data, streamed responses (server actions)
|
|
28
|
+
- Image optimizer and custom loaders, remotePatterns/domains
|
|
29
|
+
- NextAuth callbacks (`/api/auth/callback/*`), sign-in providers, CSRF/state handling
|
|
30
|
+
- Edge-only features (bot protection, IP gates) and their Node equivalents
|
|
31
|
+
</high_value_targets>
|
|
32
|
+
|
|
33
|
+
<advanced_techniques>
|
|
34
|
+
<middleware_bypass>
|
|
35
|
+
- Test for CVE-class middleware bypass via `x-middleware-subrequest` crafting and `x-nextjs-data` probing. Look for 307 + `x-middleware-rewrite`/`x-nextjs-redirect` headers and attempt bypass on protected routes.
|
|
36
|
+
- Attempt direct route access on Node vs Edge runtimes; confirm protection parity.
|
|
37
|
+
</middleware_bypass>
|
|
38
|
+
|
|
39
|
+
<server_actions>
|
|
40
|
+
- Capture streamed POSTs containing `Next-Action` headers. Map hashed action IDs via source maps or specialized tooling to discover hidden actions.
|
|
41
|
+
- Invoke actions out of UI flow and with alternate content-types; verify server-side authorization is enforced per action and not assumed from client state.
|
|
42
|
+
- Try cross-tenant/object references within action payloads to expose BOLA/IDOR via server actions.
|
|
43
|
+
</server_actions>
|
|
44
|
+
|
|
45
|
+
<rsc_and_cache>
|
|
46
|
+
- RSC fetch cache: probe `fetch` cache modes (force-cache, default, no-store) and revalidate tags/paths. Look for user-bound data cached without identity keys (ETag/Set-Cookie unaware).
|
|
47
|
+
- Confirm that personalized data is rendered via `no-store` or properly keyed; attempt cross-user content via shared caches/CDN.
|
|
48
|
+
- Inspect Flight data streams for serialized sensitive fields leaking through props.
|
|
49
|
+
</rsc_and_cache>
|
|
50
|
+
|
|
51
|
+
<isr_and_revalidation>
|
|
52
|
+
- Identify ISR pages (stale-while-revalidate). Check if responses may include user-bound fragments or tenant-dependent content.
|
|
53
|
+
- On-demand revalidation endpoints: look for weak secrets in URLs, referer-disclosed tokens, or unvalidated hosts triggering `revalidatePath`/`revalidateTag`.
|
|
54
|
+
- Attempt header-smuggling or method variations to trigger revalidation flows.
|
|
55
|
+
</isr_and_revalidation>
|
|
56
|
+
|
|
57
|
+
<draft_preview_mode>
|
|
58
|
+
- Draft/preview mode toggles via secret URLs/cookies; search for preview enable endpoints and secrets in client bundles/env leaks.
|
|
59
|
+
- Try setting preview cookies from subdomains, alternate paths, or through open redirects; observe content differences and persistence.
|
|
60
|
+
</draft_preview_mode>
|
|
61
|
+
|
|
62
|
+
<next_image_ssrf>
|
|
63
|
+
- Review `images.domains`/`remotePatterns` in `next.config.js`; test SSRF to internal hosts (IPv4/IPv6 variants, DNS rebinding) if patterns are broad.
|
|
64
|
+
- Custom loader functions may fetch with arbitrary URLs; test protocol smuggling and redirection chains.
|
|
65
|
+
- Attempt cache poisoning: craft same URL with different normalization to affect other users.
|
|
66
|
+
</next_image_ssrf>
|
|
67
|
+
|
|
68
|
+
<nextauth_pitfalls>
|
|
69
|
+
- State/nonce/PKCE: validate per-provider correctness; attempt missing/relaxed checks leading to login CSRF or token mix-up.
|
|
70
|
+
- Callback URL restrictions: open redirect in `callbackUrl` or mis-scoped allowed hosts; hijack sessions by forcing callbacks.
|
|
71
|
+
- JWT/session bridges: audience/issuer not enforced across API routes/Route Handlers; attempt cross-service token reuse.
|
|
72
|
+
</nextauth_pitfalls>
|
|
73
|
+
|
|
74
|
+
<edge_runtime_diffs>
|
|
75
|
+
- Edge runtime lacks certain Node APIs; defenses relying on Node-only modules may be skipped. Compare behavior of the same route in Edge vs Node.
|
|
76
|
+
- Header trust and IP determination can differ at the edge; test auth decisions tied to `x-forwarded-*` variance.
|
|
77
|
+
</edge_runtime_diffs>
|
|
78
|
+
|
|
79
|
+
<client_and_dom>
|
|
80
|
+
- Identify `dangerouslySetInnerHTML`, Markdown renderers, and user-controlled href/src attributes. Validate CSP/Trusted Types coverage for SSR/CSR/hydration.
|
|
81
|
+
- Attack hydration boundaries: server vs client render mismatches can enable gadget-based XSS.
|
|
82
|
+
</client_and_dom>
|
|
83
|
+
</advanced_techniques>
|
|
84
|
+
|
|
85
|
+
<bypass_techniques>
|
|
86
|
+
- Content-type switching: `application/json` ↔ `multipart/form-data` ↔ `application/x-www-form-urlencoded` to traverse alternate code paths.
|
|
87
|
+
- Method override/tunneling: `_method`, `X-HTTP-Method-Override`, GET on endpoints unexpectedly accepting writes.
|
|
88
|
+
- Case/param aliasing and query duplication affecting middleware vs handler parsing.
|
|
89
|
+
- Cache key confusion at CDN/proxy (lack of Vary on auth cookies/headers) to leak personalized SSR/ISR content.
|
|
90
|
+
</bypass_techniques>
|
|
91
|
+
|
|
92
|
+
<special_contexts>
|
|
93
|
+
<uploads_and_files>
|
|
94
|
+
- API routes and Route Handlers handling file uploads: check MIME sniffing, Content-Disposition, stored path traversal, and public serving of user files.
|
|
95
|
+
- Validate signing/scoping of any generated file URLs (short TTL, audience-bound).
|
|
96
|
+
</uploads_and_files>
|
|
97
|
+
|
|
98
|
+
<integrations_and_webhooks>
|
|
99
|
+
- Webhooks that trigger revalidation/imports: require HMAC verification; test with replay and cross-tenant object IDs.
|
|
100
|
+
- Analytics/AB testing flags controlled via cookies/headers; ensure they do not unlock privileged server paths.
|
|
101
|
+
</integrations_and_webhooks>
|
|
102
|
+
</special_contexts>
|
|
103
|
+
|
|
104
|
+
<validation>
|
|
105
|
+
1. Provide side-by-side requests for different principals showing cross-user/tenant content or actions.
|
|
106
|
+
2. Prove cache boundary failure (RSC/ISR/CDN) with response diffs or ETag collisions.
|
|
107
|
+
3. Demonstrate server action invocation outside UI with insufficient authorization checks.
|
|
108
|
+
4. Show middleware bypass (where applicable) with explicit headers and resulting protected content.
|
|
109
|
+
5. Include runtime parity checks (Edge vs Node) proving inconsistent enforcement.
|
|
110
|
+
</validation>
|
|
111
|
+
|
|
112
|
+
<pro_tips>
|
|
113
|
+
1. Enumerate with both App and Pages routers: many apps ship a hybrid surface.
|
|
114
|
+
2. Treat caching as an identity boundary—test with cookies stripped, altered, and with Vary/ETag diffs.
|
|
115
|
+
3. Decode client bundles for preview/revalidate secrets, action IDs, and hidden routes.
|
|
116
|
+
4. Use streaming-aware tooling to capture server actions and RSC payloads; diff flight data.
|
|
117
|
+
5. For NextAuth, fuzz provider params (state, nonce, scope, callbackUrl) and verify strictness.
|
|
118
|
+
6. Always retest under Edge and Node; misconfigurations often exist in only one runtime.
|
|
119
|
+
7. Probe `next/image` aggressively but safely—test IPv6/obscure encodings and redirect behavior.
|
|
120
|
+
8. Validate negative paths: other-user IDs, other-tenant headers/subdomains, lower roles.
|
|
121
|
+
9. Focus on export/report/download endpoints; they often bypass resolver-level checks.
|
|
122
|
+
10. Document minimal, reproducible PoCs; avoid noisy payloads—prefer precise diffs.
|
|
123
|
+
</pro_tips>
|
|
124
|
+
|
|
125
|
+
<remember>Next.js security breaks where identity, authorization, and caching diverge across routers, runtimes, and data paths. Bind subject, action, and object on every path, and key caches to identity and tenant explicitly.</remember>
|
|
126
|
+
</nextjs_security_testing_guide>
|