Metadata-Version: 2.4
Name: ciamitm
Version: 0.2.0
Summary: Cyber Injection Assistant: a local HTTP(S) MITM testing proxy
Requires-Python: >=3.13
Description-Content-Type: text/markdown
Requires-Dist: mitmproxy>=12.2.3
Requires-Dist: aiosqlite>=0.21.0
Requires-Dist: sqlalchemy>=2.0.41
Requires-Dist: mesop>=1.3.3
Requires-Dist: pandas>=3.0.5
Requires-Dist: pydantic>=2.13.4

# Cyber Injection Assistant (CIA)

Cyber Injection Assistant (CIA) is a local HTTP(S) MITM testing proxy built on mitmproxy. It records traffic to SQLite, runs external Python rules against requests, can generate blocking responses, and includes a small Mesop web UI for viewing and filtering captured flows.

Use it only for traffic you own or are authorized to inspect.

## Features

- HTTP(S) proxy powered by mitmproxy.
- Async SQLAlchemy + SQLite traffic storage.
- External rule files with no dependency on CIA internals.
- Runtime rule enable/disable and global bypass switch.
- Web UI for Wireshark-style traffic browsing, filtering, request/response details, CA links, and clearing records.
- Local CA generation for HTTPS interception.
- Binary payload download from captured request/response bodies.

## Requirements

- Python 3.13 or newer.
- `uv` for dependency management.
- A browser or HTTP client configured to use the local proxy.

Install dependencies:

```powershell
uv sync
```

Install CIA as a command:

```powershell
uv tool install .
```

After installation, verify the command is available:

```powershell
cia --help
```

During development you can run the command without installing it globally:

```powershell
uv run cia --help
```

## Quick Start

Start CIA with the default config:

```powershell
cia
```

Or use an explicit config file:

```powershell
cia -f userdata/config.toml
```

On startup CIA prints the rules directory it scanned and each discovered rule:

```text
[cia] scanning rules: C:\repos\cia\userdata\rules
[cia] rules discovered: 1
[cia] - example [active] block www.baidu.com (C:\repos\cia\userdata\rules\example.py)
```

Default endpoints:

- Proxy: `127.0.0.1:2080`
- Web UI: `http://127.0.0.1:5280/`
- CA import page: `http://127.0.0.1:5280/_cia/install-ca`

Configure your browser proxy as an HTTP proxy pointing to `127.0.0.1:2080`. HTTPS websites are handled through HTTP CONNECT; do not configure the browser to use an HTTPS/SSL proxy endpoint.

## Configuration

The default config is [userdata/config.toml](userdata/config.toml):

```toml
[userdata]
rules = "./rules"
net_logs = "./data" # also supports ::memory::

[proxy]
protocol = "http"
ca = "./ca.pem"
host = "127.0.0.1"
port = 2080

[web]
host = "0.0.0.0"
port = 5280

[rules]
# rule_name = true
```

Paths are resolved relative to the config file.

`userdata.net_logs` can be a directory, a SQLite file path, or `::memory::`. When it is a directory, CIA stores logs in `net_logs.sqlite3` inside that directory.

Rules are enabled by default. Add entries under `[rules]` to control initial activation:

```toml
[rules]
example = true
some_other_rule = false
```

## HTTPS and CA Trust

CIA generates a local root CA at the path configured by `proxy.ca`. The web UI Settings tab shows the CA path and SHA-256 fingerprint.

Useful CA routes:

- `/_cia/install-ca`: browser-friendly import instructions.
- `/_cia/ca.crt`: DER certificate with `.crt` filename.
- `/_cia/ca.cer`: DER certificate with `.cer` filename.
- `/_cia/ca.pem`: PEM certificate.
- `/ca.pem`: PEM certificate shortcut.

Chrome and Edge can usually trust the CA from the Windows Current User Root store. Use the Settings button in CIA to install it, or import the `.crt` manually.

Firefox normally uses its own certificate store. Import the CA from Firefox settings, or enable `security.enterprise_roots.enabled` in `about:config` so Firefox trusts the Windows Current User Root store.

If you regenerated the CA, delete the old `CIA Local Root CA` entry from your browser first, then import the new one and confirm the fingerprint.

## Rule Files

Rules are external Python files loaded from the configured `userdata.rules` directory.
Rule files can import the public request/response models from `cia.typing`. Each rule module must export:

```python
from cia.typing import Request, Response

rule_name = "block-example"
rule_description = "optional description"


def handle(request: Request) -> Response | None:
    if request.host == "example.com":
        return Response(
            status_code=403,
            content_type="text/plain",
            body="blocked",
        )
    return None
```

`rule_name` must be a non-empty string. `rule_description` is optional and defaults to `None`.
`handle` is required and can be synchronous or asynchronous.

The `handle` function receives one `Request` object with:

- `host`: request host.
- `port`: request port.
- `path`: request path and query string.
- `request_body`: raw request body as `bytes`.
- `header`: request headers as `dict[str, list[str]]`.

Return `None` to allow the request to continue. Return a `Response` to block the request and generate that response.

`Response` fields:

- `status_code`: HTTP status code. Defaults to `200`.
- `content_type`: response content type. Defaults to `application/json`.
- `headers`: extra response headers.
- `body`: response payload. `str`, `bytes`, and JSON-serializable values are supported.

Example with an asynchronous rule:

```python
from cia.typing import Request, Response

rule_name = "block-by-host"


async def handle(request: Request) -> Response | None:
    if request.host.endswith("example.test"):
        return Response(status_code=403, body="blocked")
    return None
```

CIA validates each rule at startup. A rule file fails to load if `rule_name` is missing or empty, `rule_description` is not `str` or `None`, `handle` is missing, or `handle` does not accept exactly one `Request` argument.

## Web UI

The web UI shows captured traffic in a table with time, method, host, path, status, and matched rule. Selecting a row opens a right-side details panel with `REQUEST` and `RESPONSE` tabs.

The body viewer:

- Pretty-prints JSON with two-space indentation.
- Shows text bodies directly.
- Shows a `Download binary data` link for binary payloads.

The Rules tab lets you enable or disable individual rules and toggle `Bypass all traffics`, which skips all rule handling without unloading rules.

The Settings tab shows proxy and CA information, lets you install the CA, controls auto refresh, and includes `Clear records` to delete all captured traffic logs.

## Display Filters

The traffic table supports simple display filters.

Examples:

```text
host == 'example.com'
method == GET and status_code == 403
not is_blocked == true
url =~ 'baidu|example'
matches[0].rule_name == example
```

Supported operators:

- `==`: exact string comparison.
- `!=`: string inequality.
- `=~`: regular expression search.
- `and`, `or`, `not`, and parentheses.
- Dotted paths and list indexes such as `matches[0].rule_name`.

## Development Notes

Run a quick import check:

```powershell
uv run cia --help
```

The proxy and web UI run together from the `cia` command. Stop the process with `Ctrl+C`.
