A freshly installed Apache Kafka cluster accepts unauthenticated PLAINTEXT connections on every listener and applies no authorisation at all. The Apache Kafka project says so plainly in its own security model, and it treats an open cluster as a deployment choice rather than a defect. That leaves platform teams to assemble listener design, authentication, ACLs, encryption in transit and at rest, Kafka Connect hardening, JMX protection and patching themselves, across brokers, KRaft controllers, Connect workers, MirrorMaker 2 and Streams applications. This guide covers the whole platform from a data security angle: where the trust boundaries sit, which settings close them, how to roll changes out without an outage, and what to monitor. It is written for platform engineers, data engineers and security architects who run self-managed Kafka or need to judge a managed service. Credential lifecycle (SCRAM, OAuth, certificates and rotation) is covered in depth in the companion Kafka Credentials Security Guide, so this page only summarises it.
Key takeaways
- Security is opt-in at every layer. Listeners default to PLAINTEXT, there is no authoriser until you set
authorizer.class.name, the Connect REST API is unauthenticated on port 8083 and JMX is unauthenticated. Each must be secured separately. - Authentication without authorisation is full access. With no authoriser configured, every authenticated principal can do everything. Pair SASL or mTLS with
StandardAuthorizerand default deny. - Kafka does not encrypt data at rest. Log segments, indexes and snapshots are plain bytes. Disk encryption covers stolen media; only producer-side message encryption protects records from broker operators.
- Kafka Connect is the softest target. Its REST API has no per-connector authorisation, connector configs can override client settings by default, and plugins run arbitrary code in the worker JVM.
- Configuration is a code-execution surface. A chain of CVEs (CVE-2023-25194, CVE-2025-27818, CVE-2025-27819) turned JAAS settings into remote code execution, so AlterConfigs and connector creation are administrator-level rights.
The Kafka trust model and attack surface
Kafka's security model makes several explicit assumptions that shape every control decision. Anyone with shell access to a broker, controller or its disks can read every topic, forge any principal and rewrite ACLs. Any host that can authenticate on the inter-broker or controller listener is effectively part of the cluster. Any JAR on the classpath, and any pluggable class named in configuration (authorisers, serialisers, connectors, transforms, config providers), runs with the full privileges of the process. The project also states that the data plane (produce and consume), the Admin API and JMX each have separate authentication and authorisation stories, so securing one does not secure the others.
| Surface | Default exposure | Typical port or setting | Primary control |
|---|---|---|---|
| Client listeners (produce, consume, Admin API) | PLAINTEXT, no authorisation | 9092 by convention; listeners, advertised.listeners | SASL_SSL or SSL with mTLS, StandardAuthorizer, ACLs |
| Inter-broker listener | Same as client listener unless separated | inter.broker.listener.name | Dedicated internal listener, mTLS, firewalled from clients |
| KRaft controller listener | Whatever protocol is mapped | controller.listener.names | Never reachable from client networks; mTLS |
| Kafka Connect REST API | HTTP, unauthenticated, all connectors | 8083 by default; listeners, admin.listeners | Management network only, HTTPS, reverse proxy or REST extension authentication |
| JMX on brokers, clients, Connect, Streams | Unauthenticated | com.sun.management.jmxremote.* | Disable, bind to localhost with an exporter, or enable authentication and TLS |
| Broker disks and tiered storage | Plain bytes | log.dirs, remote storage | Volume encryption, message-level encryption, restricted host access |
| Configuration files | Keystore passwords and SASL secrets often inline | server.properties, client and connector configs | ConfigProvider references with allowed.paths, secrets manager |
For the threat side, the relevant MITRE ATT&CK techniques are T1190 Exploit Public-Facing Application (exposed listeners and Connect REST), T1078 Valid Accounts (stolen SCRAM passwords or client certificates), T1040 Network Sniffing and T1557 Adversary-in-the-Middle (PLAINTEXT or SASL_PLAINTEXT traffic), T1552.001 Credentials In Files (inline secrets in properties files), T1565 Data Manipulation (injected records on a writable topic) and T1485 Data Destruction (topic deletion by an over-privileged principal).
Listener and network architecture
Each broker listener has its own security protocol, chosen through listener.security.protocol.map. Getting the listener layout right is the foundation; every other control assumes it.
| Protocol | Authentication | Encryption | When to use |
|---|---|---|---|
| PLAINTEXT | None | None | Closed test environments only |
| SSL | Optional mTLS (ssl.client.auth=required) | TLS | Inter-broker and controller traffic; clients with a managed PKI |
| SASL_PLAINTEXT | SASL | None | Avoid: credentials and data cross the network in clear, and SCRAM replay (CVE-2024-56128) was only exploitable without TLS |
| SASL_SSL | SASL, optionally plus mTLS | TLS | Default choice for client-facing listeners |
- Separate internal and external listeners: put replication (
inter.broker.listener.name) and KRaft traffic (controller.listener.names) on a dedicated SSL or SASL_SSL listener that is firewalled off from clients, so a compromise of a client-facing listener cannot impersonate a broker. The project recommends never exposing the controller listener to client networks. - Treat advertised.listeners as security configuration: after the first metadata fetch, clients connect to whatever addresses the broker advertises. A wrong entry can push clients onto a PLAINTEXT listener or an address outside your controlled network path.
- Bind narrowly: bind external listeners only to interfaces that intended clients can reach, and restrict source ranges with security groups or network policy. See the Network Segmentation Guide.
- Cap connection abuse:
max.connectionsandmax.connections.per.ip(withmax.connections.per.ip.overrides) limit connection floods. Unauthenticated clients have caused broker out-of-memory conditions before (CVE-2022-34917), which is another reason to keep listeners off untrusted networks. - Apply quotas: client quotas on
producer_byte_rate,consumer_byte_rateandrequest_percentagestop one principal or a compromised client from starving the cluster.
Authentication: choosing mechanisms per listener
Kafka supports mTLS and five SASL mechanisms (GSSAPI, PLAIN, SCRAM-SHA-256, SCRAM-SHA-512 and OAUTHBEARER), enabled per listener through sasl.enabled.mechanisms. The project recommends mTLS for broker-to-broker and controller-to-broker traffic because it needs no shared password and rotates with the PKI. Decision points:
- Existing Kerberos estate: GSSAPI keeps credential management in the KDC.
- Central identity provider and workload identity: OAUTHBEARER with a configured JWKS endpoint and validator. The default implementation creates and validates unsecured JWTs and is for test only. Note CVE-2026-33557: in Kafka 4.1.0 to 4.1.1 the default validator accepted JWTs without checking signature, issuer or audience (fixed in 4.1.2 and 4.2.0).
- Self-contained clusters: SCRAM-SHA-512 over SASL_SSL, with credentials stored in cluster metadata.
- PLAIN: acceptable only inside SASL_SSL, and only with a callback handler (
sasl.server.callback.handler.class) that checks an external store rather than passwords in a JAAS file. - Frameworks that fan out (Spark, Flink, Connect): delegation tokens let tasks use a short-lived SCRAM credential that inherits the requester's principal and ACLs and expires on
delegation.token.expiry.time.ms.
Every application should have its own principal. Principal design, mapping rules, rotation runbooks and credential monitoring are in the Kafka Credentials Security Guide; the wider practice is in the Secrets Management Guide.
Authorisation with ACLs
Authentication produces a KafkaPrincipal; the authoriser decides what it may do. KRaft clusters ship org.apache.kafka.metadata.authorizer.StandardAuthorizer. An ACL is a tuple of principal, host, operation, resource pattern and permission. Resource types are Topic, Group, Cluster, TransactionalId, DelegationToken and User, and patterns are LITERAL or PREFIXED.
Defaults that decide your exposure
- No authoriser: all authenticated principals have full access. This is the most common gap in clusters that "have security turned on".
- Authoriser with no matching ACL: access is denied, except for principals in
super.users, which bypass ACLs entirely. Treat that list like a root password and keep it to broker and break-glass identities. - allow.everyone.if.no.acl.found=true: reverses default deny for resources with no ACLs. It is a migration aid and should not remain set once ACLs are in place.
- Host restrictions:
--allow-hostand--deny-hostaccept IP addresses only, not hostnames, so they are weak in dynamic container networks; rely on principals and network policy instead.
Least-privilege patterns
| Workload | Operations to grant | Resource pattern | Avoid |
|---|---|---|---|
| Producer | Write, Describe (and Create only if it must create topics); IdempotentWrite on Cluster or Write on TransactionalId where needed | PREFIXED on the team's topic namespace, e.g. payments. | Wildcard topic * |
| Consumer | Read, Describe on topics; Read on its consumer group | LITERAL group name; PREFIXED topics | Shared groups across applications |
| Kafka Connect worker | Read and Write on its internal config, offset and status topics; per-connector topic prefixes | PREFIXED per connector | One principal with cluster-wide Write |
| Platform automation | Create, Delete, AlterConfigs, DescribeConfigs on named resources | LITERAL or PREFIXED, Cluster only where unavoidable | Membership of super.users |
| Monitoring | Describe, DescribeConfigs | Cluster and topics | Read on data topics |
The kafka-acls.sh convenience options --producer and --consumer generate the basic grants, and --resource-pattern-type prefixed applies them to a namespace. Two points from the CVE history matter here. First, Alter and AlterConfigs on the Cluster resource are effectively code execution on older versions, because JAAS settings could load JNDI or LDAP login modules (CVE-2025-27819, CVE-2025-27818). Second, ACL tooling has had bugs during migrations: CVE-2024-27309 caused other ACLs on a resource, including DENY rules, to be ignored when an ACL was removed during a ZooKeeper to KRaft migration in 3.5.0 to 3.6.1. Verify effective access after any migration, not just the ACL list.
Encryption in transit and at rest
In transit
- Protocols: disable TLS below 1.2 with
ssl.enabled.protocolsand prefer TLS 1.3 where the JDK supports it. Restrictssl.cipher.suitesto your approved list. - Hostname verification: keep
ssl.endpoint.identification.algorithm=httpson clients (the default since Kafka 2.0). Setting it to empty to "fix" a certificate mismatch removes protection against an adversary in the middle. - Separate keystores: use distinct keystores for inter-broker and client-facing listeners so a leaked client-facing key cannot impersonate a broker.
- Rotation without restarts: keystores can be replaced through dynamic broker configuration with
kafka-configs.sh --entity-type brokers --alter. Track expiry; see the Certificate Expiry Outages and 47-Day TLS Certificates Guide. - Every client: Connect, MirrorMaker 2 and Streams consume the same
ssl.*andsasl.*client properties. A secure broker with a PLAINTEXT replication flow to a disaster recovery cluster is still a leak. - Cost: the project notes a performance cost for TLS that depends on CPU and JVM; load test before enforcing, rather than leaving a PLAINTEXT listener "for performance". See the mTLS Guide.
At rest
| Option | Protects against | Does not protect against | Trade-off |
|---|---|---|---|
| Filesystem or block-device encryption | Disk theft, misdirected backups and snapshots | Anyone with broker login or a super user principal | Transparent, low effort; baseline for every cluster |
| Message-level (producer-side) encryption with keys in a KMS | Broker operators, backups, tiered storage, replication targets | Compromised producer or consumer applications | Breaks broker-side processing of encrypted fields; key distribution to consumers |
| Tiered storage with an encrypting remote store | Exposure of offloaded segments in object storage | Local segments and broker access | Depends on the store's own key management |
Retention is part of data protection. Long retention.ms values and compacted topics that keep personal data indefinitely widen the blast radius of any read access; set retention per topic from data classification. Sensitive dynamic broker settings are encrypted in the metadata log with password.encoder.secret; rotating it needs password.encoder.old.secret and a rolling restart. See the Encryption Guide and the Data Security Guide.
Securing Kafka Connect, JMX and the wider ecosystem
- REST API exposure: anyone who reaches the Connect REST port can create, reconfigure, stop or delete any connector and read its configuration, and because plugins run arbitrary code, that can mean running anything the installed plugins allow. Bind it to a management network, use an
httpslistener (inter-worker forwarding uses the same channel), and setadmin.listenersto separate or disable the admin endpoints. - REST authentication: terminate mTLS or OIDC at a reverse proxy that is the only host allowed to reach the port, or register an extension through
rest.extension.classes. The bundledPropertyFileLoginModulestores cleartext credentials and is for test use only. - No per-connector isolation: REST authentication gates the whole API, not individual connectors. Do not grant REST access to anyone you would not trust as a cluster administrator; give distrusting teams their own Connect clusters.
- Client override policy:
connector.client.config.override.policydefaults toAll. The project recommendsAllowlistsince 4.2.0 (the default from 5.0), permitting only the keys you need. Class-loading overrides such assasl.jaas.configare a code-execution vector; this is the root of CVE-2023-25194. - System properties against JAAS abuse: on versions affected by the JNDI and LDAP issues, set
org.apache.kafka.disallowed.login.modules, and useorg.apache.kafka.sasl.oauthbearer.allowed.urlsto constrain OAUTHBEARER token and JWKS URLs (CVE-2025-27817 allowed file reads and SSRF through them; the allowed list defaults to empty from 4.0.0). - Secrets in connector configs: secrets placed inline are written to
config.storage.topicas ordinary records. Use ConfigProvider references so only${alias:fields}templates are stored, setallowed.pathson file providers (CVE-2024-31141 showed untrusted ConfigProvider use reading files and environment variables), and remember a REST caller who knows a template can usually retrieve its resolved value. - Plugins: install connectors, converters and transforms only from trusted sources and pin versions; control
plugin.pathlike a code deployment. See the Software Supply Chain Security Guide. - JMX: unauthenticated by default on brokers, clients, Connect and Streams. Disable remote JMX, or bind to localhost with a metrics exporter beside it, or enable
com.sun.management.jmxremote.authenticate=truewith TLS. - Container images: the project does not rebuild released Docker images, so base-layer CVEs accumulate. Rebuild or patch images for long-running deployments.
Where identity fits
Almost every Kafka principal is a non-human identity: producer and consumer services, Connect workers, MirrorMaker, stream processors and platform automation. The risks are the familiar NHI ones: shared principals that make ACLs meaningless, long-lived SCRAM passwords and client certificates copied into many property files, and super user entries added for convenience and never removed. Inventory principals against owners, give each workload its own identity, and prefer short-lived OAuth tokens or certificates issued by your workload identity platform. See the Non-Human Identity (NHI) Guide and the Database Credential and Access Security Guide for the equivalent problem in databases.
Rolling out security on a running cluster
Kafka supports adding security to a live cluster through rolling restarts, because listeners are independent. A safe order:
- Inventory: list listeners, advertised addresses, clients per listener (from connection metrics and network flows), Connect clusters, MirrorMaker flows, JMX ports and the current Kafka version against the project's CVE list.
- Patch first: move to a supported release that includes the JAAS, OAUTHBEARER and ConfigProvider fixes (3.9.1, 4.0.0 or later, and 4.1.2 or 4.2.0 or later if you use OAUTHBEARER on 4.1.x).
- Add secure listeners alongside existing ones: add SASL_SSL for clients and an SSL listener with mTLS for inter-broker and controller traffic, by rolling restart. Switch
inter.broker.listener.namein a second roll. - Enable the authoriser in transitional mode: set
authorizer.class.namewithallow.everyone.if.no.acl.found=true, setkafka.authorizer.loggerto INFO, and watch denials. - Write ACLs per principal: start with the producer and consumer patterns above. Pilot one team's namespace, then expand.
- Migrate clients: move applications to the secure listener in waves, starting with non-critical consumers. Track remaining PLAINTEXT connections per listener.
- Close the gaps: remove
allow.everyone.if.no.acl.found, remove PLAINTEXT listeners, cutsuper.usersto the minimum, lock down Connect REST and JMX. - Rollback plan: keep the previous listener configuration ready to re-add by rolling restart, and keep the transitional flag available for one release cycle. Rolling back ACLs means re-applying the exported ACL set, so export it (
kafka-acls.sh --list) before each change.
Small versus large estates: a single cluster with a few services can move straight to SCRAM over SASL_SSL with prefixed ACLs managed in version control. Large estates with many teams benefit from OAUTHBEARER tied to the identity provider, ACLs generated from a topic catalogue with named owners, and a separate Connect cluster per trust domain. Managed Kafka services handle broker patching and often disk encryption, but listener exposure, ACL design, Connect and client configuration remain yours.
Detection and measurement
| Signal | Source | What it can indicate |
|---|---|---|
| Denied operations | kafka.authorizer.logger at INFO | Misconfigured ACLs, or a principal probing beyond its rights |
| All allowed operations | kafka.authorizer.logger at DEBUG (high volume) | Forensic timeline of who read or wrote what |
| Failed authentications | Selector metrics failed-authentication-rate and failed-authentication-total | Password spraying (ATT&CK T1110), expired certificates, misconfigured clients |
| ACL and config changes | Admin API calls in the request log (kafka.request.logger), change tickets | Unauthorised privilege changes, JAAS or ConfigProvider abuse |
| Connector creation and update | Connect REST access logs at the proxy | Connector configs pointing at unexpected hosts or login modules |
| Unexpected topic reads | New consumer groups on sensitive topics | Data exfiltration using valid credentials (ATT&CK T1078) |
Ship authoriser and request logs off-broker to append-only storage: Kafka has no built-in tamper-evident audit trail. Do not run client NetworkClient logging at DEBUG in production; CVE-2026-33558 showed that this logs full requests including SASL and delegation token messages. Useful KPIs:
- Listener coverage: percentage of client connections on SASL_SSL or SSL (target 100%).
- Authorisation coverage: clusters with an authoriser and without
allow.everyone.if.no.acl.found. - Wildcard exposure: number of ACLs on topic
*or principalUser:*. - Super users: count per cluster, with a named owner for each.
- Patch latency: days from a Kafka CVE publication to deployment of the fixed version.
- Connect exposure: Connect clusters with authenticated HTTPS REST and an Allowlist override policy.
Framework mapping
| Kafka control | NIST SP 800-53 Rev. 5 | NIST CSF 2.0 | ISO/IEC 27001:2022 Annex A | CIS Controls v8.1 |
|---|---|---|---|---|
| Per-workload principals, SASL or mTLS | IA-3, IA-5 | PR.AA-01 | A.8.5 | Control 6 |
| StandardAuthorizer, least-privilege ACLs, small super.users | AC-3, AC-6 | PR.AA-05 | A.5.15 | Control 6 |
| TLS on all listeners and client flows | SC-8 | PR.DS-02 | A.8.24 | Control 3 |
| Disk and message-level encryption, retention | SC-28 | PR.DS-01 | A.8.24 | Control 3 |
| Listener separation, Connect REST and JMX off client networks | SC-7, CM-7 | PR.PS-01 | A.8.20 | Controls 4 and 12 |
| Hardened configuration, override Allowlist | CM-6 | PR.PS-01 | A.8.9 | Control 4 |
| Authoriser and request logging, monitoring | AU-2, AU-12, SI-4 | DE.CM-01 | A.8.15 | Control 8 |
Common failure patterns
- "We turned on SASL": authentication enabled with no authoriser, so every authenticated client, including a stolen test credential, has full cluster access.
- Transitional flag left on:
allow.everyone.if.no.acl.found=truestays in production for years, so any new topic without ACLs is open to all. - Connect REST on the application network: an unauthenticated port 8083 lets anyone add a connector that reads topics, writes to external systems or, with class-loading overrides, runs code in the worker.
- Secrets in the config topic: database and cloud credentials inlined in connector configs end up in
config.storage.topic, readable by any principal with Read on it and present in every backup. - Disaster recovery in clear: the primary cluster is locked down, but MirrorMaker 2 replicates to a second cluster over PLAINTEXT, or the target cluster has no authoriser.
- Unencrypted disks and broad host access: because Kafka writes plain bytes, a snapshot of a broker volume shared for troubleshooting exposes every retained record.
Practitioner checklist
- Remove PLAINTEXT and SASL_PLAINTEXT listeners from every non-test cluster, and confirm
advertised.listenersonly advertises secure listeners. - Put inter-broker and controller traffic on a dedicated mTLS listener that clients cannot reach.
- Configure
StandardAuthorizer, removeallow.everyone.if.no.acl.foundand keepsuper.usersto brokers and break-glass identities. - Grant prefixed, per-principal ACLs from a topic catalogue with owners; export and version the ACL set.
- Enforce TLS 1.2 or higher with hostname verification on every client, including Connect, MirrorMaker 2 and Streams.
- Encrypt broker volumes; use producer-side encryption with KMS-managed keys for regulated fields; set retention per topic from data classification.
- Restrict Connect REST to a management network with HTTPS and authentication, set
connector.client.config.override.policy=Allowlist, and move connector secrets into ConfigProviders withallowed.paths. - Disable or authenticate JMX on all Kafka processes.
- Track Kafka releases against the project CVE list and rebuild container images regularly.
- Ship authoriser and request logs off-broker and alert on authentication failures, ACL changes and new consumer groups on sensitive topics.
Standards and references
- Apache Kafka: Security documentation and security model
- Apache Kafka: Kafka Connect security model
- Apache Kafka: CVE list
- NIST: SP 800-53 Rev. 5
- NIST: Cybersecurity Framework 2.0
- MITRE ATT&CK: Exploit Public-Facing Application
- MITRE ATT&CK: Valid Accounts
Related NHI Mgmt Group resources: Kafka Credentials Security Guide · Redis Security Guide · Database Security Guide · mTLS Guide · Data Security Guide