# ocls — OpenClaw Security Scanner
> Offline security scanner for agentic AI framework installations.
[](https://gitlab.com/pyratzlabs/software/Openclaw_Security_Tooling_CLI/-/pipelines)
[](LICENSE)
[](https://crates.io/crates/openclaw-scan)
`ocls` scans your **OpenClaw**, **Claude Code**, or any compatible agentic AI framework
directory and produces an actionable security report — covering credential exposure,
permission misconfigurations, unsafe hook scripts, insecure MCP endpoints, and data
retention risks.
Works with **all model backends**: Claude, OpenAI, Mistral, xAI/Grok, OpenRouter,
Google Gemini, and more. The threat surface is framework-level, not model-level.
**Nothing is sent anywhere** — analysis runs entirely on your machine.
---
## Features
- **7 scanner categories** — config, secrets, permissions, network, dependencies, hooks, data exposure
- **100–0 score** with letter grade (A–F) per category and overall
- **Rich terminal output** with ANSI colour, score bars, and per-finding remediation
- **JSON output** for CI pipelines, dashboards, and `jq` scripting
- **Parallel scanning** via Rayon — fast even on large history files
- **Single static binary** — no runtime, no dependencies
- **Auto-detects** `~/.claude`, `~/.openclaw`, `$OPENCLAW_HOME`, or accepts an explicit path
---
## Installation
### Homebrew (macOS / Linux) — recommended
```bash
brew tap victorbinetruypic/ocls
brew install ocls
```
### Cargo
```bash
cargo install openclaw-scan
```
### Pre-built binary
Download the binary for your platform from the
[Releases page](https://gitlab.com/pyratzlabs/software/Openclaw_Security_Tooling_CLI/-/releases),
then:
```bash
chmod +x ocls-*
sudo mv ocls-* /usr/local/bin/ocls
```
| Linux x86\_64 (musl) | `ocls-linux-x86_64` |
| Linux aarch64 (musl) | `ocls-linux-aarch64` |
| macOS Apple Silicon | `ocls-macos-aarch64` |
| macOS Intel | `ocls-macos-x86_64` |
### From source (requires Rust ≥ 1.75)
```bash
git clone https://gitlab.com/pyratzlabs/software/Openclaw_Security_Tooling_CLI.git
cd Openclaw_Security_Tooling_CLI
cargo install --path .
```
---
## Quick start
```bash
# Auto-detect your installation and scan it
ocls
# Scan a specific directory
ocls ~/.claude
# Scan multiple directories
ocls ~/.openclaw ~/projects/my-agent/.claude
# Show only HIGH and above
ocls --min-severity high
# Full detail: remediation steps + evidence for every finding
ocls -v
# Machine-readable JSON for scripting / CI
# Scan only the secrets category
ocls --category secrets
# Disable colour output (e.g. in scripts or CI logs)
ocls --no-color
```
---
## Example output
```
╔════════════════════════════════════════════════════╗
║ ocls v0.1.0 · OpenClaw Security Scanner ║
╚════════════════════════════════════════════════════╝
Scanning ~/.claude [auto-detected · Claude Code]
FINDINGS ──────────────────────────────────────────────
● CRITICAL [Secrets] AWS key in history.jsonl:234
● HIGH [Config] Bash(*) allow rule in settings.json
● HIGH [Permissions] .credentials.json world-readable (644)
● MEDIUM [Network] HTTP MCP endpoint: http://api.example.com
● LOW [Dependencies] Plugin not updated in 90+ days
SUMMARY ───────────────────────────────────────────────
Score 67 / 100 Grade: C
Config ████████░░ 78 1 high 1 medium
Secrets ██████░░░░ 55 1 critical
Permissions ███████░░░ 70 1 high
Network ████████░░ 82 1 medium
Dependencies █████████░ 92 1 low
Hooks ██████████ 100 —
Data ████████░░ 80 —
5 findings (1 critical · 2 high · 1 medium · 1 low)
Run `ocls -v` for remediation steps.
Run `ocls --json` for machine-readable output.
```
---
## CLI reference
```
ocls [OPTIONS] [PATH]...
Arguments:
[PATH]... Path(s) to scan. Repeatable. Auto-detects if omitted.
Options:
-j, --json Output machine-readable JSON
-q, --quiet Suppress banner; findings only
-v, --verbose Show remediation and evidence per finding
--no-color Disable ANSI colour codes
--category <CATEGORY> Scan only one category
[config|secrets|permissions|network|deps|hooks|history]
--min-severity <SEVERITY> Minimum severity to show [default: low]
[critical|high|medium|low|info]
--ignore-path <GLOB> Exclude path from scan (repeatable)
-h, --help Print help
-V, --version Print version
```
### Exit codes
| `0` | No findings at or above `--min-severity` |
| `1` | One or more findings present |
| `2` | Scan error (path not found, permission denied, etc.) |
Use exit code `1` in CI to fail a build when security issues are found:
```yaml
# GitLab CI example
security-scan:
script:
- ocls --min-severity high --json > security-report.json
artifacts:
paths: [security-report.json]
```
### Path auto-detection
If no path argument is given, `ocls` probes in this order and uses the first match:
1. `$OPENCLAW_HOME`
2. `~/.openclaw/`
3. `~/.claude/`
4. `~/.config/openclaw/`
5. `./` (if it contains a known framework marker file)
---
## Scanner categories
| **Config** | `settings.json` wildcard allow rules, `dangerouslySkipPermissions`, MCP `alwaysAllow` |
| **Secrets** | AI provider keys (Anthropic, OpenAI, Mistral, xAI, OpenRouter, Gemini…), AWS/GitHub/GitLab tokens, private keys, JWTs, DB connection strings found in history, plans, debug files, and `CLAUDE.md` |
| **Permissions** | File mode bits on credentials, history, settings, and backup directories |
| **Network** | Unencrypted `http://` MCP endpoints, bare IP addresses in server configs, OAuth misconfiguration |
| **Dependencies** | Installed plugins vs. blocklist, tamper detection via stored hash, staleness (>90 days), unofficial sources |
| **Hooks** | Shell injection via unquoted variables / backticks, `--dangerously-skip-permissions`, outbound `curl`/`wget` calls, world-writable hook scripts |
| **Data Exposure** | `history.jsonl` > 10 MB, `debug/` > 50 MB, backups older than 30 days, unrotated telemetry UUIDs |
Secret evidence is always **redacted** in output (`sk-ant-****`, `ghp_****`, etc.) — the full value is never printed.
---
## Scoring
Each finding deducts points from a 100-point baseline:
| Critical | −25 pts |
| High | −12 pts |
| Medium | −5 pts |
| Low | −2 pts |
| Info | 0 pts |
Grades: **A** (90–100) · **B** (75–89) · **C** (60–74) · **D** (40–59) · **F** (<40)
Category sub-scores use the same formula applied independently per category.
---
## JSON output format
```bash
ocls --json
```
```json
{
"version": "0.1.0",
"scanned_at": "2025-03-03T10:30:00Z",
"scanned_paths": ["/home/user/.claude"],
"overall_score": 67,
"overall_grade": "C",
"total_critical": 1,
"total_high": 2,
"total_medium": 1,
"total_low": 1,
"total_info": 0,
"categories": [ ... ],
"findings": [
{
"severity": "critical",
"category": "secret_detection",
"title": "Anthropic API key in history.jsonl",
"description": "A live Anthropic API key was found at line 42 of history.jsonl.",
"path": "/home/user/.claude/history.jsonl",
"line": 42,
"evidence": "sk-ant-****",
"remediation": "Rotate the key immediately at console.anthropic.com, then clear your history."
}
]
}
```
---
## Development
### Running the tests
```bash
cargo test --all # unit + integration tests
cargo clippy -- -D warnings # lint
cargo fmt --check # formatting
```
### Adding a new scanner rule
Each scanner lives in `src/scanner/<name>.rs` and implements the `Scanner` trait.
Rules are unit-tested in the same file; integration tests go in `tests/integration/`.
See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
---
## Contributing
Bug reports, rule suggestions, and pull requests are welcome.
- **Issues:** <https://gitlab.com/pyratzlabs/software/Openclaw_Security_Tooling_CLI/-/issues>
- **Contributing guide:** [CONTRIBUTING.md](CONTRIBUTING.md)
---
## License
MIT — see [LICENSE](LICENSE).