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.1.tar.gz (27.8 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.1-py3-none-any.whl (29.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: ciamitm-0.2.1.tar.gz
  • Upload date:
  • Size: 27.8 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.1.tar.gz
Algorithm Hash digest
SHA256 9990b1ba28420833bdc12cf7f87458aa7b2be45be14a5481f17823f312564160
MD5 107825d57ed8f9c6729ae23952a7fba7
BLAKE2b-256 5d5d1536b348fa9e276a71c90b778da480c819d55ce5c6fcd387e5fbc951549c

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ciamitm-0.2.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f015fa18adbddaa0006c2e35113d636bc9e89edb9fd1eba123281397b9bf63d6
MD5 d3ea23dd75cd58d8f3b9ac9905bb6388
BLAKE2b-256 4de3dad423610e279d2edc51076bae3fafcbd47e570b7c9f7ebfbb777d9df39b

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