{"id":50780867,"url":"https://github.com/gusta-ve/wraith","last_synced_at":"2026-06-16T01:00:35.974Z","repository":{"id":363443822,"uuid":"1263383933","full_name":"gusta-ve/wraith","owner":"gusta-ve","description":"Pipeline-based offensive security scanner: recon, web vuln testing (XSS/SQLi/IDOR/BAC) and post-exploitation. Python, no core deps.","archived":false,"fork":false,"pushed_at":"2026-06-12T02:21:37.000Z","size":267,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-12T03:15:18.367Z","etag":null,"topics":["broken-access-control","idor","offensive-security","pentest","post-exploitation","python","recon","red-team","security","security-tools"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gusta-ve.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"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-08T22:51:42.000Z","updated_at":"2026-06-12T02:21:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/gusta-ve/wraith","commit_stats":null,"previous_names":["gusta-ve/wraith"],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/gusta-ve/wraith","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gusta-ve%2Fwraith","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gusta-ve%2Fwraith/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gusta-ve%2Fwraith/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gusta-ve%2Fwraith/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gusta-ve","download_url":"https://codeload.github.com/gusta-ve/wraith/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gusta-ve%2Fwraith/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34386320,"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-15T02:00:07.085Z","response_time":63,"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":["broken-access-control","idor","offensive-security","pentest","post-exploitation","python","recon","red-team","security","security-tools"],"created_at":"2026-06-12T03:03:01.221Z","updated_at":"2026-06-16T01:00:35.962Z","avatar_url":"https://github.com/gusta-ve.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# wraith\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/hero.svg\" alt=\"wraith — offensive recon \u0026 vulnerability detection pipeline\" width=\"900\"\u003e\n\u003c/p\u003e\n\nAn offensive security scanner that runs the recon-to-detection workflow as a\npipeline of small composable phases. Point it at a target; it resolves hosts,\nscans ports, maps the web surface, tests it and reports what it finds — then\nhand the catch to [hickok](https://github.com/gusta-ve/hickok) to act on it. The\ncore has no third-party dependencies.\n\n[![PyPI](https://img.shields.io/pypi/v/wraith-sec?color=crimson\u0026label=pypi)](https://pypi.org/project/wraith-sec/)\n[![CI](https://github.com/gusta-ve/wraith/actions/workflows/ci.yml/badge.svg)](https://github.com/gusta-ve/wraith/actions/workflows/ci.yml)\n[![Release](https://img.shields.io/github/v/release/gusta-ve/wraith?color=crimson)](https://github.com/gusta-ve/wraith/releases)\n![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)\n![MIT](https://img.shields.io/badge/license-MIT-green)\n\n- [Install](#install)\n- [Usage](#usage)\n- [Phases](#phases)\n- [Web testing](#web-testing)\n- [Post-exploitation](#post-exploitation--hickok)\n- [Extending](#extending)\n- [Lab](#lab)\n\n## Install\n\npipx gives you a global `wraith` (the right call on Kali, which blocks system\npip via PEP 668):\n\n```bash\nsudo apt install -y pipx \u0026\u0026 pipx ensurepath\npipx install wraith-sec            # the command is `wraith`\npipx install \"wraith-sec[http]\"    # + httpx, faster probing\n```\n\nFrom a clone:\n\n```bash\ngit clone https://github.com/gusta-ve/wraith \u0026\u0026 cd wraith\npython3 -m venv .venv \u0026\u0026 source .venv/bin/activate\npip install -e \".[http]\"\n```\n\nOr without installing anything: `PYTHONPATH=src python3 -m wraith run target`.\n\n\u003cdetails\u003e\n\u003csummary\u003eRestricted network (proxy / broken IPv6 / HTTP-2 hiccups)\u003c/summary\u003e\n\nIf `pip`/`git` time out on PyPI or GitHub, grab the prebuilt wheel from the\n[releases page](https://github.com/gusta-ve/wraith/releases/latest) — one file,\nzero dependencies, no clone and no build step:\n\n```bash\npython3 -m venv ~/.local/share/wraith-venv\n~/.local/share/wraith-venv/bin/pip install ./wraith_sec-*.whl   # the wheel you downloaded\nln -sf ~/.local/share/wraith-venv/bin/wraith ~/.local/bin/wraith\n```\n\n`git clone` failing with *\"HTTP2 framing layer\"*? Force HTTP/1.1:\n`git config --global http.version HTTP/1.1`.\n\u003c/details\u003e\n\n## Usage\n\n`run` is the default command, so a target is all you need:\n\n```bash\nwraith target.com                              # full pipeline (no subcommand needed)\nwraith -u https://target.com:8443              # target as a URL (-u/--url); the port is scanned too\nwraith 10.10.10.5 -p resolve,tcp-scan,http-probe   # only these phases\nwraith target.com --recon                      # recon only: ports + service/version, no attack traffic\nwraith target.com -P web                       # sweep HTTP/alt-HTTP ports; -P all for a full scan\nwraith target.com -s sessions.json             # adds access-control / IDOR\nwraith target.com -v                           # progress; -v 2 = attack detail (payloads/requests), -v 3 = responses\nwraith target.com -x high                      # exit code 2 on a High+ finding\nwraith target.com --delay 0.5 --jitter 0.5     # quiet: pace requests, randomise the timing\nwraith target.com --random-agent               # send a real browser UA, not wraith/\u003cver\u003e\nwraith target.com --proxy http://127.0.0.1:8080  # route through Burp (or any HTTP/SOCKS proxy)\nwraith target.com --tor                        # route via Tor — verified, fails closed\nwraith target.com --ghost                      # max-opsec preset: Tor + random UA + low-and-slow, one flag\nwraith --theme matrix target.com               # crimson (default) | matrix | ice | amber | mono\nwraith showdown                                # toggle \"showdown mode\" — wraith plays the catch out (reveal + verdict)\nwraith phases                                  # list phases and their dependencies\n```\n\nA run writes a self-contained directory under a fixed per-user location —\n`~/.local/share/wraith/runs/` by default (set `WRAITH_RUNS` to move it, or\n`--workdir` per run) — so [hickok](https://github.com/gusta-ve/hickok) finds it\nfrom anywhere:\n\n```\n~/.local/share/wraith/runs/target.com-\u003cts\u003e/\n  workspace.json   every host, service, endpoint and finding (resumable)\n  report.md\n  report.html      dark, self-contained\n  findings.json\n```\n\nA run against the bundled lab (`examples/vuln_app.py`) — every finding shown is\none wraith actually catches:\n\n![a wraith run](docs/demo.svg)\n\n`--no-banner` and `--no-color` (or `NO_COLOR`) strip the cosmetics for logs and\nCI; `WRAITH_THEME` sets a default theme.\n\n## Phases\n\nEach phase declares the phases it depends on. The engine resolves that graph and\nruns independent phases concurrently; a failing phase is isolated and its\ndependents are skipped. Everything is shared through one persisted workspace.\n\n```\nresolve            DNS resolution\ntcp-scan           async TCP connect scan of common ports\nhttp-probe         status, Server header and title\ncontent-discovery  path/file wordlist with soft-404 filtering\ntech-detect        server / language / framework / CMS fingerprint\nvhost              virtual-host discovery via Host-header fuzzing\ntemplate-checks    declarative JSON/YAML vulnerability checks\nsecurity-headers   security headers, cookie flags and CORS\ninjection          XSS, SQLi (error/boolean/time), command injection, SSTI, LFI, open redirect\naccess-control     Broken Access Control and IDOR (needs sessions)\n```\n\n## Web testing\n\n`injection` crawls the target, pulls parameters from query strings and forms,\nand probes each with a battery of techniques. Every technique has a single,\nexplainable oracle — and **every hit is confirmed a second way before it's\nreported**, so a finding is evidence, not a guess:\n\n| Technique | Oracle | Confirmed by |\n|---|---|---|\n| Reflected XSS | a raw `\u003c`/`\u003e`/`\"` marker reflects unencoded | — |\n| SQLi (error-based) | a single quote raises a DB error | a *balanced* quote clears it |\n| SQLi (boolean-blind) | a TRUE condition page matches normal, FALSE diverges | a second, different injection context |\n| SQLi (time-blind) | `SLEEP`/`pg_sleep`/`WAITFOR` delays the response | a longer sleep delays proportionally more |\n| Command injection | `; sleep N` delays the response | same time-correlation proof |\n| SSTI | `{{a*b}}` comes back evaluated (the product) | a second random product |\n| Path traversal / LFI | `../../etc/passwd` returns a `root:x:0:0:` signature | read twice |\n| Open redirect | a redirect param lands in `Location` | — |\n\nVerbosity is levelled like other scanners. `-v` (level 1) is lightweight\nprogress — which parameter is being tested, crawl brackets — so a run never\nlooks frozen. `-v 2` is the full attack play-by-play: every payload, its oracle\nmeasurement (similarity ratios, response timings) and the confirmation step,\nplus each HTTP request. `-v 3` adds the responses:\n\n```bash\nwraith target.com -p injection -v      # level 1 — progress only\nwraith target.com -p injection -v 2    # the detailed attack trace\n```\n\n`security-headers` reports missing CSP/HSTS/X-Frame-Options/nosniff, weak cookie\nflags and CORS that reflects an arbitrary origin.\n\n`access-control` needs authenticated sessions. It crawls as the privileged\nsession and replays every request as the lower-privilege and anonymous ones; a\nlower principal getting identical content is a vertical bypass, and mutating\nnumeric ids surfaces IDOR. Grab a session with:\n\n```bash\nwraith login http://target/login -u alice -p secret \\\n    --user-field user --pass-field password -o sessions.json\n```\n\n## Evasion / opsec\n\nBy default wraith scans flat out from a `wraith/\u003cver\u003e` User-Agent — loud, and easy\nto attribute in a target's logs. For an authorized engagement where the footprint\nmatters, control it:\n\n```bash\nwraith target.com --ghost                      # the safest footprint, one flag: Tor + random UA + low-and-slow\nwraith target.com --delay 0.5 --jitter 0.5     # pace requests (+ random jitter)\nwraith target.com -A \"Mozilla/5.0 …\"           # an explicit User-Agent\nwraith target.com --random-agent               # a random real-browser UA per run\nwraith target.com -H \"X-Forwarded-For: 1.2.3.4\" --cookie \"session=…\"\nwraith target.com --proxy socks5h://127.0.0.1:9050   # any HTTP/SOCKS proxy (Burp, …)\nwraith target.com --tor                        # route via Tor, verified\nwraith --check-tor --tor                       # just confirm the exit, then exit\n```\n\nThe quietest run of all is `--recon`: it sends no attack traffic at all — just port\ndiscovery and service/version fingerprinting, like an `nmap -sV` (a couple of\nrequests, not a wordlist of `/wp-login.php` probes). Pair it with the knobs below to\nmap a target before deciding whether to bring the loud phases.\n\n`--delay` is enforced across every phase (the scan goes serial while it's set), so\nthe whole run is paced, not just one phase. SOCKS/Tor is native (no PySocks) and\nresolves DNS remotely (`socks5h`) so the hostname never leaks to your resolver.\n`--tor` **fails closed**: wraith verifies the exit really is Tor before sending any\nattack traffic and aborts otherwise, so a misconfigured run can't deanonymise you.\n\nDon't want to remember the knobs? `--ghost` is the one-flag preset for the safest\nfootprint — Tor (fail-closed), a random browser UA, low-and-slow pacing and serial\nrequests, all at once. Override any single piece with its own flag (`--ghost --delay\n2`). The same flag works in [hickok](https://github.com/gusta-ve/hickok).\n\n## Post-exploitation — [hickok](https://github.com/gusta-ve/hickok)\n\nwraith finds and proves the way in; landing a shell and working the box is\n[**hickok**](https://github.com/gusta-ve/hickok)'s job — wraith's companion. It\nreads a wraith run and acts on it:\n\n```bash\nhickok call          # picks up wraith's latest run on its own, flags the footholds\nhickok -l 9001       # catch the reverse shell\n```\n\nwraith holds the aces, hickok brings the eights — aces and eights, the dead\nman's hand.\n\n## Extending\n\nA phase is one file; a check can be pure data. See\n[docs/writing-a-phase.md](docs/writing-a-phase.md) and\n[docs/writing-a-template.md](docs/writing-a-template.md).\n\n```python\nfrom wraith.core.phase import Phase, register\n\n@register\nclass MyPhase(Phase):\n    name = \"my-phase\"\n    requires = frozenset({\"http-probe\"})\n\n    async def run(self, ws, console):\n        for ep in ws.endpoints:\n            ...  # ws.add_finding(...)\n```\n\n## Lab\n\n`examples/vuln_app.py` is a deliberately vulnerable app to practise against and\nto exercise every web phase: BAC, IDOR, reflected XSS, SQLi (error/boolean/time),\ncommand injection, SSTI, path traversal/LFI, open redirect, CORS, insecure\ncookies and missing headers. Its `/db?id=` is a boolean-blind SQLi over a real\n(tiny) SQLite database — point [hickok](https://github.com/gusta-ve/hickok)'s\n`hickok sql` at it to walk and dump it.\n\n```bash\npython3 examples/vuln_app.py \u0026\nwraith 127.0.0.1 -s examples/sessions.json -v\n```\n\nFor a bigger, leveled target — a whole town of rooms, tutorial to impossible —\nthere's [**deadwood**](https://github.com/gusta-ve/deadwood), the dedicated\npractice range for wraith and hickok:\n\n```bash\npipx install deadwood-sec \u0026\u0026 deadwood serve   # http://127.0.0.1:8666\nwraith 127.0.0.1:8666 -v\n```\n\n## Tests\n\n```bash\npip install -e \".[dev]\" \u0026\u0026 pytest\n```\n\n## Disclaimer\n\nBuilt for security research and testing — point it where you're meant to. What\nanyone does with it from there is theirs alone; the author takes no\nresponsibility for misuse or for any damage caused.\n\n## License\n\nMIT.\n\n---\n\n*You never saw it coming — the wraith was already holding aces.*\n\n*the aces Wild Bill was holding — Deadwood, 1876.*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgusta-ve%2Fwraith","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgusta-ve%2Fwraith","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgusta-ve%2Fwraith/lists"}