Security
KafkaMCP is designed to be the secure boundary between AI agents and your Kafka infrastructure. This page covers the security model, threat mitigations, and best practices.
Security Model
KafkaMCP implements defense-in-depth with multiple layers:
flowchart LR
Agent -->|Credential| AuthN[Agent Identity\nstatic / OIDC / mTLS]
AuthN -->|Policy Check| AuthZ[Authorization\ndefault-deny]
AuthZ -->|Approval Gate| AP[Signed Approval / Decision\nGuarded packs]
AP -->|Budget Check| RL[Rate Limiting]
RL -->|Execute| Kafka[Kafka Operation]
Kafka -->|Record| Audit[Audit Log\nsigned chain]
Agent Identity
KafkaMCP supports four identity providers, selected by policies.identity.provider:
| Provider | Credential | Suitable for |
|---|---|---|
none (default) | X-Agent-ID / X-Client-ID header | stdio transport, local dev |
static | Authorization: Bearer <token> against an inline token table | Simple multi-agent deployments |
oidc | JWT bearer token verified against an OIDC issuer's JWKS | Enterprise / SSO environments |
mtls | TLS client certificate (SPIFFE URI SAN → URI SAN → Subject CN) | Service-mesh / zero-trust deployments |
Network transport enforcement: sse and streamable-http transports refuse to start without a cryptographic identity provider (static, oidc, or mtls) and policies.default_deny: true. The X-Agent-ID header fallback is rejected by default for all cryptographic providers — an attacker cannot bypass verification by omitting their credential. Use server.dangerously_allow_unauthenticated_network: true only for local development.
Static provider tokens are converted to SHA-256 fingerprints at startup; raw tokens are not retained, and verification scans all configured fingerprints with constant-time comparison.
Authorization (Policy Engine)
The YAML policy engine provides fine-grained access control:
- Default-deny mode — when
policies.default_deny: true, all access is blocked unless an explicit rule allows it - Glob pattern matching — topic rules use patterns like
orders.*,*.dlq,payments-* - Per-resource permissions — topics (
read,write,create,delete,admin), consumer groups (describe,reset), schemas (read) - Auth-filtered results — list operations only return resources the agent is authorized to see
Approval Grants and Decisions (guarded packs)
ops-write and governance are rejected on stdio. The config validator
enforces a complete secure posture at startup:
| Requirement | Value |
|---|---|
| Transport | sse or streamable-http (not stdio) |
| Identity provider | static, oidc, or mtls |
| Header fallback | disabled (allow_header_fallback: false) |
| Authorization | default_deny: true |
| Signing key | KAFKAMCP_APPROVAL_SIGNING_KEY ≥32 bytes |
| Self-approval | false (two-person rule, default) |
Every mutating or destructive action then requires a short-lived, single-use approval grant before it executes:
- Request — agent calls
kafka_approvalwithaction=request, specifying the target tool, cluster, resource, and arguments. KafkaMCP server-digests the normalized arguments intoargs_digest. - Policy simulation — call
kafka_governance_decisionwithaction=simulateto preview whether the grant would be authorized, including blast-radius and recovery guidance, without side effects. - Approve — a different identity (two-person rule;
allow_self_approval: falseby default) callskafka_approvalwithaction=approve. - Use — the original agent uses the approval token when calling the mutating tool. The token is consumed on first use.
- Audit — every transition (request → approve → use / expire / revoke) is signed with
KAFKAMCP_APPROVAL_SIGNING_KEYand recorded. Useaction=verifyto validate a grant's decision chain andaction=exportto export records.
Rate Limiting
Per-agent token bucket rate limiting prevents:
- Runaway autonomous agent loops
- Aggressive polling that overloads brokers
- High-cost search or aggregation bursts
- Accidental fan-out across many topics
Configure via policies.agents[].rate_limit.requests_per_minute.
Audit Logging
Every tool call and resource read is recorded with:
- Timestamp, agent ID, tool/resource name
- Input parameters (with sensitive values redacted)
- Cluster name, result status, latency
- Message count and error details
Audit entries are kept in memory and optionally written to a JSONL file for durable storage.
Transport Security
TLS
KafkaMCP applies transport-specific TLS minimums:
- The inbound MCP HTTPS server requires TLS 1.3.
- Kafka broker connections (
security_protocol: SSLorSASL_SSL) default to TLS 1.2 for provider compatibility and can be raised to TLS 1.3 withtls_min_version. - Kafka Connect REST calls follow the same TLS 1.2 default and support an
explicit TLS 1.3 minimum through
connect_tls.min_version. - Schema Registry HTTPS uses Go's secure TLS defaults.
SASL Authentication
Supported SASL mechanisms for Kafka broker authentication:
PLAINSCRAM-SHA-256SCRAM-SHA-512
KafkaMCP logs a warning when SASL PLAIN is used without TLS. Always use SASL_SSL in production.
Schema Registry Credentials
Schema Registry connections support basic authentication. KafkaMCP warns when credentials are sent over non-HTTPS connections.
Data Protection
PII Redaction (Data Masking)
KafkaMCP supports policy-driven field-level masking before messages reach agents:
- Built-in detectors — email, SSN, credit card, phone number
- NER detection — lightweight named entity recognition for PII
- Custom regex — define your own patterns
- Per-agent rules — apply different masking policies to different agents
- JSON path patterns — target specific fields (
$.user.email,**email**)
masking:
enabled: true
rules:
- name: redact-emails
type: email
field_path: "**email**"
- name: custom-api-key
type: regex
pattern: "API_KEY_\\w+"
replace: "[REDACTED_KEY]"
agents: ["restricted-agent"]
Sensitive Data Redaction
KafkaMCP automatically redacts sensitive information in:
- Audit logs — passwords, tokens, and credentials are never logged
- Connector configs — Kafka Connect connector configurations have sensitive fields masked
- Error messages — stack traces and error details do not leak credentials
Input Validation
KafkaMCP validates all inputs before executing operations:
| Validation | Purpose |
|---|---|
| Max message size | Prevents oversized produce payloads (default: 1 MB) |
| String length limits | Prevents injection via overly long parameters |
| Cluster name validation | Only configured cluster names are accepted |
| Dangerous config keys | Blocks modification of critical topic configs (min.insync.replicas, etc.) |
| Consume timeout capping | Prevents unbounded consumer reads |
| Window bounds clamping | Limits aggregate and join window sizes |
| Join limit clamping | Caps the number of join results |
Concurrency Protection
- Semaphore — limits concurrent expensive operations (consume, produce, describe) to protect broker connections
- HTTP response body limit — 10 MB cap on Kafka Connect REST API responses
- Cryptographic random IDs — subscriber group IDs use
crypto/randto prevent collisions
HTTP Security
When running with SSE or streamable-http transport, KafkaMCP applies security headers middleware:
X-Content-Type-Options: nosniffX-Frame-Options: DENYStrict-Transport-Security(when TLS is enabled)
The metrics endpoint defaults to 127.0.0.1. Container deployments may set
server.metrics_host: 0.0.0.0, but must restrict the metrics port with
firewall or NetworkPolicy rules.
Best Practices
Production Checklist
- Use a cryptographic identity provider — configure
policies.identity.provider: static,oidc, ormtls(required for network transports) - Enable default-deny — set
policies.default_deny: true - Define agent policies — give each agent only the permissions it needs
- Set
KAFKAMCP_APPROVAL_SIGNING_KEY— required (≥32 bytes) forops-writeorgovernance; previous keys can be configured during rotation - Keep guarded deployments single-active —
ops-write,governance, and SQLite must not run on multiple active replicas - Keep
allow_self_approval: false— enforce two-person approval for write operations (default) - Enable audit logging — set
audit.enabled: truewith alog_filefor durability - Use TLS everywhere — configure
security_protocol: SASL_SSLfor Kafka, HTTPS for Schema Registry - Set rate limits — configure
requests_per_minutefor every agent - Enable data masking — mask PII fields before they reach agents
- Use environment variables — keep credentials out of config files with
${VAR}expansion - Review audit logs — regularly inspect what agents are doing
Least Privilege Example
policies:
default_deny: true
agents:
- id: incident-agent
topics:
- pattern: "*.dlq"
permissions: [read]
- pattern: "monitoring.*"
permissions: [read]
consumer_groups:
permissions: [describe]
schemas:
permissions: [read]
rate_limit:
requests_per_minute: 60
This agent can only read DLQ and monitoring topics, describe consumer groups, and read schemas — nothing else.
Reporting Vulnerabilities
If you discover a security vulnerability, please report it responsibly:
- Do not open a public GitHub issue
- Use GitHub Private Vulnerability Reporting — this is the only supported reporting channel
- Include steps to reproduce and potential impact
- Allow reasonable time for a fix before public disclosure
See SECURITY.md for full details.