Metadata-Version: 2.4
Name: vardrrunner
Version: 0.50.0
Summary: Local automation runner for the VardrSec product family
Author: Jorge Aquino
License-Expression: MIT
Project-URL: Homepage, https://github.com/VardrSec/VardrRunner
Project-URL: Repository, https://github.com/VardrSec/VardrRunner
Project-URL: Changelog, https://github.com/VardrSec/VardrRunner/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/VardrSec/VardrRunner/issues
Project-URL: Security, https://github.com/VardrSec/VardrRunner/security/policy
Keywords: security,bug-bounty,recon,automation,cli,vardrsec
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Information Technology
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Security
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: typer>=0.12
Requires-Dist: rich>=13
Requires-Dist: requests>=2.31
Requires-Dist: keyring>=24
Provides-Extra: mcp
Requires-Dist: mcp<3,>=2; extra == "mcp"
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-cov>=5; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Requires-Dist: mypy>=1.11; extra == "dev"
Requires-Dist: types-requests>=2.31; extra == "dev"
Requires-Dist: bandit>=1.7; extra == "dev"
Requires-Dist: cryptography>=42; extra == "dev"
Requires-Dist: mcp<3,>=2; extra == "dev"
Dynamic: license-file

# VardrRunner

**The local automation runner for the VardrSec product family.**

VardrRunner runs your security tooling on *your* machine and syncs the results to a
VardrSec backend (today: [VardrMap](https://github.com/VardrSec/VardrMap)) over HTTP.
It runs only when you invoke a command: execute a tool or pipeline directly, or use
`jobs run` to claim queued jobs once, report progress, and upload results. It never
installs a startup service or starts a background scan worker.

> **Why local?** Recon and scanning tools belong on the operator's box — their bandwidth,
> their IP, their tool versions. The backend orchestrates and stores; the runner does the
> work. The two are fully decoupled and only ever exchange JSON.

---

## Features
- **Manual queue execution** — `jobs run` claims and executes pending jobs once, then exits
- **Manual invocation only** — no startup registration, detached daemon, or automatic queue polling
- **Tool runners** — `httpx`, `subfinder`, `nuclei`, `nmap`, `dnsx`, `naabu`, `katana`
  (crawler), `gau` (archived URLs),
  each capturing output into an atomically unique run directory, every run bounded by a
  timeout that terminates the complete child-process tree
- **Pinned, verified tool installs** — `tools install --all` downloads exact versions of
  httpx, subfinder, nuclei, dnsx, naabu, katana, gau, ffuf and dalfox into one folder, `~/.vardrmap/tools`, after
  checking each against a SHA-256 pinned in this package. The runner re-checks every
  managed binary before use and refuses to run one that has changed
- **Recon pipelines** — chain tools in one command: `recon` (subfinder → httpx → nuclei),
  `deep` (adds dnsx resolution), `ports` (subfinder → dnsx → naabu), `quick`
- **VardrGate authorization tests** — `vardrgate_api_test` jobs drive the local `vardrgate`
  binary over a CLI/JSON contract and attach the sanitized result to the job. Identity
  credentials may reference a secret (`value_env` / `value_keychain`) that is resolved on
  the runner at execution time, so the secret never reaches the backend
- **Importers** — pull existing `nuclei` / `httpx` output files into the backend
- **Real heartbeat** — reports hostname, version, OS, and per-tool availability so the
  backend's Bridge shows live machine status
- **Crash-safe queue execution** — journals each backend job in local SQLite before claim,
  reconciles interrupted work, hashes artifacts, and writes portable run manifests
- **Sanitized audit evidence** — `audit list`, `audit show`, and atomic JSON exports without
  raw targets, credentials, request bodies, or headers
- **Small-team operations** — stable runner UUID/name, rotating JSON logs, strict production
  preflight, and native systemd/launchd/Windows Scheduled Task management
- **AI agent integration (MCP)** — `vardrrunner mcp` serves the engagement to an MCP client
  (Claude Code, Claude Desktop): the agent reads scope, findings, assets, recon and jobs, and
  queues scans or drafts findings with your approval. No tool can edit scope or delete, so
  target-controlled output can't steer it. Optional extra: `pip install 'vardrrunner[mcp]'`
- **Reviewed authorization-case authoring** — `test-cases draft` turns observed API operations or an
  OpenAPI file into VardrGate drafts in a review file that is never overwritten; `test-cases save
  --reviewed` stores them. Drafts never contain credentials and never guess who should have access
- **Shared API playbooks and execution evidence** — MCP reads Map's original versioned API guides and filtered job/case/identity evidence. Six instruction-only prompts guide the work without fetching data during expansion; they do not save reviewed cases or commit client deliverables
- **Gate result binding** — refuse a case changed between polling and claim, and retain a hash of the unresolved case with the result artifact. Map uses it to distinguish bound assessments from legacy or unknown results; a completed command does not certify a secure API
- **Guided verified setup** — one idempotent `init` command for interactive onboarding or
  non-interactive host provisioning, ending in a doctor acceptance gate
- **Bounded execution** — schema/capability negotiation, target and artifact ceilings,
  free-disk reserve, and optional parallelism that never overlaps one engagement
- **Live job events** — emits `started → targets_resolved → running → uploaded → done/failed`
  so the backend Terminal shows real-time logs
- **Preflight (`doctor`)** — one command validates the whole machine (creds, URL, perms,
  auth, daemon, disk, tools, pipelines) and exits non-zero on actionable failures, for
  scripted host preflight
- **Safe by default** — missing tools fail the job loudly, targets are normalized before
  use, risky target classes can be denied locally, and the API key is stored locally with
  restrictive permissions

## Requirements
- Python **3.10+**
- The external tools you intend to run. `vardrrunner tools install --all` installs verified builds of `httpx`, `subfinder`, `nuclei`, `dnsx`, `naabu`, `katana`, `gau`, `ffuf` and `dalfox`; `nmap` comes from your OS installer or package manager, and `vardrgate` (for `vardrgate_api_test` jobs) from its repository. Tools already on your `PATH` still work and are reported as unverified
- For ffuf, supply a named wordlist in `~/.vardrmap/wordlists` (for example `common.txt` for `--wordlist common`); none ship with the runner
- A VardrSec backend URL and an API key (`vmap_…` for VardrMap)
- VardrMap **≥ v0.22.0** as the backend — the runner calls `/engagements/*` (see [CHANGELOG](CHANGELOG.md) v0.27.0)

That is the baseline API requirement, not support for every newer feature. Shared
playbooks, evidence reads and bound assessments require the matching Map endpoints
and migration; deploy that backend first. These features ship in Runner 0.47.0.
Identity preflight additionally requires [VardrGate v0.1.0 or newer](https://github.com/VardrSec/VardrGate/releases).
Install its verified binary on your `PATH` before enabling preflight cases.
See [API assessment guidance](docs/cli.md#api-assessment-guidance).

## Install

```bash
pipx install vardrrunner
```

That's it — [pipx](https://pipx.pypa.io) puts `vardrrunner` on your `PATH` in its own
isolated environment, which is what you want for a CLI. `pip install vardrrunner` also
works if you're already inside a virtualenv you manage yourself.

### No Python on the machine?

Common on a fresh VPS or a clean Windows box. [uv](https://docs.astral.sh/uv/) is a single
static binary that downloads its own CPython, so it needs nothing preinstalled:

```bash
# install uv itself
curl -LsSf https://astral.sh/uv/install.sh | sh        # macOS / Linux
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"   # Windows

uv tool install vardrrunner
```

`uvx vardrrunner <command>` runs it without installing at all — handy for a one-shot job on
a box you don't intend to keep.

### Other options

**From a GitHub Release** — every tag ships a wheel, an sdist, a CycloneDX SBOM, and a
build-provenance attestation. Use this when you need to verify the artifact before
installing it:

```bash
pipx install ./vardrrunner-<version>-py3-none-any.whl
```

**From source**, for development:

```bash
git clone https://github.com/VardrSec/VardrRunner.git
cd VardrRunner
python -m venv venv
.\venv\Scripts\Activate.ps1     # Windows  (macOS/Linux: source venv/bin/activate)
pip install -e ".[dev]"
```

Note that a clone alone does **not** give you the `vardrrunner` command — it has to be
installed into an environment on your `PATH`, which is what the `pip install -e` step
above does. Inside a venv you'll need it activated; `pipx`/`uv` avoid that entirely.

> Homebrew / Scoop formulae are planned once there's demand.

## Quick start
```bash
vardrrunner init               # guided setup for manual use; no background startup
vardrrunner tools install --all   # pinned, verified tools into ~/.vardrmap/tools
```

Installation and normal setup create no startup task, launch no daemon, and do not offer
background startup in a prompt. VardrRunner runs when you invoke it. Use `vardrrunner jobs run`
to execute queued jobs manually. If an older setup installed automatic startup, remove it
with `vardrrunner service uninstall`; upgrading alone does not remove an existing service.

`service install`, `daemon start`, and legacy setup service flags are no longer
supported, including their former opt-in flags. Install the program with `pipx install
vardrrunner`; install scan dependencies with `tools install`. See
[legacy cleanup instructions](docs/cli.md#service--legacy-startup-cleanup).

### One-shot usage
```bash
vardrrunner engagements                                       # list your engagements
vardrrunner scope <engagement-id>                             # show in/out-of-scope items
vardrrunner jobs list                                         # show the backend queue
vardrrunner jobs run                                          # claim + execute all pending jobs once
vardrrunner audit list                                        # inspect durable local job evidence
vardrrunner identity set-name chicago-runner-1                # durable human label
vardrrunner --version                                         # installed version
vardrrunner update                                            # install the newest release (pipx)
vardrrunner update check                                      # only check for one
vardrrunner run subfinder --engagement <engagement-id>        # run a single tool and upload results
vardrrunner import nuclei --engagement <engagement-id> -f out.jsonl
```
`--engagement` takes the engagement UUID; `--program` and `-p` are accepted as aliases.

See **[docs/cli.md](docs/cli.md)** for the full command reference.

## Configuration

**Desktop / dev:** `vardrrunner login` stores your API key in the **OS keychain** (macOS
Keychain, Windows Credential Locker, Linux Secret Service), leaving only the backend URL in
`~/.vardrmap/config.json`. Where no keyring backend is available, login fails closed unless
you explicitly pass `--allow-plaintext-credentials`; on headless boxes and containers,
prefer `VARDRMAP_API_KEY` below. `vardrrunner credentials` reports which source is actually
in use, and `vardrrunner logout` removes the key from both.

**CI / servers / containers:** set credentials via environment variables (no keychain
needed). The key resolves in this order — **`VARDRMAP_API_KEY` env → OS keychain → config
file**:

| Variable | Purpose |
|----------|---------|
| `VARDRMAP_URL` | Backend base URL (must be `https://`, except `localhost`) |
| `VARDRMAP_API_KEY` | Your `vmap_` API key |
| `VARDRRUNNER_TOOL_TIMEOUT` | Per-tool run timeout in seconds (default 1800); a hung tool is killed and the job marked failed |
| `VARDRRUNNER_ALLOW_INSECURE` | Set to `1` to permit a plain-HTTP backend URL (not recommended) |
| `VARDRUNNER_NAME` | Optional display/heartbeat label; does not replace the stable UUID |
| `VARDRUNNER_MAX_TARGETS` | Queue target ceiling (default 500; range 1–100000) |
| `VARDRUNNER_MAX_ARTIFACT_MB` | Artifact ceiling before upload (default 100 MiB; range 1–10240) |
| `VARDRUNNER_MAX_CONCURRENT_JOBS` | Parallel engagement groups (default 1; range 1–8) |
| `VARDRUNNER_MIN_FREE_DISK_MB` | Required free-space reserve (default 512 MiB; 0 disables) |
| `VARDRRUNNER_DENY_TARGETS` | Comma-separated target classes, literal hosts, or CIDRs to block locally; nothing is denied by default |
| `VARDRRUNNER_ALLOW_DENIED_TARGETS` | Set to `1` for an explicit, audited override of local deny rules |

The runner refuses to send your API key over plain HTTP to a non-local host, so a mistyped
`http://` URL can't leak your key.

Environment credentials apply to the command you explicitly invoke. Use the OS keychain
for stored credentials; VardrRunner does not install a service to keep them running.

## Documentation
- [docs/architecture.md](docs/architecture.md) — how the runner is structured and how it talks to the backend
- [docs/development.md](docs/development.md) — local setup, testing, and contribution workflow
- [docs/cli.md](docs/cli.md) — complete command and flag reference
- [docs/adr/](docs/adr/) — Architecture Decision Records
- [SECURITY.md](SECURITY.md) — private vulnerability reporting and support policy
- [CHANGELOG.md](CHANGELOG.md) — version history

## Development & testing
```bash
pip install -e ".[dev]"   # editable install + dev tools (pytest, ruff, mypy)
ruff check vardrrunner tests           # lint
ruff format --check vardrrunner tests  # formatting
mypy vardrrunner                       # type check
pytest tests                          # scanner smoke tests skip unless explicitly enabled
```
CI runs ruff (lint + format), mypy, and a bandit security scan, then the test suite at a
95% coverage floor on Python 3.10–3.14 (Linux) plus Python 3.14 on Windows and macOS,
and a `pip-audit` dependency audit — on every push and PR to `main`.
Contributions follow the **Engineering Charter** in [CLAUDE.md](CLAUDE.md): clean code,
tests with behavior changes, documentation updated, and the relevant checks green.
Docs-only changes require a diff and Markdown-link check.

## License
[MIT](LICENSE) © 2026 Jorge Aquino.

---
*Part of the VardrSec product family — [VardrMap](https://github.com/VardrSec/VardrMap) · VardrRunner · [VardrGate](https://github.com/VardrSec/VardrGate).*
