{"id":50839682,"url":"https://github.com/balangyaoejuspher/rastray","last_synced_at":"2026-06-18T10:00:48.428Z","repository":{"id":364251194,"uuid":"1267055093","full_name":"balangyaoejuspher/rastray","owner":"balangyaoejuspher","description":"Blazing-fast static analysis CLI for security, dependency, and performance audits.","archived":false,"fork":false,"pushed_at":"2026-06-16T04:15:19.000Z","size":887,"stargazers_count":2,"open_issues_count":5,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-16T08:24:29.871Z","etag":null,"topics":["cli","dependencies-audit","linter","miettte","rust","security","static-analysis"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/balangyaoejuspher.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-12T07:17:12.000Z","updated_at":"2026-06-16T04:15:22.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/balangyaoejuspher/rastray","commit_stats":null,"previous_names":["balangyaoejuspher/rastray"],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/balangyaoejuspher/rastray","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balangyaoejuspher%2Frastray","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balangyaoejuspher%2Frastray/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balangyaoejuspher%2Frastray/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balangyaoejuspher%2Frastray/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/balangyaoejuspher","download_url":"https://codeload.github.com/balangyaoejuspher/rastray/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/balangyaoejuspher%2Frastray/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34441285,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-17T02:00:05.408Z","response_time":127,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","dependencies-audit","linter","miettte","rust","security","static-analysis"],"created_at":"2026-06-14T06:02:50.373Z","updated_at":"2026-06-17T09:01:30.427Z","avatar_url":"https://github.com/balangyaoejuspher.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rastray\n\n[![CI](https://github.com/balangyaoejuspher/rastray/actions/workflows/ci.yml/badge.svg)](https://github.com/balangyaoejuspher/rastray/actions/workflows/ci.yml)\n[![Security audit](https://github.com/balangyaoejuspher/rastray/actions/workflows/audit.yml/badge.svg)](https://github.com/balangyaoejuspher/rastray/actions/workflows/audit.yml)\n[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/balangyaoejuspher/rastray/badge)](https://securityscorecards.dev/viewer/?uri=github.com/balangyaoejuspher/rastray)\n[![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](#license)\n[![MSRV](https://img.shields.io/badge/MSRV-1.86.0-blue.svg)](Cargo.toml)\n\n\u003e Blazing-fast static analysis CLI for security, dependency, and performance audits.\n\n`rastray` is a single-binary, Rust-native command-line scanner that walks a project tree in parallel and runs a registry of pluggable analyzers against it — looking for hard-coded secrets, vulnerable or out-of-date dependencies, and hot-path performance smells. It is designed to be **fast enough to run in pre-commit hooks** and **strict enough to gate CI pipelines**.\n\nIt is **not** another lint wrapper. `rastray` carries its own crawler, its own diagnostic renderer (powered by [`miette`](https://crates.io/crates/miette)), and emits both human-friendly terminal output and machine-readable JSON from the same engine.\n\n---\n\n## Why rastray?\n\nMost security/dep/perf tools in the polyglot world fall into one of three buckets:\n\n1. **Language-locked** (`bandit` for Python, `npm audit` for Node, `cargo audit` for Rust). You end up running four of them in CI.\n2. **Heavy SaaS** (Snyk, SonarQube). Paid, network-dependent, slow.\n3. **Generic linters with plugins**. Good signal, but configuration sprawl.\n\n`rastray` aims to be the **fourth option**: one offline binary, one config-free invocation, polyglot from day one, and aggressively fast because it is built on `ignore::WalkBuilder` (the engine that powers `ripgrep`) plus a `tokio` runtime for network-bound advisory lookups.\n\n---\n\n## Installation\n\n### Prebuilt binaries _(recommended)_\n\nEach release attaches statically-linked binaries for the common\nplatforms. The shell installer downloads, checksum-verifies, and\nextracts the right archive for your OS / arch:\n\n**Linux / macOS**\n\n```sh\ncurl -fsSL https://github.com/balangyaoejuspher/rastray/releases/latest/download/install.sh | sh\n```\n\n**Windows (PowerShell)**\n\n```powershell\nirm https://github.com/balangyaoejuspher/rastray/releases/latest/download/install.ps1 | iex\n```\n\nBoth installers honor `RASTRAY_VERSION` (e.g. `0.1.0`) and\n`RASTRAY_INSTALL_DIR`. See [`install/README.md`](install/README.md) for\ndetails.\n\n### From crates.io\n\n```sh\ncargo install rastray --locked\n```\n\n### Prerequisites _(for source builds)_\n\n- **Rust** 1.86.0 or newer (`rustup default stable`)\n- A working C/C++ toolchain for linking:\n  - Windows → **Visual Studio Build Tools** with the _Desktop development with C++_ workload (provides `link.exe`)\n  - macOS → Xcode Command Line Tools (`xcode-select --install`)\n  - Linux → `build-essential` / `gcc` + `pkg-config`\n\n### From source\n\n```sh\ngit clone https://github.com/balangyaoejuspher/rastray.git\ncd rastray\ncargo build --release\n# Binary lands at ./target/release/rastray\n```\n\n---\n\n## Usage\n\n```sh\nrastray [OPTIONS] [PATH]\n```\n\n`PATH` defaults to the current directory.\n\n### Common invocations\n\n```sh\n# Scan the current project, human-friendly output\nrastray\n\n# Scan a specific directory, only show medium+ findings\nrastray ./services/api --min-severity medium\n\n# Emit JSON for CI ingestion\nrastray --json \u003e rastray-report.json\n\n# Force inclusion of hidden files and ignored paths\nrastray --hidden --no-ignore\n\n# Limit parallelism (default is num_cpus)\nrastray -j 4\n\n# Crank verbosity for debugging the crawler\nrastray -vv\n```\n\n### Flags\n\n| Flag                     | Default   | Description                                                                                 |\n| ------------------------ | --------- | ------------------------------------------------------------------------------------------- |\n| `PATH`                   | `.`       | Directory or file to scan.                                                                  |\n| `--min-severity \u003cLEVEL\u003e` | `low`     | Suppress findings below this severity. One of: `info`, `low`, `medium`, `high`, `critical`. |\n| `--json`                 | off       | Shortcut for `--format json`.                                                               |\n| `--format \u003cFMT\u003e`         | inferred  | `human`, `json`, `gh-actions`, or `sarif`. Overrides `--json` when both are set.            |\n| `-o`, `--output \u003cFILE\u003e`  | stdout    | Write `json` / `sarif` output to a file instead of stdout. No effect for `human`/`gh-actions`. |\n| `--no-ignore`            | off       | Ignore `.gitignore`, `.ignore`, and global ignore files.                                    |\n| `--hidden`               | off       | Descend into hidden files and directories.                                                  |\n| `--follow-links`         | off       | Follow symlinks during the walk.                                                            |\n| `-j`, `--threads \u003cN\u003e`    | auto      | Worker thread count for the parallel crawler.                                               |\n| `--max-depth \u003cN\u003e`        | unlimited | Cap directory recursion depth.                                                              |\n| `--config \u003cFILE\u003e`        | auto      | Path to a `.rastray.toml` config file. By default, rastray walks up from the scan path looking for one. |\n| `--no-config`            | off       | Skip config-file discovery and loading.                                                     |\n| `--fail-on \u003cLEVEL\u003e`      | inherited | Exit code 1 if any finding is at or above this severity. One of: `info`, `low`, `medium`, `high`, `critical`, `never`. Defaults to `--min-severity`. Overrides `[scan].fail_on` in config. |\n| `-v`, `--verbose`        | off       | Repeat for more detail (`-v`, `-vv`, `-vvv`).                                               |\n| `-q`, `--quiet`          | off       | Suppress non-finding output. Mutually exclusive with `--verbose`.                           |\n\n### Configuration file\n\nIf a `.rastray.toml` file exists in the scan directory (or any ancestor),\nrastray loads it automatically. Use `--config` to point at a specific file\nor `--no-config` to skip loading entirely.\n\n```toml\n[scan]\nfail_on = \"high\"            # exit non-zero only on findings \u003e= high (default: any)\n\n[scan.ignore]\npaths = [\"target/**\", \"dist/**\", \"vendor/**\"]\n\n[rules]\n\"RSTR-SEC-005\" = false                          # disable a rule entirely\n\"RSTR-PERF-001\" = { severity = \"low\" }          # downgrade a rule's severity\n\"RSTR-PERF-002\" = { enabled = false }           # explicit form\n```\n\n### Exit codes\n\n`rastray` follows the standard CI-friendly convention:\n\n| Code | Meaning                                                                |\n| ---- | ---------------------------------------------------------------------- |\n| `0`  | Scan completed; **no findings** at or above the fail-on threshold.     |\n| `1`  | Scan completed; **at least one finding** at or above the fail-on threshold. |\n| `2`  | **Runtime error** (I/O failure, malformed input, configuration error). |\n\nThe fail-on threshold defaults to `--min-severity` and can be overridden\nvia `--fail-on \u003cLEVEL\u003e` or `[scan].fail_on` in `.rastray.toml`. Use\n`--fail-on never` (or `fail_on = \"never\"`) to always exit `0` regardless\nof findings — useful for advisory CI runs.\n\nWire it into CI as:\n\n```sh\nrastray --min-severity high || exit $?\n```\n\n---\n\n## Architecture\n\n```\n                  ┌────────────┐\n                  │   cli.rs   │   clap-derive parser\n                  └─────┬──────┘\n                        │ Cli\n                  ┌─────▼──────┐\n                  │ crawler.rs │   ignore::WalkBuilder + mpsc aggregator\n                  └─────┬──────┘\n                        │ CrawlSummary\n                  ┌─────▼──────┐\n                  │  modules/  │   Analyzer trait registry\n                  │  secrets   │\n                  │  deps      │\n                  │  perf      │\n                  └─────┬──────┘\n                        │ Vec\u003cFinding\u003e\n                  ┌─────▼──────┐\n                  │ reporter.rs│   Human (miette) | JSON (serde)\n                  └────────────┘\n```\n\n- **`main.rs`** — orchestrator. Installs the `miette` hook, parses CLI, runs the crawler, dispatches analyzers, applies severity filtering, renders, returns `ExitCode`.\n- **`cli.rs`** — `clap` derive structs (`Cli`, `Severity`, `OutputFormat`). Handles `--json` / `--format` reconciliation.\n- **`crawler.rs`** — parallel filesystem walk. Hard-blocks noise dirs (`.git`, `node_modules`, `target`, `dist`, `build`, `.venv`, `venv`, `__pycache__`). Classifies each entry as `Manifest | Source | Config | Other`.\n- **`reporter.rs`** — `Finding`, `Location`, `Report`. Dual renderer: `miette::Diagnostic` for humans, `serde_json::to_string_pretty` for machines. Source spans are read lazily and degrade gracefully on I/O errors.\n- **`modules/`** — analyzer trait + registry. New analyzers implement `Analyzer` and are appended to `default_registry()`.\n\n### Adding a new analyzer\n\n1. Create `src/modules/\u003cname\u003e.rs`.\n2. Define a unit struct and implement `Analyzer`:\n   ```rust\n   pub struct MyAnalyzer;\n   impl MyAnalyzer { pub fn new() -\u003e Self { Self } }\n   impl Analyzer for MyAnalyzer {\n       fn name(\u0026self) -\u003e \u0026'static str { \"my-analyzer\" }\n       fn analyze(\u0026self, crawl: \u0026CrawlSummary) -\u003e Result\u003cVec\u003cFinding\u003e, AnalyzerError\u003e {\n           Ok(Vec::new())\n       }\n   }\n   ```\n3. Register it in `default_registry()` in `src/modules/mod.rs`.\n\n---\n\n## JSON output schema\n\n```jsonc\n{\n  \"stats\": {\n    \"files_scanned\": 0,\n    \"manifests\": 0,\n    \"source_files\": 0,\n    \"config_files\": 0,\n    \"other_files\": 0,\n    \"crawl_errors\": 0,\n    \"skipped\": 0,\n  },\n  \"perf\": {\n    \"walk_ms\": 0,\n    \"analyze_ms\": 0,\n    \"total_ms\": 0,\n    \"bytes_scanned\": 0,\n  },\n  \"findings\": [\n    {\n      \"code\": \"RSTR-XXX-000\",\n      \"message\": \"...\",\n      \"severity\": \"low|medium|high|critical|info\",\n      \"category\": \"secret|dependency|performance|crawler|internal\",\n      \"help\": \"remediation hint or null\",\n      \"location\": {\n        \"file\": \"relative/path/to/file\",\n        \"line\": 0,\n        \"column\": 0,\n        \"byte_offset\": 0,\n        \"byte_length\": 0,\n      },\n    },\n  ],\n}\n```\n\nThe JSON output is considered **stable within a minor version** and follows semantic versioning. See [`CHANGELOG.md`](CHANGELOG.md) for any schema additions.\n\n---\n\n## Continuous integration\n\nA ready-to-copy GitHub Actions workflow is available under\n[`examples/github-actions/`](examples/github-actions/). It runs `rastray`\non every push and pull request, posts findings as inline annotations\n(`--format gh-actions`), and uploads a SARIF report to GitHub Code\nScanning (`--format sarif --output rastray.sarif`).\n\nSee [`examples/github-actions/README.md`](examples/github-actions/README.md)\nfor setup instructions.\n\nDrop-in `.rastray.toml` snippets for common adoption patterns (advisory,\nstrict, monorepo) are in [`examples/config/`](examples/config/).\n\n---\n\n## Security\n\n`rastray` is itself a security-focused tool, so it holds itself to its own standards:\n\n- No `unsafe` Rust anywhere in the codebase.\n- No `unwrap` / `expect` / `panic!` in user-facing code paths.\n- TLS via `rustls` only — no OpenSSL surface area.\n- Minimal default feature flags on `tokio` and `reqwest` to keep the dependency graph small.\n- Pinned MSRV (`1.86.0`).\n\nTo report a vulnerability, please **do not** open a public issue. See [`SECURITY.md`](SECURITY.md) for the disclosure process.\n\n---\n\n## Contributing\n\n`rastray` is currently source-available but **closed to external code contributions**\nwhile the architecture stabilises. Bug reports, security reports, feature requests,\nand forks are welcome. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the full policy\nand the rules that apply to pre-approved pull requests.\n\n---\n\n## License\n\nLicensed under either of\n\n- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or \u003chttp://www.apache.org/licenses/LICENSE-2.0\u003e)\n- MIT license ([LICENSE-MIT](LICENSE-MIT) or \u003chttp://opensource.org/licenses/MIT\u003e)\n\nat your option.\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbalangyaoejuspher%2Frastray","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbalangyaoejuspher%2Frastray","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbalangyaoejuspher%2Frastray/lists"}