{"id":50319395,"url":"https://github.com/duriantaco/ravage","last_synced_at":"2026-05-31T05:00:41.130Z","repository":{"id":360900876,"uuid":"1247975650","full_name":"duriantaco/ravage","owner":"duriantaco","description":"AI pentesting research agent for controlled local labs, evidence gated exploit chains, memory-assisted learning, and benchmark eval.","archived":false,"fork":false,"pushed_at":"2026-05-29T01:59:15.000Z","size":2426,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-29T02:25:22.553Z","etag":null,"topics":["ai-agent","authorized-testing","benchmarking","dast","pentesting","python","research","security","web-security"],"latest_commit_sha":null,"homepage":"https://duriantaco.github.io/ravage/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/duriantaco.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"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-05-24T02:57:54.000Z","updated_at":"2026-05-29T01:59:03.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/duriantaco/ravage","commit_stats":null,"previous_names":["duriantaco/ravage"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/duriantaco/ravage","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duriantaco%2Fravage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duriantaco%2Fravage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duriantaco%2Fravage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duriantaco%2Fravage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/duriantaco","download_url":"https://codeload.github.com/duriantaco/ravage/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/duriantaco%2Fravage/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33719601,"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-05-31T02:00:06.040Z","response_time":95,"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":["ai-agent","authorized-testing","benchmarking","dast","pentesting","python","research","security","web-security"],"created_at":"2026-05-29T02:08:29.415Z","updated_at":"2026-05-31T05:00:41.122Z","avatar_url":"https://github.com/duriantaco.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/ravage_logo.png\" alt=\"Ravage logo\" width=\"360\"\u003e\n\u003c/p\u003e\n\n# Ravage\n\nRavage is a source-available research workspace for autonomous web application\npenetration-testing agents on controlled, authorized targets.\n\nThe current system includes:\n\n- `ravage attack`: the model-driven `ai-web` loop with scoped tool execution,\n  audit events, reports, resume support, and an optional live observer.\n- `ravage scan`: deterministic DAST probes that reuse the same scope, audit,\n  workspace, and report shape without spending model turns.\n- `ravage lab`: deliberately vulnerable local lab boxes for reproducible\n  testing.\n- Tool-runtime preflight for host or Docker scanners such as `nmap`, `ffuf`,\n  `katana`, `nuclei`, and `sqlmap`.\n- Optional local Ravage Memory for reviewed, redacted, replay-backed lessons.\n- Benchmark harnesses for local manifests and XBEN-style controlled runs.\n\n## Responsible Use\n\nRead [DISCLAIMER.md](DISCLAIMER.md) and [LICENSE](LICENSE) before running\nanything. Ravage is provided for research under a restrictive research license;\nit is not open-source software.\n\nOnly use Ravage against systems you own or have explicit written authorization\nto test, inside the agreed rules of engagement. Do not run it against public\ninternet targets, production services, customer environments, employer systems,\nor any machine outside your authorization.\n\nThe lab boxes in this repository intentionally contain serious vulnerabilities.\nRun them only on localhost or an isolated private lab network. Do not expose\nthem to a public or shared network.\n\n## Scope Enforcement\n\nRavage is localhost-first. Remote targets require `--allow-remote-target` and\nmust be explicitly listed in the engagement `scope.in_scope`. HTTP and browser\nactions are checked against scope, redirects are rechecked before following, and\nterminal tools are allowlisted to scoped network tools only.\n\nThe runtime records an `orchestrator/scope_firewall_plan_generated` audit event,\nbut it does not automatically install firewall rules on the host. Treat that\nevent as a firewall plan, not evidence that kernel-level egress filtering was\napplied. The plan is intentionally IP/CIDR-only for network destinations, so\nhostname entries are skipped rather than relying on DNS at rule-install time.\nThe Docker scope-enforcement integration test applies rules explicitly inside\nits Kali container.\n\n## Install From Source\n\nRavage is currently a source-checkout project. There is no published Ravage\nPyPI release yet, and there are no tagged releases yet.\n\nUse Python 3.12. The workspace is managed with `uv`:\n\n```bash\nuv sync --frozen\nsource .venv/bin/activate\nravage --help\nravage --version\n```\n\nFor a fresh local wheel-style install without relying on the checkout venv,\ninstall the shared schemas and runtime package together:\n\n```bash\npython3.12 -m venv .venv\n.venv/bin/python -m pip install packages/schemas packages/ravage\n.venv/bin/ravage --help\n.venv/bin/ravage --version\n```\n\nExternal scanners are not Python dependencies. Check or install them where the\nRavage process runs:\n\n```bash\nravage tools check\nravage tools install\nravage tools install --method docker --execute\n```\n\n`ravage tools install` is a dry run unless `--execute` is passed.\n\n## Local Lab Quickstart\n\nList the local boxes:\n\n```bash\nravage lab list\n```\n\n- `ravage-acme-box`: Python support portal with login, invoices, catalog\n  search, JWT admin access, SSRF, and 4 default flags.\n- `ravage-forgeops-box`: Go release-operations portal with project BOLA,\n  audit query injection, weak JWT, artifact traversal, diagnostics command\n  injection, SSRF, extra non-flag findings, and 6 default flags.\n- `ravage-node-market-box`: Node/Express market portal with order BOLA,\n  catalog SQL injection, JWT admin confusion, prototype-pollution-style beta\n  config abuse, internal admin pivot, and 5 default flags.\n- `ravage-perimeter-box`: Python two-service perimeter lab with hidden edge\n  backup/debug paths, a secondary ops port, default credentials, audit SQL\n  injection, authenticated export traversal, and 5 default flags.\n\nStart the Acme support portal:\n\n```bash\nravage lab up ravage-acme-box\n```\n\nRun a deterministic scan:\n\n```bash\nravage scan labs/ravage-acme-box/brief.yaml \\\n  --profile web-basic \\\n  --max-actions 40 \\\n  --observe\n```\n\nRun the model-driven agent with a hosted OpenAI-compatible profile:\n\n```bash\nexport OPENAI_API_KEY=...\n\nravage attack labs/ravage-acme-box/brief.yaml \\\n  --observe \\\n  --model-profile hosted-openai \\\n  --model-tier low \\\n  --tool-runtime auto \\\n  --tool-image ravage-kali:latest \\\n  --memory off \\\n  --allow-paid-models\n```\n\nStop the box:\n\n```bash\nravage lab down ravage-acme-box\n```\n\nEvery `ravage attack` run writes:\n\n```text\nruns/\u003cbrief\u003e-\u003ctimestamp\u003e/\n  audit.db\n  agent.stdout\n  report.json\n  workspace/\n```\n\nEvery `ravage scan` run writes the same shape, with `scan.stdout` instead of\n`agent.stdout`.\n\nAudit rows are hash-chained as they are written. Verify an untouched run\ndirectory or direct database path with:\n\n```bash\nravage audit verify runs/\u003cbrief\u003e-\u003ctimestamp\u003e\nravage audit verify runs/\u003cbrief\u003e-\u003ctimestamp\u003e/audit.db\n```\n\nResume a previous run by pointing at the run directory, workspace directory, or\n`report.json`:\n\n```bash\nravage attack labs/ravage-acme-box/brief.yaml \\\n  --resume-from runs/brief-YYYYMMDDHHMMSS/report.json\n```\n\nAttach the observer to an existing run:\n\n```bash\nravage observe runs/brief-YYYYMMDDHHMMSS \\\n  --lab-manifest labs/ravage-acme-box/ravage-lab.yaml\n```\n\nTo run the recon-heavy perimeter lab, substitute `ravage-perimeter-box`. Its\nbrief explicitly scopes both `http://127.0.0.1:8094` and\n`http://127.0.0.1:8095`, and requires port scanning plus directory brute-force\ncapabilities:\n\n```bash\nravage lab up ravage-perimeter-box\nravage attack labs/ravage-perimeter-box/brief.yaml \\\n  --observe \\\n  --observe-port 8790 \\\n  --model-profile hosted-openai \\\n  --model-tier low \\\n  --tool-runtime auto \\\n  --tool-image ravage-kali:latest \\\n  --tool-recon \\\n  --memory off \\\n  --allow-paid-models\n```\n\nThe live web UI does not display credentials. Assisted-mode seed credentials\nlive in each lab's `OPERATOR_NOTES.md`; omit that file from the agent context\nfor stricter black-box testing. The dashboard masks captured flag values by\ndefault but shows counts, proof status, agent steps, and the current\nattack-chain stage.\n\n`ai-web` tracks coverage as access state changes. A probe that is blocked by\nauthentication or privilege is not treated as permanently done; after a cookie,\nheader, browser login, default-credential success, or JWT privilege change, the\nagent releases those blocked candidates for retry. Confirmed command injection\nand local file inclusion also get tiny read-only flag follow-ups on localhost\ncapture-flag labs only. This is deliberately evidence-gated so the agent covers\nmore ground without learning lab-specific paths or treating memory as proof.\nThe same coverage ledger now records all paths attempted by bounded multi-path\nprobes, so failed variants do not burn later turns as if they were still fresh.\nJSON account/config routes can also be checked with a bounded business-logic\nprobe for mass-assignment or merge-style privilege changes.\n\n## Included Labs\n\n| Lab | Default URL | Difficulty | Flags | Main coverage |\n| --- | --- | --- | ---: | --- |\n| `ravage-acme-box` | `http://127.0.0.1:8088` | medium | 4 | login, IDOR, SQLi, weak JWT, SSRF |\n| `ravage-forgeops-box` | `http://127.0.0.1:8090` | hard | 6 | BOLA, query injection, JWT, traversal, command injection, SSRF |\n| `ravage-node-market-box` | `http://127.0.0.1:8092` | medium | 5 | BOLA, SQLi, JWT confusion, config merge abuse, SSRF |\n| `ravage-perimeter-box` | `http://127.0.0.1:8094` and `:8095` | hard | 5 | multi-port recon, hidden paths, default credentials, SQLi, traversal |\n\nSee [BENCHMARKS.md](BENCHMARKS.md) for scoring rules and latest local run\nnotes.\n\n## Model Providers\n\n`ai-web` uses OpenAI-compatible chat-completions routes. Built-in profiles cover\nlocal Ollama, LM Studio, vLLM, LiteLLM, and hosted OpenAI-compatible APIs.\n\nInspect routes:\n\n```bash\nravage --print-model-routes \\\n  --model-profile local-ollama \\\n  --model-tier mid\n```\n\nUse hosted models only with explicit spend acknowledgement:\n\n```bash\nravage attack labs/ravage-acme-box/brief.yaml \\\n  --model-profile hosted-openai \\\n  --model-tier low \\\n  --allow-paid-models\n```\n\nSee [docs/model-providers.md](docs/model-providers.md) for provider-specific\nenvironment variables.\n\n## Memory\n\nRavage Memory is local and optional. It stores redacted candidate lessons in\nSQLite, retrieves reviewed memories as advisory hints, and only promotes\nreplay-backed lessons.\n\n```bash\nravage memory review\nravage memory show \u003cmemory_id\u003e\nravage memory promote \u003cmemory_id\u003e --reason \"replayed on controlled target\" --replay-passed\nravage memory reject \u003cmemory_id\u003e --reason \"overfit or noisy\"\nravage memory export --redacted\nravage memory gc\n```\n\nBenchmarks default memory to `off` for reproducibility. Normal local/manual\nruns default to `read`.\n\nSee [docs/memory.md](docs/memory.md).\n\n## Benchmarks\n\nRun the deterministic local SQLi benchmark:\n\n```bash\nravage --benchmark eval/local_sqli_manifest.yaml \\\n  --output-dir runs/benchmarks/local-sqli\n```\n\nRun the `ai-web` benchmark with a local model route:\n\n```bash\nRAVAGE_OLLAMA_MODEL=qwen2.5-coder:32b \\\nOLLAMA_BASE_URL=http://localhost:11434/v1 \\\nravage --benchmark eval/ai_web_manifest.yaml \\\n  --output-dir runs/benchmarks/ai-web-local\n```\n\nFor hosted routes, preflight before spending:\n\n```bash\nOPENAI_API_KEY=... \\\nravage --benchmark eval/ai_web_manifest.yaml \\\n  --output-dir runs/benchmarks/ai-web-hosted-preflight \\\n  --benchmark-model-profile hosted-openai \\\n  --benchmark-model-tier low \\\n  --benchmark-limit 1 \\\n  --benchmark-max-turns 4 \\\n  --benchmark-max-model-requests 4 \\\n  --benchmark-preflight\n```\n\nFake-model tests only prove loop mechanics and scoring behavior. They are not\nbenchmark scores.\n\n## Validation\n\nRun the fast tests:\n\n```bash\npython -m pytest packages/schemas packages/ravage/tests tests\n```\n\nRun the scope-enforcement integration test when Docker is available:\n\n```bash\npython -m pytest -k test_scope_enforcement\n```\n\n## Docs\n\n- [Responsible Use Disclaimer](DISCLAIMER.md)\n- [License](LICENSE)\n- [Docs Index](docs/README.md)\n- [AI Web Operator Guide](docs/ai-web-operator-guide.md)\n- [Model Providers](docs/model-providers.md)\n- [Ravage Memory](docs/memory.md)\n- [Benchmarking](docs/benchmarking.md)\n- [Benchmarks And Local Test Boxes](BENCHMARKS.md)\n\nPlanning and strategy documents under `docs/` are useful project history, but\nthe README, operator guide, benchmark docs, and CLI help are the operational\nsource of truth.\n\n## Packaging\n\nMany established Python security tools do publish installable packages on PyPI.\nExamples include `sqlmap`, `pwntools`, `impacket`, `mitmproxy`, `wapiti3`,\n`wafw00f`, `dirsearch`, `wfuzz`, and `arjun`. Some still recommend git, Docker,\nKali packages, or OS package managers for particular workflows, and PyPI does\nnot install non-Python scanners such as `nmap`.\n\nRavage is now arranged so the publishable runtime package is `packages/ravage`,\nwith distribution name `ravage`, import package `ravage`, and console command\n`ravage`. The repository root is still a development workspace named\n`pentest-agent`; do not publish the workspace root. The shared schema models\nare prepared as a small companion distribution, `ravage-schemas`, with the\nexisting Python import package `pentest_schemas`.\n\nBefore a PyPI release:\n\n- reserve `ravage` and `ravage-schemas` on PyPI and TestPyPI;\n- publish/install `ravage-schemas` before `ravage`;\n- decide whether any other workspace members need separate public packages;\n- keep vulnerable labs, benchmark fixtures, run artifacts, and large assets out\n  of the wheel unless explicitly packaged as separate lab extras;\n- keep external scanner installation in `ravage tools install`, not Python\n  dependencies;\n- test the final wheel on TestPyPI in a clean virtual environment.\n\nThe repository includes a GitHub Actions workflow at\n`.github/workflows/publish-pypi.yml` for PyPI Trusted Publishing. Configure\npending PyPI publishers for both `ravage-schemas` and `ravage` with:\n\n- owner: `duriantaco`\n- repository: `ravage`\n- workflow: `publish-pypi.yml`\n- environment: `pypi`\n\nVersion bumps are automated by Release Please. When conventional commits land\non `main`, `.github/workflows/release-please.yml` opens or updates a release PR\nthat bumps both publishable package versions together, updates source fallback\nversions, and refreshes `CHANGELOG.md`. Merging that release PR creates the\nmatching GitHub release tag, for example `v0.0.1`.\n\nConfigure `RELEASE_PLEASE_TOKEN` with a token or GitHub App credential if the\ngenerated release should trigger the downstream PyPI publish workflow.\n\nPublishing is triggered by publishing a GitHub release whose tag matches the\npackage version.\n\n## Versioning\n\nRavage uses semantic versioning for publishable packages and tags. Release tags\nshould use `vMAJOR.MINOR.PATCH`, for example `v0.0.1`, and the package versions\nin `packages/schemas/pyproject.toml` and `packages/ravage/pyproject.toml`\nshould match the tag without the leading `v`.\n\nConventional commit titles drive the automated bump: `fix(...)` maps to patch,\n`feat(...)` maps to minor, and breaking-change markers map to major.\n\nWhile Ravage is pre-1.0, minor releases may include breaking changes as the\nagent APIs, report shape, and packaging surface settle. Patch releases should be\nlimited to compatible bug fixes, docs corrections, and packaging fixes.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduriantaco%2Fravage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fduriantaco%2Fravage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fduriantaco%2Fravage/lists"}