Skip to main content

Cyber Injection Assistant: a local HTTP(S) MITM testing proxy

Project description

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:

uv sync

Install CIA as a command:

uv tool install .

After installation, verify the command is available:

cia --help

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

uv run cia --help

Quick Start

Start CIA with the default config:

cia

Or use an explicit config file:

cia -f userdata/config.toml

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

[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]
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:

[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:

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:

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:

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:

uv run cia --help

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ciamitm-0.2.0.tar.gz (27.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ciamitm-0.2.0-py3-none-any.whl (29.9 kB view details)

Uploaded Python 3

File details

Details for the file ciamitm-0.2.0.tar.gz.

File metadata

  • Download URL: ciamitm-0.2.0.tar.gz
  • Upload date:
  • Size: 27.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for ciamitm-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5fdd2ec142817b49cec1dca5bd2d3fc43dfd0f5037cbb7b5ff06cd355e7cad3c
MD5 210c82e2e4445c4556369cfeab8961ff
BLAKE2b-256 108270aff67cd1440598e1857c84738c46930e934c9e09bbb8c907dad04b6d4f

See more details on using hashes here.

File details

Details for the file ciamitm-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: ciamitm-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 29.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for ciamitm-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7b4c22bcea19311265828ab86523631cffb528e3c40fe479f58d992a49d8b014
MD5 37e0cab381aeea2ebc83934586a489ec
BLAKE2b-256 44801cdb2782d04e7788a2ae11b7d379af98b3efdb7fd42f69c64d628c7653c3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page