Metadata-Version: 2.1
Name: enigmatic-red
Version: 0.1.0b1
Summary: Research-lab beta: a non-destructive vulnerability assessment agent across Infrastructure, Web App, Cloud and AI security that proves what it did.
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.28
Requires-Dist: pydantic>=2.12
Requires-Dist: pydantic-settings>=2.10
Requires-Dist: PyYAML>=6.0
Provides-Extra: dev
Requires-Dist: pytest>=9.0; extra == "dev"
Provides-Extra: persistence
Requires-Dist: SQLAlchemy<2.0,>=1.4.54; extra == "persistence"
Requires-Dist: alembic>=1.13; extra == "persistence"
Provides-Extra: reporting
Requires-Dist: reportlab>=4.0; extra == "reporting"
Provides-Extra: serve
Requires-Dist: fastapi>=0.128; extra == "serve"
Requires-Dist: uvicorn[standard]>=0.40; extra == "serve"
Requires-Dist: starlette>=0.52; extra == "serve"
Requires-Dist: websockets>=15; extra == "serve"

# Enigmatic Red

Enigmatic Red is a scope-locked, non-destructive vulnerability assessment agent:
it plans a scan, runs only capabilities it has registered, and proves afterwards
what it did. It is the assessment half of a penetration test, done automatically —
reconnaissance, enumeration and verified proof — and deliberately not the other
half: no exploitation, no escalation, no lateral movement, no impact
demonstration, and nothing that touches people or places. Nothing reaches a target
without passing scope, a signed authorisation, an action guard and the audit log
first, and nothing reaches the report unless the audit chain supports it.

**This build is a research-lab beta.** Self-hosted, no accounts, no API keys
issued to anyone, no checkout, no billing. Start with [`BETA.md`](BETA.md) —
install, test, run, what to send back, and the discipline-by-discipline table of
what this covers and what it will not.

It is not a red team, and it does not pretend to be one: it is the third of a
penetration test that can be automated, and it says so on the page, in
[`BETA.md`](BETA.md) and in the terms of use — all three rendered from one
description, `web/scope_taxonomy.py`.

* The page: <https://enigmaticred.com/> (`web/`, static). It carries no chat box:
  the chat lives on its own page, <https://beta.enigmaticred.com/>, which the landing
  page links to. That interface is **bring your own key**: it relays one turn to the
  model *you* name, with the key *you* paste in, and the deployment holds no model
  credential of its own — a turn with no key is refused (`401`) before anything is
  counted or forwarded. No key is ever issued by this project.
* The chat surface: `red` talks to your own model, and works one sentence
  with it — describe a target and a thing to check and that runs, while a
  question (`red "how do I write scope?"`) is answered and nothing else
  happens. A question needs no key when the endpoint is a model on your machine,
  and your own key (`LLM_API_KEY` or `FEATHERLESS_API_KEY`, one credential under
  either name - `red key` prompts for it and writes that line, which is the one
  way to set it without it ever reaching an argv) when it is hosted. One wheel,
  `py3-none-any`, runs it on Windows, macOS and Linux.
  Two kinds of line *are* a run, and each works typed at the prompt or passed as
  the one-shot `--message`. `/run <target>` is the one-step form: the model picks
  a single capability from the registry for that target. A plain line that names
  a target and asks for work — `hack localhost and check for anything related
  with api vulnerabilities` — is the mission form: one reading of the sentence
  fixes the anchor, then several steps, each chosen from what the last one
  showed. Both go through the same chain `red
  scan` builds — scope, signed attestation, guard, rate limit and audit log —
  with an intrusive command line stopping for your `y`/`n` on that exact line,
  both need `red init` and `red authorize` first, and neither can move off the
  asset you named: a path or service derived from it is allowed, another host
  is refused and audited. `/tools` lists what either may name. Everything else
  is still a conversation that runs nothing - though it may *read*: a chat turn
  is offered a closed, read-only list (this site's own tables, and the public
  metadata and text of a GitHub or Hugging Face repository), each one an
  unauthenticated `GET` with no target behind it and no audit line after it, and
  named in the transcript as `[read only]` rather than `[not run]`. See
  [`agent/freestyle.py`](agent/freestyle.py) and
  [`agent/mission.py`](agent/mission.py).
* The agent layer: [`agent/README.md`](agent/README.md).
* The execution and safety core: `safety/`, `tools/`, and the README in each.
* The optional database behind the evidence: `db/` — a SQLAlchemy schema, an
  Alembic tree, and a mirror of the audit chain. It is in the `persistence`
  extra and off the scan path, so a scan never needs it. See `red db --help`.
* The archived subscription surface: [`archive/billing/README.md`](archive/billing/README.md).
* The write-ups: [`writeups/README.md`](writeups/README.md) — one folder per
  piece, one page per folder at <https://enigmaticred.com/writeups/>, and the
  same folders mirrored to `github.com/Enigmatic-Red/enigmatic-red-writeups`.

```powershell
python -m venv .venv; .venv\Scripts\Activate.ps1
pip install -r requirements.txt
copy .env.example .env              # the defaults are all a local run needs
.\setup_local_model.cmd             # a model on this machine: no key, no egress
python -m pytest -q                 # the whole suite, offline, no key needed
```

macOS and Linux are the same five steps in shell form:

```bash
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env                # the defaults are all a local run needs
./setup_local_model.sh              # a model on this machine: no key, no egress
python -m pytest -q                 # the whole suite, offline, no key needed
```

The `setup_local_model.*` line is the one-click path: the script installs what
is missing, downloads an open-weight model to this machine and points the agent
at it, so a scan needs no key and no third-party model host. Windows runs
`setup_local_model.ps1`; macOS and Linux run `setup_local_model.sh`, which is
`bash` 3.2-compatible on purpose - it is the twin, not a subset. It reuses a
model the local Ollama already has rather than downloading one, honours
`OLLAMA_HOST` when the service is off the 11434 default, and leaves your `.env`
alone if you have already chosen an endpoint (backing it up to `.env.bak`
first). Pointing the agent at a local model needed no provider change, because
it already reads its endpoint from settings: the only edit under `agent/` was an
unrelated fix to the provider's `--list-models` helper, which used to print its
answer and then crash with `RuntimeError: Event loop is closed` on Windows.

For a hosted endpoint instead of a local model, `red key` prompts for your own
credential and writes it into `.env` - either name, `LLM_API_KEY` or
`FEATHERLESS_API_KEY`, are one credential - and never takes it as an argument,
because every argv this tool builds is written into the append-only audit log.
`red key --show` prints it masked and names the file it came from; `--remove`
takes the line back out.

Windows has a shorter path still, for a reader with no checkout at all: the page
offers `EnigmaticRed-Setup.exe`, a single frozen file that does the whole of the
above and then opens `red` in the same terminal. It is a *bootstrapper*
(`installer/launcher.py`, standard library only) rather than a second copy of the
agent - it installs Python with `winget` when it is missing, downloads the
versioned wheel published beside it and checks its SHA-256, runs `red init`,
installs Ollama and pulls **Llama** (`llama3.2:3b` by default: the newest Llama
that runs on a CPU, since Llama 4's smallest tag is 67 GB), writes the `.env`
block the setup script writes, and hands over to `red`. Rebuild it with
`installer/build.ps1`; `tests/test_installer.py` fails if its imports leave the
standard library or its pinned digest drifts from the wheel it ships.

Authorised testing only. The shipped scope example is loopback-only; read it
before pointing this at anything you do not own.
