Commit graph

356 commits

Author SHA1 Message Date
root
ee890feccc perf(browser): fix single-core pinning and 2s per-action delay
- Replace shared global event loop singleton with per-BrowserInstance
  event loop threads, so multiple agents run browser I/O in parallel
  across cores instead of serializing through one thread (C15 pinning)
- Remove hard asyncio.sleep(2) after every browser action; replace with
  page.wait_for_load_state("networkidle", timeout=1500) so pages are
  ready when content settles, not after an arbitrary fixed delay
- Switch screenshot encoding from PNG to JPEG (quality=75) for ~5-10x
  lower CPU encode time and smaller base64 payloads to the LLM
- Add uvloop support (optional install) for lower event loop I/O latency
- Expand Chromium launch args: disable background throttling, renderer
  backgrounding, extensions, sync, and site-isolation overhead
- Fix BrowserInstance.close() to properly tear down playwright and stop
  the private event loop thread to avoid thread leaks
- Fix is_alive() to check loop.is_running() since _loop is no longer Optional

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 19:10:33 +02:00
Ahmex000
94966308d3 Add LLM rate limiter to enforce configurable requests-per-minute limit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 16:15:01 +02:00
strix-bugbounty
e34bb66e08 Add comprehensive web vulnerability skills for bug bounty hunting
Added 27 new vulnerability/technique files covering the full web security landscape:
- command_injection, xpath_injection, ssi_injection, smtp_injection
- saml_attacks, graphql_attacks, grpc_testing, oidc_attacks
- web_cache_deception, http_parameter_pollution, http2_vulnerabilities
- dom_clobbering, postmessage_attacks, prototype_pollution_advanced
- type_juggling, regex_dos, csv_formula_injection, log_injection
- security_headers, tls_ssl_misconfig, session_management
- account_takeover, insecure_deserialization_advanced, idor_advanced
- s3_bucket_misconfig, cloud_misconfig, api_key_exposure, web_recon

Each file includes attack surface, key vulnerabilities, bypass techniques,
testing methodology, validation steps, and pro tips for bug bounty hunters.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 14:58:25 +02:00
Ahmex000
5a90192f2c Add 36 new vulnerability/technology/cloud skill profiles
New vulnerabilities: waf_bypass, 403_401_bypass, rate_limit_bypass, oauth_sso, jwt,
reset_password, host_header_injection, cache_poisoning, crlf_injection, deserialization,
ldap_injection, cspt, csp_bypass, captcha_bypass, cookie_attacks, email_attacks,
dns_hijacking, llm_attacks, client_side_desync, input_validation, api_testing,
authentication, functions_testing, js_analysis

New technologies: wordpress, nginx, jenkins, jira, iis, tomcat, php_security, aem, salesforce

New cloud: aws_security, azure_security

New protocols: websocket

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 18:03:08 +02:00
Ahmex000
10e032775e feat: update NoSQL injection skill with expanded coverage
Replace minimal nosql_injection.md with comprehensive version from usestrix/strix#404 covering MongoDB operator injection, Redis/Elasticsearch/DynamoDB attack surfaces, blind extraction, bypass techniques, and validation methodology.
2026-03-28 23:08:04 +01:00
Ahmex000
96c6394765 feat: add HTTP request smuggling skill
Add strix/skills/vulnerabilities/http_request_smuggling.md covering CL.TE, TE.CL, H2.CL, H2.TE desync techniques, detection methodology, exploitation scenarios, and validation steps.

Cherry-picked from usestrix/strix#405.
2026-03-28 23:05:07 +01:00
root
c21c4d26b2 fix code-review issues and add 8 new vulnerability skills
Checkpoint / resume fixes (bot review on PR #380):
- cli.py: skip checkpoint save when scan completed cleanly (agent.state.completed)
  to prevent stale checkpoint re-creating after base_agent.py deletes it
- tui.py: same completed guard in both _save_checkpoint_on_interrupt and
  action_custom_quit to cover all TUI exit paths
- checkpoint_restore.py: fix infinite recursion in _depth() for cyclic
  parent_id references in corrupted checkpoints — mark node before recursing
- config.py: restore original shell-env-wins precedence for LLM vars;
  cli-config.json only applies when the shell var is absent, preventing
  silent override of rotated keys managed via shell environment

New vulnerability skills (from upstream PRs #204 and #334):
- clickjacking, cors_misconfiguration, nosql_injection, prototype_pollution,
  ssti, websocket_security (PR #204)
- mfa_bypass, edge_cases (PR #334)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 10:16:11 +01:00
root
43cb418c92 Fix all critical issues flagged in code review
- checkpoint.py: remove debug log file (strix_checkpoint_debug.log)
  that was writing to every user's home directory on each save
- checkpoint.py: acquire _agents_lock before iterating _agent_instances
  to prevent RuntimeError on concurrent sub-agent creation/removal
- checkpoint_restore.py: register restored sub-agents in _agent_graph,
  _agent_instances, and _agent_states so send_message_to_agent can
  route to them — previously they were unreachable after resume
- tracer.py: revert Path.home() back to Path.cwd() to avoid silent
  breaking change for all users; checkpoint logic in main.py already
  uses Path.home() directly so tracer change was not needed
- cli.py / tui.py: move checkpoint_restore imports to top of file
  per PEP 8, remove noqa: E402 suppressions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 15:13:55 +01:00
Ahmex000
39dd85e7f0 Fix model config override and code review issues
- config.py: cli-config.json LLM vars now always override shell env,
  preventing stale shell values from reverting the configured model
- checkpoint_restore.py: extract shared restore logic from cli/tui to
  eliminate code duplication
- cli.py / tui.py: use shared checkpoint_restore module, add
  double-save guard via threading.Event
- agents_graph_actions.py: add _agents_lock for thread-safe access to
  _running_agents and _agent_instances, fix mutable default arg in
  restore_sub_agents

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 14:34:52 +01:00
Ahmex000
c1a464a9de Add checkpoint debug logging to diagnose resume save failures
Writes SAVED/FAILED entries to ~/strix_checkpoint_debug.log on every
save attempt, bypassing the suppressed warning logger. This lets us
see if saves are happening during resumed sessions and what error (if
any) is causing them to fail silently.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:59:38 +01:00
Ahmex000
9cba355b54 Fix checkpoint not updating on second resume
Root cause: checkpoint and tracer run directories used CWD-relative
paths (Path("strix_runs") and Path.cwd() / "strix_runs"). Launching
strix from different directories across sessions created separate
checkpoint files that never updated each other, so the third session
always resumed from the first session's iteration.

Fix: use Path.home() / "strix_runs" as the canonical absolute path in
both tracer.py and main.py so all sessions write to the same location
regardless of CWD.

Also includes earlier serialization robustness fixes (mode="json" +
_json_default fallback) and explicit checkpoint save in action_custom_quit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 13:55:41 +01:00
Ahmex000
daecf22290 Fix threading race condition in container initialization
Multiple sub-agent threads starting simultaneously all saw
_needs_fresh_container=True and each called _create_container,
which removes the container the previous thread just created.
Result: only 1 of N sub-agents got a live container; the rest
got 'Container X not found' on every tool call, and the root
agent's sandbox init also failed when sub-agents trashed the
container underneath it.

Fix: add threading.Lock (_container_init_lock) around the
slow path in _get_or_create_container. Only the first thread
to acquire the lock creates the container; all waiting threads
re-check _scan_container inside the lock and reuse the
already-running one, paying zero extra Docker overhead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 12:51:30 +01:00
Ahmex000
6d6cdb96a9 Fix Docker container 409 race condition on resume
- Add _needs_fresh_container flag: always create a fresh container on
  first call to _get_or_create_container in a new runtime instance,
  preventing reuse of stale containers from a previous session whose
  async docker-rm hasn't completed yet.

- Add _cleanup_existing_containers(): uses subprocess.run (synchronous
  docker rm -f) instead of the SDK remove() which returns before Docker
  fully frees the container name, causing 409 Conflict on containers.run().
  Searches by both name filter and strix-scan-id label to catch containers
  in mid-removal state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 12:38:28 +01:00
root
7e8651a490 Restore sub-agents from checkpoint with full message history on resume
Previously sub-agents were terminated on Ctrl+C and never properly restored
— only the root agent resumed. This is the full fix.

Architecture change:
- checkpoint.py: Added sub_agent_states field (dict[agent_id -> AgentState
  dump]) saved from _agent_instances at every checkpoint write. Every
  currently-running non-root agent is captured.

- base_agent.py: Replaced fragile _is_root_resume heuristic with an explicit
  is_resumed flag (set via agent config). Works for both root and sub-agents.
  Prevents duplicate task message from being added to restored agents.

- cli.py / tui.py: Added _restore_sub_agents() which, on resume, iterates
  checkpoint sub_agent_states in topological order (parents before children),
  restores each agent's full AgentState, resets blocking flags, clears the
  old sandbox, injects a [SYSTEM - SUB-AGENT RESUMED] message, and spawns
  each agent in a daemon thread — identical to how the root agent is handled.
  Sub-agents are spawned BEFORE execute_scan so root agent can communicate
  with them immediately using their original IDs.

- Root agent's resume message now says "these sub-agents are ALREADY RUNNING
  at IDs [X, Y]" instead of "re-spawn them" — prevents double-spawning.

- agents_graph_actions.py: [SYSTEM - SUB-AGENT RESUMED] filtered from
  inherited context alongside [SYSTEM - SCAN RESUMED] so freshly-spawned
  child agents never see these system markers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 10:54:24 +01:00
root
8e8b86e844 Fix sub-agents killed after resume: strip SCAN RESUMED from inherited context
Root cause: create_agent passes the parent's full conversation history
(inherited_messages) to each new sub-agent. After resume, the parent's
history ends with a [SYSTEM - SCAN RESUMED] message that says:
  "ALL previous sub-agents have been terminated"
  "Do NOT call agent_finish unless all testing is genuinely complete"

Sub-agents reading this in their inherited context got confused:
- They thought they were the "terminated" agents and shouldn't be running
- They avoided calling agent_finish even when their task was done
- This caused them to hang, loop, or exit immediately without reporting

Fix: filter out any [SYSTEM - SCAN RESUMED] messages from the inherited
context before giving it to sub-agents. The resume instructions are only
relevant to the root agent — sub-agents should see normal parent context.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 10:31:23 +01:00
root
87078de4f1 Fix sub-agents not re-spawning after resume
Root causes:
1. Resume message said "re-spawn sub-agents" but didn't say WHICH ones
   or that old agent IDs are dead — LLM tried to interact with old IDs
   and got confused.
2. send_message_to_agent returned unhelpful "not found" error when the
   LLM used old (dead) agent IDs after resume.

Fixes:
- _build_resume_context_message / _inject_resume_context_message now
  accept the full checkpoint_data object and extract tracer_agents to
  list every non-completed sub-agent by name and task. The LLM now
  knows exactly which agents to re-spawn.
- Message explicitly forbids interacting with any agent ID from history
  and instructs the LLM to call view_agent_graph first.
- send_message_to_agent returns an actionable error when target is not
  found: explains it may be a dead session ID and tells the LLM to use
  view_agent_graph then create_agent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 10:20:10 +01:00
root
66166d5d68 Fix resume: auto-detect checkpoint by target hash + save on Ctrl+C
Root cause of resume not working:
- generate_run_name() adds a random suffix every time, so without
  --run-name the checkpoint from a previous session was never found.
- Ctrl+C during the first iteration (before any checkpoint was saved)
  left no checkpoint to resume from.

Fixes:
1. _find_checkpoint_by_target_hash(): scans strix_runs/ for the most
   recent checkpoint whose target_hash matches the current targets.
   Now running `strix --target example.com` again automatically
   resumes the last interrupted scan without needing --run-name.

2. _save_checkpoint_on_interrupt(): saves current agent state in both
   the signal handler and atexit in cli.py and tui.py, so a Ctrl+C
   mid-first-iteration still produces a valid checkpoint.

3. _setup_checkpoint_on_args() restructured: handles run_name=None,
   --force-new, explicit --run-name, and auto-detect in one place.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 10:08:48 +01:00
root
7fdf53d9f4 Add _build_resume_context_message to prevent LLM from finishing on resume
Defines the missing helper function called in cli.py and adds the equivalent
to tui.py. Injects a user message into the restored AgentState so the LLM
knows the scan was interrupted and must continue rather than call finish_scan
or agent_finish due to an abruptly-ended message history.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 09:57:35 +01:00
root
d1cddf2a74 fix: remove ghost sub-agents and reset blocking state on resume
Three bugs fixed:

1. Ghost sub-agents (root cause of all sub-agent issues):
   Restoring tracer.agents/tool_executions injected old sub-agent
   entries that had no live instances. The TUI showed them as
   interactive but they could not receive messages or run. Worse,
   they polluted the agent message-routing system so new sub-agents
   spawned after resume failed to communicate with the root agent.
   Fix: only restore chat_messages, vulnerability_reports, and the
   execution ID counter. The root agent's LLM context (message
   history) already knows what all sub-agents did.

2. Root agent stuck in wait state after resume:
   If the scan was interrupted while the root agent was in a wait
   state (waiting_for_input=True, stop_requested=True, etc.) the
   restored AgentState had those flags set and the loop froze
   immediately. Fix: reset all blocking flags on restore in both
   cli.py and tui.py.

3. Completed flag causing instant exit:
   If completed=True was serialised into the checkpoint (edge case)
   the loop would exit on the first should_stop() check. Fix:
   reset completed=False on restore.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 09:45:41 +01:00
root
91fb78179c fix: sub-agents skip task message due to overly broad resume guard
The previous guard `if not self.state.messages` broke sub-agents because
they can have pre-loaded context messages in their state before agent_loop
is called. This caused them to start without a task and produce no output.

Fix: only skip the initial task message when parent_id is None AND messages
is already populated (= root agent resume). Sub-agents always get their
task message regardless of whether their state has prior context.

- Fresh root agent:        parent_id=None, messages=[]   → adds task ✓
- Fresh sub-agent:         parent_id=set,  messages=[]   → adds task ✓
- Sub-agent with context:  parent_id=set,  messages=[..] → adds task ✓
- Resumed root agent:      parent_id=None, messages=[..] → skips  ✓

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 08:40:26 +01:00
root
fd5366f612 fix: save and restore sub-agent state in checkpoints
Previously checkpoints only saved tracer.chat_messages and
tracer.vulnerability_reports, leaving tracer.agents and
tracer.tool_executions empty on resume — so all sub-agents
(both in-progress and completed) were invisible after resuming.

Changes:
- checkpoint.py: add tracer_agents, tracer_tool_executions,
  tracer_next_execution_id fields to CheckpointModel; populate
  them in CheckpointManager.save() from the live tracer
- cli.py: on resume, restore agents dict, tool_executions dict,
  and advance _next_execution_id to avoid ID collisions
- tui.py: same restore logic so TUI sidebar shows all previous
  agents and their tool results immediately on resume

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 08:26:17 +01:00
Ahmex000
8a86a92e48 feat: add resume/checkpoint system for interrupted scans
- New strix/telemetry/checkpoint.py: Pydantic CheckpointModel + CheckpointManager
  with atomic writes (.tmp → rename), non-fatal errors, target-hash validation
- base_agent.py: save checkpoint after every iteration (root agents only),
  delete on clean completion, guard against duplicate task message on resume
- main.py: add --run-name, --resume, --new/--force-new CLI flags;
  _setup_checkpoint_on_args() handles load/validate/corrupt-recovery
- cli.py: resume banner, history replay (previous vulns + last 3 thoughts),
  restore AgentState with fresh sandbox + extended max_iterations budget
- tui.py: pre-populate tracer from checkpoint, restore AgentState in agent_config
- README.md: add "Resuming Interrupted Scans" section with usage examples

Original scan behavior is 100% preserved when --run-name is not used.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 07:30:12 +01:00
Ahmed Allam
f0f8f3d4cc Add tip about Strix integration with GitHub Actions 2026-03-17 22:14:11 -07:00
0xallam
1404864097 feat: add interactive mode for agent loop
Re-architects the agent loop to support interactive (chat-like) mode
where text-only responses pause execution and wait for user input,
while tool-call responses continue looping autonomously.

- Add `interactive` flag to LLMConfig (default False, no regression)
- Add configurable `waiting_timeout` to AgentState (0 = disabled)
- _process_iteration returns None for text-only → agent_loop pauses
- Conditional system prompt: interactive allows natural text responses
- Skip <meta>Continue the task.</meta> injection in interactive mode
- Sub-agents inherit interactive from parent (300s auto-resume timeout)
- Root interactive agents wait indefinitely for user input (timeout=0)
- TUI sets interactive=True; CLI unchanged (non_interactive=True)
2026-03-14 11:57:58 -07:00
0xallam
7dde988efc fix: web_search tool not loading when API key is in config file
The perplexity API key check in strix/tools/__init__.py used
Config.get() which only checks os.environ. At import time, the
config file (~/.strix/cli-config.json) hasn't been applied to
env vars yet, so the check always returned False.

Replace with _has_perplexity_api() that checks os.environ first
(fast path for SaaS/env var), then falls back to Config.load()
which reads the config file directly.
2026-03-14 11:48:45 -07:00
Ahmed Allam
f71e34dd0f Update web search model name to 'sonar-reasoning-pro' 2026-03-11 14:20:04 -07:00
Alex
f860b2f8e2 Change VERTEXAI_LOCATION from 'us-central1' to 'global'
us-central1 doesn't have access to the latest gemini models like gemini-3-flash-preview
2026-03-11 08:08:18 -07:00
alex s
a60cb4b66c
Add OpenTelemetry observability with local JSONL traces (#347)
Co-authored-by: 0xallam <ahmed39652003@gmail.com>
2026-03-09 01:11:24 -07:00
dependabot[bot]
048be1fe59
chore(deps): bump pypdf from 6.7.4 to 6.7.5 (#343) 2026-03-08 09:46:32 -07:00
Ms6RB
672a668ecf
feat(skills): add NestJS security testing module (#348) 2026-03-08 09:45:08 -07:00
dependabot[bot]
3c6fccca74 chore(deps): bump pypdf from 6.7.2 to 6.7.4
Bumps [pypdf](https://github.com/py-pdf/pypdf) from 6.7.2 to 6.7.4.
- [Release notes](https://github.com/py-pdf/pypdf/releases)
- [Changelog](https://github.com/py-pdf/pypdf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/py-pdf/pypdf/compare/6.7.2...6.7.4)

---
updated-dependencies:
- dependency-name: pypdf
  dependency-version: 6.7.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-02 15:34:01 -08:00
Ahmed Allam
72c3e0dd90
Update README 2026-03-03 03:33:46 +04:00
Ahmed Allam
d30e1d2f66
Update models.mdx 2026-03-03 03:33:14 +04:00
octovimmer
3e8a5c64bb chore: remove references of codex models 2026-03-02 15:29:29 -08:00
octovimmer
968cb25cbf chore: remove codex models from supported models 2026-03-02 15:29:29 -08:00
dependabot[bot]
5102b641c5 chore(deps): bump pypdf from 6.7.1 to 6.7.2
Bumps [pypdf](https://github.com/py-pdf/pypdf) from 6.7.1 to 6.7.2.
- [Release notes](https://github.com/py-pdf/pypdf/releases)
- [Changelog](https://github.com/py-pdf/pypdf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/py-pdf/pypdf/compare/6.7.1...6.7.2)

---
updated-dependencies:
- dependency-name: pypdf
  dependency-version: 6.7.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-26 14:58:52 -08:00
0xallam
30e3f13494 docs: Add Strix Platform and Enterprise sections to README 2026-02-26 14:58:28 -08:00
0xallam
5d91500564 docs: Add human-in-the-loop section to proxy documentation 2026-02-23 19:54:54 -08:00
0xallam
4384f5bff8 chore: Bump version to 0.8.2 2026-02-23 18:41:06 -08:00
0xallam
d84d72d986 feat: Expose Caido proxy port to host for human-in-the-loop interaction
Users can now access the Caido web UI from their browser to inspect traffic,
replay requests, and perform manual testing alongside the automated scan.

- Map Caido port (48080) to a random host port in DockerRuntime
- Add caido_port to SandboxInfo and track across container lifecycle
- Display Caido URL in TUI sidebar stats panel with selectable text
- Bind Caido to 0.0.0.0 in entrypoint (requires image rebuild)
- Bump sandbox image to 0.1.12
- Restore discord link in exit screen
2026-02-23 18:37:25 -08:00
mason5052
0ca9af3b3e docs: fix Discord badge expired invite code
The badge image URL used invite code  which is expired,
causing the badge to render 'Invalid invite' instead of the server info.
Updated to use the vanity URL  which resolves correctly.

Fixes #313
2026-02-22 20:52:03 -08:00
dependabot[bot]
939bc2a090 chore(deps): bump google-cloud-aiplatform from 1.129.0 to 1.133.0
Bumps [google-cloud-aiplatform](https://github.com/googleapis/python-aiplatform) from 1.129.0 to 1.133.0.
- [Release notes](https://github.com/googleapis/python-aiplatform/releases)
- [Changelog](https://github.com/googleapis/python-aiplatform/blob/main/CHANGELOG.md)
- [Commits](https://github.com/googleapis/python-aiplatform/compare/v1.129.0...v1.133.0)

---
updated-dependencies:
- dependency-name: google-cloud-aiplatform
  dependency-version: 1.133.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-22 20:51:29 -08:00
0xallam
00c571b2ca fix: Lower sidebar min width from 140 to 120 for smaller terminals 2026-02-22 09:28:52 -08:00
0xallam
522c010f6f fix: Update end screen to display models.strix.ai instead of strix.ai and discord 2026-02-22 09:03:56 -08:00
Ahmed Allam
551b780f52
Update installation instructions
Removed pipx installation instructions for strix-agent.
2026-02-22 00:10:06 +04:00
0xallam
643f6ba54a chore: Bump version to 0.8.1 2026-02-20 10:36:48 -08:00
0xallam
7fb4b63b96 fix: Change default model from claude-sonnet-4-6 to gpt-5 across docs and code 2026-02-20 10:35:58 -08:00
0xallam
027cea2f25 fix: Handle stray quotes in tag names and enforce parameter tags in prompt 2026-02-20 08:29:01 -08:00
0xallam
b9dcf7f63d fix: Address code review feedback on tool format normalization 2026-02-20 08:29:01 -08:00
0xallam
e09b5b42c1 fix: Prevent assistant-message prefill rejected by Claude 4.6 2026-02-20 08:29:01 -08:00