Skip to content
Open
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,17 @@ strix --target https://your-app.com --instruction "Perform authenticated testing
# Multi-target testing (source code + deployed app)
strix -t https://github.com/org/app -t https://your-app.com

# White-box source-aware scan (local repository)
strix --target ./app-directory --scan-mode standard

# Focused testing with custom instructions
strix --target api.your-app.com --instruction "Focus on business logic flaws and IDOR vulnerabilities"

# Provide detailed instructions through file (e.g., rules of engagement, scope, exclusions)
strix --target api.your-app.com --instruction-file ./instruction.md

# Force PR diff-scope against a specific base branch
strix -n --target ./ --scan-mode quick --scope-mode diff --diff-base origin/main
```

### Headless Mode
Expand All @@ -198,6 +204,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Install Strix
run: curl -sSL https://strix.ai/install | bash
Expand All @@ -210,6 +218,11 @@ jobs:
run: strix -n -t ./ --scan-mode quick
```

> [!TIP]
> In CI pull request runs, Strix automatically scopes quick reviews to changed files.
> If diff-scope cannot resolve, ensure checkout uses full history (`fetch-depth: 0`) or pass
> `--diff-base` explicitly.

### Configuration

```bash
Expand Down
43 changes: 42 additions & 1 deletion containers/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,36 @@ RUN mkdir -p /home/pentester/.npm-global

RUN npm install -g retire@latest && \
npm install -g eslint@latest && \
npm install -g js-beautify@latest
npm install -g js-beautify@latest && \
npm install -g @ast-grep/cli@latest && \
npm install -g tree-sitter-cli@latest

RUN set -eux; \
TS_PARSER_DIR="/home/pentester/.tree-sitter/parsers"; \
mkdir -p "${TS_PARSER_DIR}"; \
for repo in tree-sitter-java tree-sitter-javascript tree-sitter-python tree-sitter-go tree-sitter-bash tree-sitter-json tree-sitter-yaml tree-sitter-typescript; do \
if [ "$repo" = "tree-sitter-yaml" ]; then \
repo_url="https://github.com/tree-sitter-grammars/${repo}.git"; \
else \
repo_url="https://github.com/tree-sitter/${repo}.git"; \
fi; \
if [ ! -d "${TS_PARSER_DIR}/${repo}" ]; then \
git clone --depth 1 "${repo_url}" "${TS_PARSER_DIR}/${repo}"; \
fi; \
done; \
if [ -d "${TS_PARSER_DIR}/tree-sitter-typescript/typescript" ]; then \
ln -sfn "${TS_PARSER_DIR}/tree-sitter-typescript/typescript" "${TS_PARSER_DIR}/tree-sitter-typescript-typescript"; \
fi; \
if [ -d "${TS_PARSER_DIR}/tree-sitter-typescript/tsx" ]; then \
ln -sfn "${TS_PARSER_DIR}/tree-sitter-typescript/tsx" "${TS_PARSER_DIR}/tree-sitter-typescript-tsx"; \
fi; \
tree-sitter init-config >/dev/null 2>&1 || true; \
TS_CONFIG="/home/pentester/.config/tree-sitter/config.json"; \
mkdir -p "$(dirname "${TS_CONFIG}")"; \
[ -f "${TS_CONFIG}" ] || printf '{}\n' > "${TS_CONFIG}"; \
TMP_CFG="$(mktemp)"; \
jq --arg p "${TS_PARSER_DIR}" '.["parser-directories"] = ((.["parser-directories"] // []) + [$p] | unique)' "${TS_CONFIG}" > "${TMP_CFG}"; \
mv "${TMP_CFG}" "${TS_CONFIG}"

WORKDIR /home/pentester/tools
RUN git clone https://github.com/aravind0x7/JS-Snooper.git && \
Expand All @@ -110,6 +139,18 @@ RUN git clone https://github.com/aravind0x7/JS-Snooper.git && \
USER root

RUN curl -sSfL https://raw.githubusercontent.com/trufflesecurity/trufflehog/main/scripts/install.sh | sh -s -- -b /usr/local/bin
RUN set -eux; \
ARCH="$(uname -m)"; \
case "$ARCH" in \
x86_64) GITLEAKS_ARCH="x64" ;; \
aarch64|arm64) GITLEAKS_ARCH="arm64" ;; \
*) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \
esac; \
TAG="$(curl -fsSL https://api.github.com/repos/gitleaks/gitleaks/releases/latest | jq -r .tag_name)"; \
curl -fsSL "https://github.com/gitleaks/gitleaks/releases/download/${TAG}/gitleaks_${TAG#v}_linux_${GITLEAKS_ARCH}.tar.gz" -o /tmp/gitleaks.tgz; \
tar -xzf /tmp/gitleaks.tgz -C /tmp; \
install -m 0755 /tmp/gitleaks /usr/local/bin/gitleaks; \
rm -f /tmp/gitleaks /tmp/gitleaks.tgz

RUN apt-get update && apt-get install -y zaproxy

Expand Down
10 changes: 10 additions & 0 deletions docs/integrations/ci-cd.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ Use the `-n` or `--non-interactive` flag:
strix -n --target ./app --scan-mode quick
```

For pull-request style CI runs, Strix automatically scopes quick scans to changed files. You can force this behavior and set a base ref explicitly:

```bash
strix -n --target ./app --scan-mode quick --scope-mode diff --diff-base origin/main
```

## Exit Codes

| Code | Meaning |
Expand Down Expand Up @@ -78,3 +84,7 @@ jobs:
<Note>
All CI platforms require Docker access. Ensure your runner has Docker available.
</Note>
<Tip>
If diff-scope fails in CI, fetch full git history (for example, `fetch-depth: 0` in GitHub Actions) so merge-base and branch comparison can be resolved.
</Tip>
6 changes: 6 additions & 0 deletions docs/integrations/github-actions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install Strix
run: curl -sSL https://strix.ai/install | bash
Expand Down Expand Up @@ -58,3 +60,7 @@ The workflow fails when vulnerabilities are found:
<Tip>
Use `quick` mode for PRs to keep feedback fast. Schedule `deep` scans nightly.
</Tip>

<Note>
For pull_request workflows, Strix automatically uses changed-files diff-scope in CI/headless runs. If diff resolution fails, ensure full history is fetched (`fetch-depth: 0`) or set `--diff-base`.
</Note>
14 changes: 11 additions & 3 deletions docs/tools/sandbox.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,21 @@ Strix runs inside a Kali Linux-based Docker container with a comprehensive set o
| [js-beautify](https://github.com/beautifier/js-beautify) | JavaScript deobfuscation |
| [JSHint](https://jshint.com) | JavaScript code quality tool |

## Source-Aware Analysis

| Tool | Description |
| ------------------------------------------------------- | --------------------------------------------- |
| [Semgrep](https://github.com/semgrep/semgrep) | Fast SAST and custom rule matching |
| [ast-grep](https://ast-grep.github.io) | Structural AST/CST-aware code search (`sg`) |
| [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) | Syntax tree parsing and symbol extraction (Java/JS/TS/Python/Go/Bash/JSON/YAML grammars pre-configured) |
| [Bandit](https://bandit.readthedocs.io) | Python security linter |

## Secret Detection

| Tool | Description |
| ----------------------------------------------------------- | ------------------------------------- |
| [TruffleHog](https://github.com/trufflesecurity/trufflehog) | Find secrets in code and history |
| [Semgrep](https://github.com/semgrep/semgrep) | Static analysis for security patterns |
| [Bandit](https://bandit.readthedocs.io) | Python security linter |
| [Gitleaks](https://github.com/gitleaks/gitleaks) | Detect hardcoded secrets in repositories |

## Authentication Testing

Expand All @@ -64,7 +72,7 @@ Strix runs inside a Kali Linux-based Docker container with a comprehensive set o

| Tool | Description |
| -------------------------- | ---------------------------------------------- |
| [Trivy](https://trivy.dev) | Container and dependency vulnerability scanner |
| [Trivy](https://trivy.dev) | Filesystem/container scanning for vulns, misconfigurations, secrets, and licenses |

## HTTP Proxy

Expand Down
16 changes: 10 additions & 6 deletions docs/tools/terminal.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,18 @@ sqlmap -u "https://example.com/page?id=1"
### Code Analysis

```bash
# Search for secrets
trufflehog filesystem ./

# Static analysis
# Fast SAST triage
semgrep --config auto ./src

# Grep for patterns
grep -r "password" ./
# Structural AST search
sg scan ./src

# Secret detection
gitleaks detect --source ./
trufflehog filesystem ./

# Supply-chain and misconfiguration checks
trivy fs ./
```

### Custom Scripts
Expand Down
11 changes: 11 additions & 0 deletions docs/usage/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ strix --target <target> [options]
Scan depth: `quick`, `standard`, or `deep`.
</ParamField>

<ParamField path="--scope-mode" type="string" default="auto">
Code scope mode: `auto` (enable PR diff-scope in CI/headless runs), `diff` (force changed-files scope), or `full` (disable diff-scope).
</ParamField>

<ParamField path="--diff-base" type="string">
Target branch or commit to compare against (e.g., `origin/main`). Defaults to the repository's default branch.
</ParamField>

<ParamField path="--non-interactive, -n" type="boolean">
Run in headless mode without TUI. Ideal for CI/CD.
</ParamField>
Expand All @@ -50,6 +58,9 @@ strix --target api.example.com --instruction "Focus on IDOR and auth bypass"
# CI/CD mode
strix -n --target ./ --scan-mode quick

# Force diff-scope against a specific base ref
strix -n --target ./ --scan-mode quick --scope-mode diff --diff-base origin/main

# Multi-target white-box testing
strix -t https://github.com/org/app -t https://staging.example.com
```
Expand Down
4 changes: 4 additions & 0 deletions docs/usage/scan-modes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Balanced testing for routine security reviews. Best for:

**Duration**: 30 minutes to 1 hour

**White-box behavior**: Uses source-aware mapping and static triage to prioritize dynamic exploit validation paths.

## Deep

```bash
Expand All @@ -44,6 +46,8 @@ Thorough penetration testing. Best for:

**Duration**: 1-4 hours depending on target complexity

**White-box behavior**: Runs broad source-aware triage (`semgrep`, AST structural search, secrets, supply-chain checks) and then systematically validates top candidates dynamically.

<Note>
Deep mode is the default. It explores edge cases, chained vulnerabilities, and complex attack paths.
</Note>
Expand Down
23 changes: 23 additions & 0 deletions strix/agents/StrixAgent/strix_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def _build_system_scope_context(scan_config: dict[str, Any]) -> dict[str, Any]:
async def execute_scan(self, scan_config: dict[str, Any]) -> dict[str, Any]: # noqa: PLR0912
user_instructions = scan_config.get("user_instructions", "")
targets = scan_config.get("targets", [])
diff_scope = scan_config.get("diff_scope", {}) or {}
self.llm.set_system_prompt_context(self._build_system_scope_context(scan_config))

repositories = []
Expand Down Expand Up @@ -120,6 +121,28 @@ async def execute_scan(self, scan_config: dict[str, Any]) -> dict[str, Any]: #
task_parts.append("\n\nIP Addresses:")
task_parts.extend(f"- {ip}" for ip in ip_addresses)

if diff_scope.get("active"):
task_parts.append("\n\nScope Constraints:")
task_parts.append(
"- Pull request diff-scope mode is active. Prioritize changed files "
"and use other files only for context."
)
for repo_scope in diff_scope.get("repos", []):
repo_label = (
repo_scope.get("workspace_subdir")
or repo_scope.get("source_path")
or "repository"
)
changed_count = repo_scope.get("analyzable_files_count", 0)
deleted_count = repo_scope.get("deleted_files_count", 0)
task_parts.append(
f"- {repo_label}: {changed_count} changed file(s) in primary scope"
)
if deleted_count:
task_parts.append(
f"- {repo_label}: {deleted_count} deleted file(s) are context-only"
)

task_description = " ".join(task_parts)

if user_instructions:
Expand Down
20 changes: 15 additions & 5 deletions strix/agents/StrixAgent/system_prompt.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,18 @@ BLACK-BOX TESTING (domain/subdomain only):

WHITE-BOX TESTING (code provided):
- MUST perform BOTH static AND dynamic analysis
- Static: Review code for vulnerabilities
- Dynamic: Run the application and test live
- NEVER rely solely on static code analysis - always test dynamically
- You MUST begin at the very first step by running the code and testing live.
- Static: Use source-aware triage first to map risk quickly (`semgrep`, `ast-grep`, Tree-sitter tooling, `gitleaks`, `trufflehog`, `trivy fs`). Then review code for vulnerabilities
- Static coverage floor: execute at least one structural AST mapping pass (`sg` and/or Tree-sitter) per repository and keep artifact output
- Static coverage target per repository: run one `semgrep` pass, one secrets pass (`gitleaks` and/or `trufflehog`), one `trivy fs` pass, and one AST-structural pass (`sg` and/or Tree-sitter); if any are skipped, record why in the shared wiki
- Keep AST artifacts bounded and high-signal: scope to relevant paths/hypotheses, avoid whole-repo generic function dumps
- AST target selection rule: build `sg-targets.txt` from `semgrep.json` scope first (`paths.scanned`, fallback to unique `results[].path`), then run `xargs ... sg run` against that file list. Only use path-heuristic fallback if semgrep scope is unavailable, and log fallback reason in the wiki.
- Shared memory: Use notes as shared working memory; discover wiki notes with `list_notes`, read `wiki:overview` first when available, then read `wiki:security` via `get_note(note_id=...)` before analysis
- Before `agent_finish`/`finish_scan`, update `wiki:security` with scanner summaries, key routes/sinks, and dynamic follow-up plan
- Dynamic: Run the application and test live to validate exploitability
- NEVER rely solely on static code analysis when dynamic validation is possible
- Begin with fast source triage and dynamic run preparation in parallel; use static findings to prioritize live testing.
- Local execution, unit/integration testing, patch verification, and HTTP requests against locally started in-scope services are normal authorized white-box validation
- If dynamically running the code proves impossible after exhaustive attempts, pivot to just comprehensive static analysis.
- If dynamically running the code proves impossible after exhaustive attempts, pivot to comprehensive static analysis.
- Try to infer how to run the code based on its structure and content.
- FIX discovered vulnerabilities in code in same file.
- Test patches to confirm vulnerability removal.
Expand Down Expand Up @@ -460,8 +466,12 @@ JAVASCRIPT ANALYSIS:

CODE ANALYSIS:
- semgrep - Static analysis/SAST
- ast-grep (sg) - Structural AST/CST-aware code search
- tree-sitter - Syntax-aware parsing and symbol extraction support
- bandit - Python security linter
- trufflehog - Secret detection in code
- gitleaks - Secret detection in repository content/history
- trivy fs - Filesystem vulnerability/misconfiguration/license/secret scanning

SPECIALIZED TOOLS:
- jwt_tool - JWT token manipulation
Expand Down
6 changes: 5 additions & 1 deletion strix/interface/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,13 @@ async def run_cli(args: Any) -> None: # noqa: PLR0915
"targets": args.targets_info,
"user_instructions": args.instruction or "",
"run_name": args.run_name,
"diff_scope": getattr(args, "diff_scope", {"active": False}),
}

llm_config = LLMConfig(scan_mode=scan_mode)
llm_config = LLMConfig(
scan_mode=scan_mode,
is_whitebox=bool(getattr(args, "local_sources", [])),
)
agent_config = {
"llm_config": llm_config,
"max_iterations": 300,
Expand Down
Loading