Community-maintained open-source project. Not affiliated with, endorsed by, or sponsored by Traefik Labs, the Caddy project, HAProxy Technologies, or the HAProxy project. Product and trademark names (Traefik, Caddy, HAProxy) belong to their owners. Source is auditable under the MIT license.
Report privately via a GitHub Security Advisory on github.com/AIops-tools/Proxy-AIops or email zhouwei008@gmail.com. Please do not open public issues for security reports.
- Per-target secrets — the HAProxy Data Plane API password (paired with the
usernamefor HTTP Basic auth) or an optional Basic-auth credential in front of Traefik/Caddy — live encrypted in~/.proxy-aiops/secrets.enc(Fernet/AES-128 + scrypt-derived key; chmod 600), never inconfig.yamland never in source. The master password is never stored — only a per-store random salt and the ciphertext are on disk. - Traefik and Caddy commonly run unauthenticated on localhost: for those platforms the secret is optional — no store entry simply means no auth header is sent. HAProxy's credential is required.
- A legacy plaintext env var
PROXY_<TARGET_NAME_UPPER>_SECRETis still honoured as a fallback with a deprecation warning (migrate withproxy-aiops secret migrate). - The secret is held only in memory and never logged or echoed. It is presented as HTTP Basic auth at request time; the config file holds only platform, base_url, username, and TLS settings.
Every MCP tool runs through the bundled @governed_tool harness
(proxy_aiops.governance):
- Audit — every call logged to a local SQLite DB under
~/.proxy-aiops/(relocatable viaPROXY_AIOPS_HOME), agent-attributed, secret-redacted. - Token/runaway budget — hard ceilings (
PROXY_MAX_TOOL_CALLS/PROXY_MAX_TOOL_SECONDS) plus an on-by-default guard that trips a tight poll/retry loop, preventing unbounded API consumption. - Risk tier — a descriptive label on each audit row derived from
risk_level; it gates nothing.PROXY_AUDIT_APPROVED_BY/PROXY_AUDIT_RATIONALEare optional annotations recorded on the row, never required and never blocking. - Undo-token recording — reversible writes capture the BEFORE state (via a real GET) and record an inverse descriptor (config subtree restore, prior admin state / weight) whose params match the target tool's signature, so it replays as-is.
The caddy config writes and haproxy runtime-server writes are the only
state-changing tools. delete_config_path and load_config (full config
replace) are risk_level=high, accept a dry_run preview, and require double
confirmation at the CLI. set_config_value, set_server_state and
set_server_weight are risk_level=medium; all capture before-state and
record an undo token. Traefik targets accept no writes at all — the support
matrix raises a teaching error pointing at its providers.
Every value substituted into a URL path is percent-encoded centrally in
Platform.path(); Caddy config paths are additionally encoded per segment with
dot-segments (. / ..) rejected outright, so an agent-supplied path can
never escape the /config/ tree.
verify_ssl defaults to true; disable only for self-signed lab certificates.
The certificate expiry probe intentionally skips chain verification (it reads
expiry off whatever leaf is served, including an expired one) — it never trusts
or transmits anything over that connection.
All proxy-returned text (router names, upstream addresses, config values,
check statuses) is passed through a sanitize() truncate + control-character
strip before reaching the agent.
No webhooks, no telemetry. Outbound calls are limited to the configured Traefik / Caddy / HAProxy API endpoints, plus — only when an operator invokes the cert sweep with probing — a bounded TLS handshake to the inventoried domains (max 25, 5s timeout each). No post-install scripts or background services.
uvx bandit -r proxy_aiops/ mcp_server/
uv run ruff check .The latest released version receives security fixes. This is a preview (0.x); pin a version in production.