Metadata-Version: 2.4
Name: skirmisher
Version: 1.0.2
Summary: OSINT-driven initial-access engine for authorized red-team engagements.
Author-email: Uzair Varsaji <warsajiuzair@gmail.com>
Maintainer: KaliRange
License: MIT
Project-URL: Homepage, https://kalirange.com
Project-URL: Repository, https://github.com/varsaji/SKIRMISHER
Keywords: osint,red-team,recon,security,kalirange,skirmisher
Classifier: Environment :: Console
Classifier: Intended Audience :: Information Technology
Classifier: Topic :: Security
Classifier: License :: OSI Approved :: MIT License
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: rich
Requires-Dist: rich>=13; extra == "rich"
Provides-Extra: yaml
Requires-Dist: pyyaml>=6; extra == "yaml"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Dynamic: license-file

# Skirmisher

[![CI](https://github.com/varsaji/SKIRMISHER/actions/workflows/ci.yml/badge.svg)](https://github.com/varsaji/SKIRMISHER/actions/workflows/ci.yml)
&nbsp;·&nbsp; v1.0.0 &nbsp;·&nbsp; stdlib-only &nbsp;·&nbsp; one file &nbsp;·&nbsp; authorized use only

**OSINT-driven initial-access engine for _authorized_ red-team engagements.**
_KaliRange // offensive tooling_

Skirmisher turns the public exposure of an **authorized** target into a ranked,
evidence-backed way in — and then lets an operator run **scope-gated exploit
modules** against that same authorized surface. One command against an
authorized target → a confidence-scored map of who is exposed and the most
probable route to a foothold.

The differentiator isn't collection (that layer is saturated). It's the
**reasoning layer**: Skirmisher correlates scattered signals into unified,
confidence-scored identities, maps in-scope authentication surfaces, and returns
a prioritized "most-likely way in" shortlist — decisions, not another data dump.

---

## ⚠️ Authorized use only — non-negotiable

Skirmisher is built for **authorized security work only**: penetration tests,
sanctioned red-team engagements, and auditing the exposure of assets you own or
are contracted to test.

- **Scope is enforced in code, not in the docs.** Every network-touching action
  — every collector, every exploit module — is routed through
  `skirmisher.scope.Guard` and **refused unless the target is on an explicit,
  non-expired allow-list**. The policy is _default-deny_: no scope file, an
  empty allow-list, or an expired window all mean "nothing is authorized."
- **Deny beats allow.** An explicit deny entry always wins.
- **Everything is audited.** Every authorization decision — allowed _and_
  denied — is appended to a JSONL audit log so an engagement leaves a
  defensible paper trail.
- **Get written authorization before pointing this at anything.** Scope defines
  legality. Handle breach data and PII only as your engagement permits
  (GDPR / UAE PDPL and similar carry real weight).

Using this against systems you are not authorized to test is likely illegal.
Don't.

---

## Install

v0.1 is **stdlib-only** — no third-party dependencies — so it runs anywhere,
including on pre-release interpreters.

```bash
# from the repo root
pipx install .            # installs the `skirmisher` (and short `sk`) commands
# or, for development:
python3 -m venv .venv && . .venv/bin/activate
pip install -e '.[dev]'   # editable + pytest
```

### One file, no install

Skirmisher is also shipped as a **single self-contained file** — copy `skirmisher.py`
onto any box with Python 3.10+ and run it. No package, no dependencies:

```bash
python3 skirmisher.py <target>          # the whole tool, one file
```

It's generated from the package with `python3 bundle.py` (or `make single`). You can
also run the package directly without installing: `python3 -m skirmisher --help`.

### Shell completion

`skirmisher` (and its short alias `sk`) are plain commands — they work in any shell (zsh, bash, …). For
tab-completion of subcommands and module aliases:

```zsh
# zsh (source after oh-my-zsh / compinit in ~/.zshrc)
mkdir -p ~/.config/skirmisher && skirmisher completions zsh > ~/.config/skirmisher/completion.zsh
echo 'source ~/.config/skirmisher/completion.zsh' >> ~/.zshrc
```

```bash
# bash
skirmisher completions bash >> ~/.bashrc
```

---

## Quick start

New here? The [KaliRange lab walkthrough](docs/lab/walkthrough.md) runs the whole
tool end-to-end against a bundled offline fixture — no setup, no live targets.
Prefer a one-pager? The [command reference](docs/command-reference.pdf) (PDF) lists
every command, flag, and module. In the terminal: `skirmisher man` or `skirmisher <command> -h`.

Three commands. Call it, name the target, go.

```bash
skirmisher init acme.com          # scaffold a scope.json (then edit authorized_by)
skirmisher acme.com               # run the recon → ranked-access pipeline
skirmisher run probe acme.com     # run a scope-gated module at a host
```

`skirmisher <target>` is the default action (like `nmap <target>`) — no `recon` keyword
needed. `--scope` is optional; it auto-discovers `scope.json` / `scope.example.json`
in the current directory (still default-deny: no scope, nothing runs).

Try it offline against the bundled lab fixture:

```bash
skirmisher lab.local                     # full report
skirmisher lab.local -n "Jane Smith,Bill Roe"
skirmisher scope                         # what am I authorized to hit?
skirmisher scope -H vpn.lab.local        # test one host: ALLOW / DENY
skirmisher modules                       # modules + their short aliases
```

**Unix-native.** JSON goes to stdout (logs to stderr), so it pipes:

```bash
skirmisher acme.com -j | jq '.routes[0]'         # one target, JSON
skirmisher acme.com --dot | dot -Tpng -o map.png # the visual "way in" map (Graphviz)
cat hosts.txt | skirmisher - -j > out.ndjson     # many targets from stdin, NDJSON stream
skirmisher man                                   # the manual  ·  skirmisher completions zsh|bash
```

An out-of-scope target is refused **before a single packet is sent**:

```
$ skirmisher run probe 8.8.8.8
  ✗ REFUSED: run:auxiliary/tcp_service_probe on '8.8.8.8' — not on the allow-list (default-deny).
```

---

## The pipeline

Five stages, one flow. Each stage feeds the next and attaches evidence + a
confidence score.

| # | Stage | What it does |
|---|-------|--------------|
| 01 | **Profile**   | Infer email/username schema; enumerate candidate identities (offline). |
| 02 | **Correlate** | Fuse usernames, emails, avatars, names into confidence-scored identities. |
| 03 | **Enrich**    | Cross-reference identities against authorized exposure sources; flag credential-reuse. |
| 04 | **Surface**   | Map in-scope authentication surfaces (portal / webmail / VPN / SSO). |
| 05 | **Rank**      | Combine identity × surface × evidence into a prioritized "way in" shortlist. |

Then **act and report**: `skirmisher run <module> <host>` records findings to the
engagement, and `skirmisher report` turns them into a Markdown penetration-test report
(executive summary, scope, findings by severity, methodology, audit appendix).

```
target → [collectors] → normalized signals → [graph/correlate] → scored identities
       → [enrich + surface] → [scoring/rank] → ranked access plan (JSON + report)
```

---

## Architecture

Modular by design so new sources drop in without touching the core:

```
skirmisher/
  core/        Orchestrator & pipeline sequencing + EngagementContext
  scope/       Authorization guardrails, allow-list, audit log   ← safety core
  collectors/  Pluggable source adapters → normalize to Signal objects
  graph/       Entity model (Signal / Identity / Surface) + correlation engine
  scoring/     Confidence weighting & final ranking
  render/      Terminal report + machine JSON
  exploits/    Native scope-gated module framework (check / run + registry)
```

### Bundled modules

- `auxiliary/tcp_service_probe` (alias `probe`) — scope-gated TCP connect + banner grab.
- `auxiliary/http_expose` (alias `expose`) — read-only audit of an in-scope web
  surface for high-signal exposures (`.git`/`.env`, directory listing, status
  endpoints): `skirmisher run expose <in-scope-host>`.
- `auxiliary/tls_audit` (alias `tls`) — read-only TLS posture audit (deprecated
  protocol, weak cipher, expired/self-signed cert): `skirmisher run tls <in-scope-host>`.
- `auxiliary/http_fingerprint` (alias `fp`) — read-only fingerprint of a web
  surface (server, title, tech tells): `skirmisher run fp <in-scope-host>`.
- `auxiliary/http_headers` (alias `headers`) — audit security headers (HSTS, CSP,
  X-Frame-Options, cookies): `skirmisher run headers <in-scope-host>`.
- `auxiliary/ssh_audit` (alias `ssh`) — read-only SSH banner audit (SSHv1,
  outdated OpenSSH): `skirmisher run ssh <in-scope-host>`.

### Writing an exploit module

Drop a file in `skirmisher/exploits/modules/`, subclass `ExploitModule`, and it
auto-registers. Copy `modules/tcp_service_probe.py` as a template.

```python
from skirmisher.exploits.module import ExploitModule, Option, ModuleResult, Severity

class MyModule(ExploitModule):
    name = "exploit/lab/my_module"
    description = "..."
    severity = Severity.HIGH
    invasive = True                        # run() changes target state
    options = [Option("RHOST", required=True), Option("RPORT", default=8080)]

    def check(self, ctx):                  # non-invasive: is it vulnerable?
        with ctx.connect(int(ctx.store.get("RPORT"))) as sock:
            ...
        return ModuleResult.ok("looks vulnerable")

    def run(self, ctx):                    # the action, on an authorized host
        ...
        return ModuleResult.ok("done", severity=Severity.HIGH)
```

**The scope contract:** the runner authorizes every host from
`target_hosts()` (default: `RHOST` / `RHOSTS`) _before_ calling `run()`, and
`ctx.connect()` re-checks at socket-open time. A module physically cannot reach
a host that isn't in scope. If your module derives targets some other way, you
**must** override `target_hosts()` to report every host you will contact.

---

## Scope file schema

JSON (see [`scope.example.json`](scope.example.json)):

```json
{
  "engagement": "acme-external-2026",
  "authorized_by": "Jane Doe, Acme CISO",
  "authorization_ref": "SOW-2026-014",
  "expires": "2026-12-31",
  "allow": ["acme.com", "*.acme.com", "203.0.113.0/24", "198.51.100.7"],
  "deny": ["vpn-legacy.acme.com", "203.0.113.5"]
}
```

`allow` / `deny` entries may be domains (`*.` = subdomains only), bare hostnames,
IPs, or CIDRs. `engagement` and `authorized_by` are required. An empty `allow`
list is rejected.

---

## Capabilities

One tool, one version. Everything below ships in Skirmisher today:

- **Recon pipeline** — Profile → Correlate → Enrich → Surface → Rank, offline-first.
- **Correlation engine** — exact → fuzzy → perceptual avatar-hash (`avatar-linked`).
- **Credential-reuse enrichment** — `-e exposure.json` flags reused-credential identities and boosts their routes.
- **Live collectors** — `-O/--online` guard-gated DNS + TLS surface discovery on in-scope hosts.
- **Passive OSINT** — `-P/--passive` crt.sh subdomain discovery (opt-in, disclosed, in-scope-only), feeding the active probe.
- **Scope-gated modules** — `probe` (TCP banner), `expose` (HTTP exposure audit), `tls` (TLS posture).
- **Output** — human report, `--json` (NDJSON), `--dot` (Graphviz map).
- **Unix-native CLI** — `skirmisher <target>`, stdin (`skirmisher -`), completions, `skirmisher man`, global scope.

Next: PyPI publish, a broader module library, and KaliRange lab content.

## Tests

```bash
pip install -e '.[dev]'
pytest -q
```

The `tests/test_scope.py` suite guards the authorization core — those tests are
non-negotiable; if they fail, the scope guarantee is broken.

---

_Skirmisher — the open, terminal, offline engine that turns public exposure into
a ranked, **authorized** way in._
