corbel/QUICKSTART.md

385 lines
12 KiB
Markdown

# Build & Operation Guide
This document is the authoritative build guide and operator reference
for CorbelPurge. For the project overview and detection model, see
[README.md](README.md).
## Prerequisites
| Tool | Version | Purpose |
|---|---|---|
| **Rust** | 1.70+ stable | Compiles the scanner, CLI, and GUI |
| **Python 3** | any | Only needed to regenerate test fixtures |
Install Rust via [rustup](https://rustup.rs/):
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
```
The headless CLI has zero GUI dependencies and no native libraries.
The GUI adds `iced`, `rfd`, and `tokio` (all pure-Rust).
## Step 1 — Get the source
From a release tarball:
```bash
tar xzf corbel-purge-0.4.2.tar.gz
cd corbel-purge-0.4.2
```
From the repository:
```bash
git clone https://git.dcos.net/dcosnet/corbel.git
cd corbel
```
## Step 2 — Build the CLI
```bash
cargo build --release
```
The binary lands at `target/release/corbel-purge`. Verify it works:
```bash
./target/release/corbel-purge --help
```
You should see the usage banner listing `scan`, `scan-dir`, `study`,
and the supported flags (`--workspace`, `--abort-on-threat`, `--quiet`,
`--recursive`, `--preserve-format`, `--rules`, `--cve-db`,
`--no-clean-output`, `--move-clean`).
### Building the GUI (optional)
The iced 0.13 dashboard GUI is behind the `gui` feature flag:
```bash
cargo build --release --features gui --bin corbel-purge-gui
./target/release/corbel-purge-gui
```
### Build profiles
The release profile (in `Cargo.toml`) is tuned for production:
```toml
[profile.release]
opt-level = 3
lto = "thin"
codegen-units = 1
strip = "symbols"
```
For faster debug builds (no optimizations, faster compile):
```bash
cargo build # debug profile
```
## Step 3 — Run the test suite
```bash
cargo test
```
Expected output: 154 lib tests + 24 pipeline integration tests + 4
zip-bomb defense tests, all passing. The pipeline integration tests
include the corpus regression test
(`benign_realworld_pdf_produces_zero_findings`) which asserts that a
3-page PDF with 13 hyperlinks (kernel.org, linuxfromscratch.org,
github.com/microsoft/vscode, .ru URLs, mailto:, tel:, and URLs
containing "support", "account", "verify" in their paths) produces
zero findings.
### Regenerating test fixtures
The fixtures in `tests/fixtures/` are checked in. Regenerate them
only when changing the parser or scanner behavior:
```bash
pip install pypdf reportlab python-docx
python3 scripts/gen_fixtures.py
python3 scripts/gen_md_epub_fixtures.py
python3 scripts/gen_docx_fixtures.py
python3 scripts/gen_zip_bomb_fixtures.py
python3 scripts/gen_benign_realworld_pdf.py
```
## Step 4 — Scan your first file
```bash
./target/release/corbel-purge scan suspicious_document.pdf
```
If the file contains threats, the summary block prints to stdout and
the pipeline writes:
- A quarantine tarball in `./corbel_quarantine/`
(`quarantine_<ts>_<sha>.tar.gz`) containing `original.<ext>`,
`report.json`, `report.md`, and one `.bin` per carved payload
(plus paired `.hex` and `.info` files for each payload).
- A cleansed Markdown derivative in `./corbel_clean/`
(`cleansed_<ts>_<sha>.md`).
- Standalone `report_<ts>_<sha>.json` and `.md` for programmatic
access in `./corbel_quarantine/`.
If the file is clean (zero malicious findings), the pipeline writes:
- A clean-output copy in `./corbel_clean/`
(`clean_<ts>_<sha>.<ext>`) — the source file byte-for-byte.
- Standalone `report_<ts>_<sha>.json` and `.md` confirming the scan
ran and the document was clean.
## Step 5 — Try PreserveFormat mode
For a cleaned version that keeps the original format (e.g. a cleaned
`.epub` you can read in an e-reader):
```bash
./target/release/corbel-purge scan research_paper.epub --preserve-format
```
Produces `cleansed_<ts>_<sha>.epub` with malicious entries stripped
from the ZIP container but chapter text preserved. Works for PDF and
DOCX too.
## Step 6 — Pipeline-stage mode
The scanner acts as a pipeline stage: input files flow through and
clean ones end up in the output folder alongside the cleansed
derivatives of malicious ones.
```bash
# Default: copy clean files to ./corbel_clean/
./target/release/corbel-purge scan inbox/file.pdf
# Queue-draining: move (not copy) clean files to output, remove source
./target/release/corbel-purge scan inbox/file.pdf --move-clean
# Reports only, no clean-output copy
./target/release/corbel-purge scan inbox/file.pdf --no-clean-output
```
Downstream processing can then operate on the contents of
`corbel_clean/` without inspecting each file's report — every file
there has been verified clean.
## Step 7 — Scan a directory
```bash
./target/release/corbel-purge scan-dir /path/to/inbox --recursive --workspace /tmp/corbel
```
The directory walker picks up `.pdf`, `.epub`, `.md`, `.markdown`, and
`.docx` files. Each file is logged with a `[OK]`, `[MALICIOUS]`, or
`[ERROR]` tag.
## Step 8 — CI gate
Use `--abort-on-threat` to make CorbelPurge a CI gate. Exit code 2
means threats were found:
```bash
./target/release/corbel-purge scan incoming_document.pdf --abort-on-threat --quiet
# exit 0: clean
# exit 2: has threats -> fail the build
# exit 1: hard error (parse failure, IO, etc.)
```
`--quiet` suppresses the summary block and prints only the JSON
report path, which is handy for piping into downstream tooling.
## Step 9 — External threat-intel feeds (optional)
The built-in signature tables and CVE database are static. Layer your
own on top at runtime:
```bash
# Load additional signature rules
./target/release/corbel-purge scan suspicious.pdf --rules my_rules.json
# Load additional CVE signature entries
./target/release/corbel-purge scan suspicious.docx --cve-db my_cve_db.json
# Or set them via environment variables
export CORBEL_EXTERNAL_RULES=/etc/corbel/rules.json
export CORBEL_EXTERNAL_CVE_DB=/etc/corbel/cve_db.json
./target/release/corbel-purge scan suspicious.pdf
```
External rules are matched alongside the built-in tables; nothing is
overridden. See `MANIFEST.md` for the JSON schema. Supported
external-rule types:
- `homograph-host-list` — additional exact-match homograph host strings
- `signature-list` — additional `(offset, magic_bytes, name)` entries
- `shellcode-list` — additional shellcode prologue byte patterns
(Legacy `tld-list`, `keyword-list`, and `brand-list` rule types are
silently skipped — the scanner no longer consults those tables.)
## Step 10 — Study a document in place
The `study` subcommand renders the source document to a single
annotated HTML file with malicious regions wrapped in inline `<span>`
tags, color-coded by classification. Use it when you want to see
exactly where the exploit sits in context, without leaving the source
format:
```bash
./target/release/corbel-purge study suspicious.epub
```
Output lands at `study_<ts>_<sha>.html` in the workspace. Quiet mode
(`-q`) prints just the path.
## CLI flags reference
| Flag | Default | Purpose |
|---|---|---|
| `--workspace <dir>` | CWD | Root for `corbel_quarantine/` and `corbel_clean/` output dirs |
| `--abort-on-threat` | off | Exit with code 2 if any malicious finding fires |
| `--quiet`, `-q` | off | Print only the JSON report path on success |
| `--recursive`, `-r` | off | Recurse into subdirectories (`scan-dir`) |
| `--preserve-format` | off | Repackage cleansed document in original format |
| `--rules <path>` | unset | Path to external signature-rules JSON |
| `--cve-db <path>` | unset | Path to external CVE database JSON |
| `--no-clean-output` | off | Do NOT copy clean documents to output folder |
| `--move-clean` | off | Move (not copy) clean source files to output folder |
## Exit codes
| Code | Meaning |
|---|---|
| `0` | No threats found |
| `1` | Hard error (parse failure, IO failure, etc.) |
| `2` | One or more malicious findings (file was processed) |
## Environment variables
| Variable | Default | Purpose |
|---|---|---|
| `CORBEL_QUARANTINE_DIR` | `./corbel_quarantine` | Quarantine tarball + reports output dir |
| `CORBEL_CLEANSE_DIR` | `./corbel_clean` | Cleansed document + clean-output copy dir |
| `CORBEL_ABORT_ON_THREAT` | `false` | Abort on first malicious finding |
| `CORBEL_EMIT_SUSPICIOUS` | `false` | Include Suspicious findings (no default detector produces any) |
| `CORBEL_EMIT_MARKDOWN_REPORT` | `true` | Generate Markdown report alongside JSON |
| `CORBEL_EMIT_CLEAN_OUTPUT` | `true` | Copy clean documents to output folder |
| `CORBEL_MOVE_CLEAN_TO_OUTPUT` | `false` | Move (not copy) clean source files to output |
| `CORBEL_TOTAL_ARCHIVE_SCAN_CAP` | `268435456` (256 MiB) | Cumulative cap across all entries in a multi-entry archive |
| `CORBEL_EXTERNAL_RULES` | (unset) | Path to external signature-rules JSON |
| `CORBEL_EXTERNAL_CVE_DB` | (unset) | Path to external CVE database JSON |
## Expected output examples
### Clean file
```
────────────────────────────────────────────────────────────
scan complete: pdf
source: benign.pdf
sha256: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
text nodes: 12
vectors: 0
findings: 0 malicious, 0 educational, 0 total
cleansed: ./corbel_clean/clean_20260801T120000_9f86d081.pdf
json report: ./corbel_quarantine/report_20260801T120000_9f86d081.json
md report: ./corbel_quarantine/report_20260801T120000_9f86d081.md
────────────────────────────────────────────────────────────
```
### Threat found
```
────────────────────────────────────────────────────────────
scan complete: pdf
source: suspicious.pdf
sha256: a1b2c3...
text nodes: 8
vectors: 1
findings: 1 malicious, 0 educational, 1 total
quarantine: ./corbel_quarantine/quarantine_20260801T120000_abc12345.tar.gz
cleansed: ./corbel_clean/cleansed_20260801T120000_abc12345.pdf
json report: ./corbel_quarantine/report_20260801T120000_abc12345.json
md report: ./corbel_quarantine/report_20260801T120000_abc12345.md
────────────────────────────────────────────────────────────
```
Exit code is `2` when any malicious finding is produced.
## Troubleshooting
### Build fails on `lopdf` or `zip`
These crates occasionally need a newer Rust than the MSRV declared in
their `Cargo.toml`. Update Rust:
```bash
rustup update stable
```
### GUI binary not found
The GUI is behind the `gui` feature flag. Build with:
```bash
cargo build --release --features gui --bin corbel-purge-gui
```
### Scanner reports zero findings on a document I expected to be flagged
Confirm the document actually contains a Category 1 or Category 2
detector trigger (see [README.md](README.md) for the table). The
scanner does not flag based on reputation, file source, or filename.
Run with `cargo run -- scan file.pdf` for verbose output.
### Quarantine tarball missing
The tarball is written only when `malicious_count() > 0`. Clean
documents produce only `report_<ts>_<sha>.{json,md}` and a
`clean_<ts>_<sha>.<ext>` copy in the output folder.
### Test failure on `benign_realworld_pdf_produces_zero_findings`
This is the corpus regression test. If it fails, a detector is
wrong by construction — the detector fired on a clean document. Inspect
the test's failure output for the specific detector that fired and
tighten that detector's rule.
## Installation
After building, install the binary to a system path:
```bash
cargo install --path .
# or
sudo cp target/release/corbel-purge /usr/local/bin/
```
For system-wide configuration, set environment variables in
`/etc/corbel/env` or your shell profile:
```bash
export CORBEL_QUARANTINE_DIR=/var/lib/corbel/quarantine
export CORBEL_CLEANSE_DIR=/var/lib/corbel/clean
export CORBEL_EXTERNAL_RULES=/etc/corbel/rules.json
export CORBEL_EXTERNAL_CVE_DB=/etc/corbel/cve_db.json
```
## Next steps
- Read [README.md](README.md) for the project overview and detection model
- Read [MANIFEST.md](MANIFEST.md) for the detailed technical specification
- Read [TODO.md](TODO.md) for the development roadmap
- Read [FIX-NOTES-false-positive-redesign.md](FIX-NOTES-false-positive-redesign.md)
for the design notes on the two-category detector model
## Contact
**Jeremy Anderson** — [dcos.net](https://dcos.net) — [info@dcos.net](mailto:info@dcos.net)