Skip to main content
Glama
README.md
# Frugal Pentest Agent

Frugal Pentest Agent is a defensive web-security auditor for the applications you own. An LLM agent works through a web application, and optionally through its source code. Every request leaves from an isolated Docker sandbox, is checked against a scope you define, and ends up in a report with verified findings and CVSS 3.1 scores.

It is for developers who want to check their own application before they deploy it. It works with any OpenAI-compatible model, including models that run on your computer. It also runs as an MCP server, so people without an API key can use it from Claude Desktop.

> **Only test systems you own, or systems you have written permission to test.** The tool asks you to confirm this, and it refuses to send requests to hosts outside the scope you set. Read the [threat model](docs/threat-model.md) before you use it on anything that matters.

Español: [README.es.md](README.es.md)

## Features

- **Black-box checks.** Send HTTP requests, crawl a site, and review security headers, cookie flags, forms and links.
- **Source review.** Read an application's source tree in read-only mode (`--source`), then confirm what the code suggests with a live request.
- **Verified findings.** Each finding has evidence, counterevidence, impact, remediation and a CVSS 3.1 base score.
- **Reports for people and tools.** `report.md`, `findings.sarif` (SARIF 2.1.0 for code-scanning platforms), `findings.json`, `run.json`, and an audit trail in `audit.jsonl`.
- **Two front ends.** An interactive terminal session, and an MCP server (`frugal-mcp`) for Claude Desktop and other MCP clients.
- **Headless mode for CI.** `--non-interactive` runs a task list without prompts and exits with code 3 when a finding reaches `--fail-on`.
- **Any model.** LM Studio, Ollama, llama.cpp, vLLM, OpenAI, OpenRouter or any other OpenAI-compatible endpoint. See [docs/providers.md](docs/providers.md).
- **Guard rails.** A scope check on every request, a Docker sandbox with no route to your host, commands run without a shell, an allowlist of two utilities (`curl` and `ping`), and an audit trail with credentials masked.
- **Ready for coding agents.** [AGENTS.md](AGENTS.md) and two [skills](skills/) explain how an agent can use the tool or work on it.

## Requirements

- Python 3.11 or newer.
- Docker: Docker Desktop on Windows and macOS, or Docker Engine on Linux and WSL 2.
- A model endpoint that speaks the OpenAI chat API, **or** an MCP client such as Claude Desktop. The MCP mode needs no API key.

## Quick start

1. **Start Docker.** The first audit pulls the sandbox image from GitHub Container Registry (`ghcr.io/yayuuun/frugal-sandbox`). To build it from this repository instead, run:

   ```bash
   docker build -t frugal-sandbox:latest docker/sandbox
   ```

   The `v0.1.0` binary predates the automatic pull. With that release, pull the image once and tag it with the local name:

   ```bash
   docker pull ghcr.io/yayuuun/frugal-sandbox:0.1.0
   docker tag ghcr.io/yayuuun/frugal-sandbox:0.1.0 frugal-sandbox:latest
   ```

2. **Install** from a clone of this repository:

   ```bash
   pip install ".[mcp]"
   ```

   The `mcp` extra is only needed for the MCP server. If you want to work on the code, follow [CONTRIBUTING.md](CONTRIBUTING.md) instead.

3. **Configure** the scope and the model. Copy the example file, then edit it:

   ```bash
   cp .env.example .env     # on Windows: copy .env.example .env
   ```

   Set `PENTEST_SCOPE` to the hosts you may test, and `LLM_BASE_URL` and `LLM_MODEL` to your model.

4. **Check** Docker, the sandbox and the model:

   ```bash
   frugal-audit doctor
   ```

5. **Audit.** The agent asks you to confirm each tool call. Type a task in plain language, and type `/exit` when you finish:

   ```bash
   frugal-audit run
   ```

   Each run writes a folder under `audit-runs/`.

## Continuous integration

Run a fixed task list without prompts. Calls are approved automatically, but the scope and the sandbox still apply:

```bash
frugal-audit run --non-interactive --authorized \
  --scope my-app.example.com \
  --task-file audit-tasks.txt \
  --fail-on high
```

`audit-tasks.txt` has one task per line, and lines that start with `#` are comments. Keep the scope narrow and the tasks specific. The exit codes are listed in [docs/reports.md](docs/reports.md#exit-codes-of-a-non-interactive-run).

## Source code review

Point the agent at the application's source tree to review it next to the running application:

```bash
frugal-audit run --scope my-app.example.com --source ./my-app
```

The source tree is read-only. The agent can list and read its files. It cannot write to them or run them.

## Use it from Claude Desktop without an API key

`frugal-mcp` exposes the audit tools over the Model Context Protocol. Claude Desktop, or another MCP client, does the reasoning with its own model, and the server still enforces the scope and the sandbox.

See [docs/mcp.md](docs/mcp.md) for the setup and the tool list, and [examples/claude-desktop/claude_desktop_config.json](examples/claude-desktop/claude_desktop_config.json) for a configuration example.

## Configuration

Settings come from environment variables, or from a `.env` file in the working directory. Command-line flags override them.

| Environment variable | Flag | Default | Purpose |
|---|---|---|---|
| `PENTEST_SCOPE` | `--scope` | none | Comma-separated hosts you may test. Bare host names or IPv4 addresses only. |
| `AUDIT_SOURCE` | `--source` | none | Source tree to review, read-only. |
| `AUDIT_RUNS_DIR` | `--runs-dir` | `audit-runs` | Folder where run folders are written. |
| `LLM_BASE_URL` | `--base-url` | `http://localhost:1234/v1` | OpenAI-compatible endpoint. |
| `LLM_MODEL` | `--model` | none | Model name, exactly as the endpoint lists it. |
| `LLM_API_KEY` | none | `not-needed` | Key for endpoints that require one. |
| `LLM_TEMPERATURE` | `--temperature` | model default | Sampling temperature. |
| `LLM_TIMEOUT` | none | `300` | Seconds to wait for each model reply. |
| `CONTEXT_BUDGET_CHARS` | none | `96000` | Conversation size before older turns are summarized. |
| `SANDBOX_IMAGE` | none | `frugal-sandbox:latest` | Image that runs the tools. |
| `SANDBOX_NETWORK` | none | `frugal-lab` | Network of the sandbox. The `host` network is refused. |

Other flags: `--run-name` (a label for the run folder), `--timeout` (minutes), `--max-tool-steps` (default 15), `--task`, `--task-file`, `--authorized`, `--non-interactive`, and `--fail-on` (`critical`, `high`, `medium`, `low`, `info` or `none`; default `high`).

| Command | Purpose |
|---|---|
| `frugal-audit run` | An interactive session, or a non-interactive run with `--non-interactive`. |
| `frugal-audit doctor` | Checks Docker, the sandbox network and the model endpoint. |
| `frugal-audit report <run-folder>` | Regenerates `report.md`, `findings.sarif` and `run.json` for a finished run. |
| `frugal-audit mcp` (also `frugal-mcp`) | Serves the audit tools over MCP. |

## Reports

Each run writes a folder such as `audit-runs/20261022-101500-my-app/`, with `report.md`, `findings.sarif`, `findings.json`, `run.json` and `audit.jsonl`. [docs/reports.md](docs/reports.md) describes the fields, the severity scale and how to upload the SARIF file.

Run folders can hold sensitive data from the systems you test. `audit-runs/` is in `.gitignore`. Review a report before you share it.

## Practice target

The repository includes a Docker Compose file for [OWASP Juice Shop](https://github.com/juice-shop/juice-shop), a deliberately vulnerable application. It joins the same isolated lab network as the sandbox:

```bash
docker compose -f examples/juice-shop/docker-compose.yml up -d
frugal-audit run --scope juice-shop
```

The target publishes no ports to your machine, so only the sandbox can reach it. Juice Shop is insecure by design. Never expose it to the internet.

## How it stays safe

- Every request is checked against the scope before it is sent. Redirects are not followed automatically.
- Requests run in a container with a read-only file system, no host mounts, all Linux capabilities dropped except the one `ping` needs, a memory limit and a process limit. The sandbox network is internal by default.
- Commands run as argument lists, never through a shell. Only `curl` and `ping` can run, and only against hosts in scope.
- In an interactive session you approve each call, unless you type `/accept_all on`. MCP clients approve calls through their own settings.
- The audit trail records each decision and its outcome. It never contains response bodies, and it masks credentials in headers, options and URLs.

The [threat model](docs/threat-model.md) lists the risks that remain, such as state-changing requests against in-scope systems and what a hosted model endpoint learns about the target.

## Documentation

- [Model providers](docs/providers.md)
- [MCP setup for Claude Desktop](docs/mcp.md)
- [Reports and findings](docs/reports.md)
- [Architecture](docs/architecture.md)
- [Threat model](docs/threat-model.md)
- [Changelog](CHANGELOG.md)

## Contributing and security

- [CONTRIBUTING.md](CONTRIBUTING.md) explains the development setup and the checks a change must pass.
- [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) sets the expectations for everyone who takes part.
- [SECURITY.md](SECURITY.md) explains how to report a vulnerability in this tool privately.

## Acknowledgements

The project layout takes ideas from [Strix](https://github.com/usestrix/strix), an Apache-2.0 licensed AI pentesting tool: agent guidance files, skills, a headless CI mode and a report folder per run. The code here is written from scratch, and no Strix code is copied.

## License

MIT. See [LICENSE](LICENSE).