Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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`, then read the selected one via `get_note(note_id=...)` before analysis
- Before `agent_finish`/`finish_scan`, update the shared repo wiki 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