diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 61108a8..2c4b151 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,7 +46,7 @@ Skills are specialized knowledge packages that enhance agent capabilities. See [ ### Quick Guide 1. **Choose the right category** (`/vulnerabilities`, `/frameworks`, `/technologies`, etc.) -2. **Create a** `.jinja` file with your skill content +2. **Create a** `.md` file with your skill content 3. **Include practical examples** - Working payloads, commands, or test cases 4. **Provide validation methods** - How to confirm findings and avoid false positives 5. **Submit via PR** with clear description diff --git a/pyproject.toml b/pyproject.toml index 506da7c..cc2512c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,8 @@ packages = [ include = [ "LICENSE", "README.md", - "strix/**/*.jinja", + "strix/agents/**/*.jinja", + "strix/skills/**/*.md", "strix/**/*.xml", "strix/**/*.tcss" ] diff --git a/strix.spec b/strix.spec index fbe2d90..425219a 100644 --- a/strix.spec +++ b/strix.spec @@ -9,7 +9,11 @@ strix_root = project_root / 'strix' datas = [] -for jinja_file in strix_root.rglob('*.jinja'): +for md_file in strix_root.rglob('skills/**/*.md'): + rel_path = md_file.relative_to(project_root) + datas.append((str(md_file), str(rel_path.parent))) + +for jinja_file in strix_root.rglob('agents/**/*.jinja'): rel_path = jinja_file.relative_to(project_root) datas.append((str(jinja_file), str(rel_path.parent))) @@ -86,6 +90,14 @@ hiddenimports = [ # XML parsing 'xmltodict', + 'defusedxml', + 'defusedxml.ElementTree', + + # Syntax highlighting + 'pygments', + 'pygments.lexers', + 'pygments.styles', + 'pygments.util', # Tiktoken (for token counting) 'tiktoken', @@ -95,6 +107,9 @@ hiddenimports = [ # Tenacity retry 'tenacity', + # CVSS scoring + 'cvss', + # Strix modules 'strix', 'strix.interface', @@ -128,6 +143,7 @@ hiddenimports += collect_submodules('litellm') hiddenimports += collect_submodules('textual') hiddenimports += collect_submodules('rich') hiddenimports += collect_submodules('pydantic') +hiddenimports += collect_submodules('pygments') excludes = [ # Sandbox-only packages diff --git a/strix/llm/llm.py b/strix/llm/llm.py index 42f77fc..778e27f 100644 --- a/strix/llm/llm.py +++ b/strix/llm/llm.py @@ -90,7 +90,7 @@ class LLM: *list(self.config.skills or []), f"scan_modes/{self.config.scan_mode}", ] - skill_content = load_skills(skills_to_load, env) + skill_content = load_skills(skills_to_load) env.globals["get_skill"] = lambda name: skill_content.get(name, "") result = env.get_template("system_prompt.jinja").render( diff --git a/strix/skills/__init__.py b/strix/skills/__init__.py index f75cb55..cade754 100644 --- a/strix/skills/__init__.py +++ b/strix/skills/__init__.py @@ -1,5 +1,3 @@ -from jinja2 import Environment - from strix.utils.resource_paths import get_strix_resource_path @@ -15,7 +13,7 @@ def get_available_skills() -> dict[str, list[str]]: category_name = category_dir.name skills = [] - for file_path in category_dir.glob("*.jinja"): + for file_path in category_dir.glob("*.md"): skill_name = file_path.stem skills.append(skill_name) @@ -70,7 +68,7 @@ def generate_skills_description() -> str: return description -def load_skills(skill_names: list[str], jinja_env: Environment) -> dict[str, str]: +def load_skills(skill_names: list[str]) -> dict[str, str]: import logging logger = logging.getLogger(__name__) @@ -84,22 +82,22 @@ def load_skills(skill_names: list[str], jinja_env: Environment) -> dict[str, str skill_path = None if "/" in skill_name: - skill_path = f"{skill_name}.jinja" + skill_path = f"{skill_name}.md" else: for category, skills in available_skills.items(): if skill_name in skills: - skill_path = f"{category}/{skill_name}.jinja" + skill_path = f"{category}/{skill_name}.md" break if not skill_path: - root_candidate = f"{skill_name}.jinja" + root_candidate = f"{skill_name}.md" if (skills_dir / root_candidate).exists(): skill_path = root_candidate if skill_path and (skills_dir / skill_path).exists(): - template = jinja_env.get_template(skill_path) + full_path = skills_dir / skill_path var_name = skill_name.split("/")[-1] - skill_content[var_name] = template.render() + skill_content[var_name] = full_path.read_text() logger.info(f"Loaded skill: {skill_name} -> {var_name}") else: logger.warning(f"Skill not found: {skill_name}") diff --git a/strix/skills/coordination/root_agent.jinja b/strix/skills/coordination/root_agent.md similarity index 93% rename from strix/skills/coordination/root_agent.jinja rename to strix/skills/coordination/root_agent.md index e877bb9..4c4f163 100644 --- a/strix/skills/coordination/root_agent.jinja +++ b/strix/skills/coordination/root_agent.md @@ -1,4 +1,5 @@ - +# ROOT COORDINATION AGENT + You are a COORDINATION AGENT ONLY. You do NOT perform any security testing, vulnerability assessment, or technical work yourself. Your ONLY responsibilities: @@ -12,9 +13,9 @@ CRITICAL RESTRICTIONS: - NEVER write detailed vulnerability reports (only compile final summaries) - ONLY use agent_graph and finish tools for coordination - You can create agents throughout the scan process, depending on the task and findings, not just at the beginning! - - +## Agent Management + BEFORE CREATING AGENTS: 1. Analyze the target scope and break into independent tasks 2. Check existing agents to avoid duplication @@ -29,13 +30,12 @@ COORDINATION GUIDELINES: - Ensure clear task boundaries and success criteria - Terminate redundant agents when objectives overlap - Use message passing only when essential (requests/answers or critical handoffs); avoid routine status messages and prefer batched updates - - +## Final Responsibilities + When all agents complete: 1. Collect findings from all agents 2. Compile a final scan summary report 3. Use finish tool to complete the assessment Your value is in orchestration, not execution. - diff --git a/strix/skills/frameworks/fastapi.jinja b/strix/skills/frameworks/fastapi.md similarity index 83% rename from strix/skills/frameworks/fastapi.jinja rename to strix/skills/frameworks/fastapi.md index d58f4e8..47904db 100644 --- a/strix/skills/frameworks/fastapi.jinja +++ b/strix/skills/frameworks/fastapi.md @@ -1,9 +1,11 @@ - -FASTAPI — ADVERSARIAL TESTING PLAYBOOK +# FASTAPI — ADVERSARIAL TESTING PLAYBOOK -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 + +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. + +## Surface Map - - ASGI stack: Starlette middlewares (CORS, TrustedHost, ProxyHeaders, Session), exception handlers, lifespan events - Routers/sub-apps: APIRouter with prefixes/tags, mounted apps (StaticFiles, admin subapps), `include_router`, versioned paths - Security and DI: `Depends`, `Security`, `OAuth2PasswordBearer`, `HTTPBearer`, scopes, per-router vs per-route dependencies @@ -12,16 +14,16 @@ - Files and static: `UploadFile`, `File`, `FileResponse`, `StaticFiles` mounts, template engines (`Jinja2Templates`) - Channels: HTTP (sync/async), WebSocket, StreamingResponse/SSE, BackgroundTasks/Task queues - Deployment: Uvicorn/Gunicorn, reverse proxies/CDN, TLS termination, header trust - - +## Methodology + 1. Enumerate routes from OpenAPI and via crawling; diff with 404-fuzzing for hidden endpoints (`include_in_schema=False`). 2. Build a Principal × Channel × Content-Type matrix (unauth, user, staff/admin; HTTP vs WebSocket; JSON/form/multipart) and capture baselines. 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. 4. Compare behavior across deployments: dev/stage/prod often differ in middlewares (CORS, TrustedHost, ProxyHeaders) and docs exposure. - - +## High Value Targets + - `/openapi.json`, `/docs`, `/redoc` in production (full attack surface map; securitySchemes and server URLs) - Auth flows: token endpoints, session/cookie bridges, OAuth device/PKCE, scope checks - Admin/staff routers, feature-flagged routes, `include_in_schema=False` endpoints @@ -29,103 +31,105 @@ - WebSocket endpoints carrying notifications, admin channels, or commands - Background job creation/fetch (`/jobs/{id}`, `/tasks/{id}/result`) - Mounted subapps (admin UI, storage browsers, metrics/health endpoints) - - - +## Advanced Techniques + +### Openapi And Docs + - Try default and alternate locations: `/openapi.json`, `/docs`, `/redoc`, `/api/openapi.json`, `/internal/openapi.json`. - If OpenAPI is exposed, mine: paths, parameter names, securitySchemes, scopes, servers; find endpoints hidden in UI but present in schema. - Schema drift: endpoints with `include_in_schema=False` won’t appear—use wordlists based on tags/prefixes and common admin/debug names. - - +### Dependency Injection And Security + - Router vs route dependencies: routes may miss security dependencies present elsewhere; check for unprotected variants of protected actions. - Minimal satisfaction: `OAuth2PasswordBearer` only yields a token string—verify if any route treats token presence as auth without verification. - Scope checks: ensure scopes are enforced by the dependency (e.g., `Security(...)`); routes using `Depends` instead may ignore requested scopes. - Header/param aliasing: DI sources headers/cookies/query by name; try case variations and duplicates to influence which value binds. - - +### Auth And Jwt + - Token misuse: developers may decode JWTs without verifying signature/issuer/audience; attempt unsigned/attacker-signed tokens and cross-service audiences. - 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. - Session bridges: check cookies set via SessionMiddleware or custom cookies. Attempt session fixation and forging if weak `secret_key` or predictable signing is used. - Device/PKCE flows: verify strict PKCE S256 and state/nonce enforcement if OAuth/OIDC is integrated. - - +### Cors And Csrf + - CORS reflection: broad `allow_origin_regex` or mis-specified origins can permit cross-site reads; test arbitrary Origins and credentialed requests. - 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. - - +### Proxy And Host Trust + - ProxyHeadersMiddleware: if enabled without network boundary, spoof `X-Forwarded-For/Proto` to influence auth/IP gating and secure redirects. - TrustedHostMiddleware absent or lax: perform Host header poisoning; attempt password reset links / absolute URL generation under attacker host. - Upstream/CDN cache keys: ensure Vary on Authorization/Cookie/Tenant; try cache key confusion to leak personalized responses. - - +### Static And Uploads + - UploadFile.filename: attempt path traversal and control characters; verify server joins/sanitizes and enforces storage roots. - FileResponse/StaticFiles: confirm directory boundaries and index/auto-listing; probe symlinks and case/encoding variants. - Parser differentials: send JSON vs multipart for the same route to hit divergent code paths/validators. - - +### Template Injection + - Jinja2 templates via `TemplateResponse`: search for unescaped injection in variables and filters. Probe with minimal expressions: -{% raw %}- `{{7*7}}` → arithmetic confirmation -- `{{cycler.__init__.__globals__['os'].popen('id').read()}}` for RCE in unsafe contexts{% endraw %} +``` +- `{{7*7}}` → arithmetic confirmation +- `{{cycler.__init__.__globals__['os'].popen('id').read()}}` for RCE in unsafe contexts +``` - Confirm autoescape and strict sandboxing; inspect custom filters/globals. - - +### Ssrf And Outbound + - Endpoints fetching user-supplied URLs (imports, previews, webhooks validation): test loopback/RFC1918/IPv6, redirects, DNS rebinding, and header control. - Library behavior (httpx/requests): examine redirect policy, header forwarding, and protocol support; try `file://`, `ftp://`, or gopher-like shims if custom clients are used. - - +### Websockets + - Authenticate each connection (query/header/cookie). Attempt cross-origin handshakes and cookie-bearing WS from untrusted origins. - Topic naming and authorization: if using user/tenant IDs in channels, subscribe/publish to foreign IDs. - Message-level checks: ensure per-message authorization, not only at handshake. - - +### Background Tasks And Jobs + - BackgroundTasks that act on IDs must re-enforce ownership/tenant at execution time. Attempt to fetch/cancel others’ jobs by referencing their IDs. - Export/import pipelines: test job/result endpoints for IDOR and cross-tenant leaks. - - +### Multi App Mounting + - Mounted subapps (e.g., `/admin`, `/static`, `/metrics`) may bypass global middlewares. Confirm middleware parity and auth on mounts. - - - +## Bypass Techniques + - Content-type switching: `application/json` ↔ `application/x-www-form-urlencoded` ↔ `multipart/form-data` to traverse alternate validators/handlers. - Parameter duplication and case variants to exploit DI precedence. - Method confusion via proxies (e.g., `X-HTTP-Method-Override`) if upstream respects it while app does not. - Race windows around dependency-validated state transitions (issue token then mutate with parallel requests). - - - +## Special Contexts + +### Pydantic Edges + - Coercion: strings to ints/bools, empty strings to None; exploit truthiness and boundary conditions. - Extra fields: if models allow/ignore extras, sneak in control fields for downstream logic (scope/role/ownerId) that are later trusted. - Unions and `Annotated`: craft shapes hitting unintended branches. - - +### Graphql And Alt Stacks + - If GraphQL (Strawberry/Graphene) is mounted, validate resolver-level authorization and IDOR on node/global IDs. - If SQLModel/SQLAlchemy present, probe for raw query usage and row-level authorization gaps. - - - +## Validation + 1. Show unauthorized data access or action with side-by-side owner vs non-owner requests (or different tenants). 2. Demonstrate cross-channel consistency (HTTP and WebSocket) for the same rule. 3. Include proof where proxies/headers/caches alter outcomes (Host/XFF/CORS). 4. Provide minimal payloads confirming template/SSRF execution or token misuse, with safe or OAST-based oracles. 5. Document exact dependency paths (router-level, route-level) that missed enforcement. - - +## Pro Tips + 1. Always fetch `/openapi.json` first; it’s the blueprint. If hidden, brute-force likely admin/report/export routes. 2. Trace dependencies per route; map which ones enforce auth/scopes vs merely parse input. 3. Treat tokens returned by `OAuth2PasswordBearer` as untrusted strings—verify actual signature and claims on the server. @@ -136,7 +140,7 @@ 8. For WebSockets, test cookie-based auth, origin restrictions, and per-message authorization. 9. Mine client bundles/env for secret paths and preview/admin flags; many teams hide routes via UI only. 10. Keep PoCs minimal and durable (IDs, headers, small payloads) and prefer reproducible diffs over noisy payloads. - -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 + +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. diff --git a/strix/skills/frameworks/nextjs.jinja b/strix/skills/frameworks/nextjs.md similarity index 87% rename from strix/skills/frameworks/nextjs.jinja rename to strix/skills/frameworks/nextjs.md index ddd2ce4..ed9f11d 100644 --- a/strix/skills/frameworks/nextjs.jinja +++ b/strix/skills/frameworks/nextjs.md @@ -1,9 +1,11 @@ - -NEXT.JS — ADVERSARIAL TESTING PLAYBOOK +# NEXT.JS — ADVERSARIAL TESTING PLAYBOOK -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 + +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. + +## Surface Map - - Routers: App Router (`app/`) and Pages Router (`pages/`) coexist; test both - Runtimes: Node.js vs Edge (V8 isolates with restricted APIs) - Data paths: RSC (server components), Client components, Route Handlers (`app/api/**`), API routes (`pages/api/**`) @@ -12,26 +14,27 @@ - Images: `next/image` optimization and remote loader - Auth: NextAuth.js (callbacks, CSRF/state, callbackUrl), custom JWT/session bridges - Server Actions: streamed POST with `Next-Action` header and action IDs - - +## Methodology + 1. Inventory routes (pages + app), static vs dynamic segments, and params. Map middleware coverage and runtime per path. 2. Capture baseline for each role (unauth, user, admin) across SSR, API routes, Route Handlers, Server Actions, and streaming data. 3. Diff responses while toggling runtime (Edge/Node), content-type, fetch cache directives, and preview/draft mode. 4. Probe caching and revalidation boundaries (ISR, RSC fetch, CDN) for cross-user/tenant leaks. - - +## High Value Targets + - Middleware-protected routes (auth, geo, A/B) - Admin/staff paths, draft/preview content, on-demand revalidate endpoints - RSC payloads and flight data, streamed responses (server actions) - Image optimizer and custom loaders, remotePatterns/domains - NextAuth callbacks (`/api/auth/callback/*`), sign-in providers, CSRF/state handling - Edge-only features (bot protection, IP gates) and their Node equivalents - - - +## Advanced Techniques + +### Route Enumeration + - __BUILD_MANIFEST.sortedPages: Execute `console.log(__BUILD_MANIFEST.sortedPages.join('\n'))` in browser console to instantly reveal all registered routes (Pages Router and static App Router paths compiled at build time) - __NEXT_DATA__: Inspect `