kproxy is a private project. This document records the project's security
posture, the threat model the implementation assumes, and how to report a
vulnerability.
Do not open a public issue or push a commit that demonstrates the vulnerability. Instead, contact the repository owner directly via private channel (email or DM) with:
- a description of the issue,
- reproduction steps,
- the commit hash you reproduced against,
- the impact you believe it has.
You will receive an acknowledgement and a remediation plan.
| Branch | Supported |
|---|---|
main |
yes |
| any other | no |
kproxy is intended to run inside a trusted network, in front of an
Apache Kafka cluster. The threat model assumes:
| Asset / threat | Mitigation |
|---|---|
| Untrusted client connections on the listener | Bounded -conn-limit, bounded frame size (frame.MaxFrameSize), per-iteration read deadline (-idle). |
| Malformed Kafka frames | internal/frame enforces length bounds; internal/kwire decoder returns truncated input and the conn is closed. |
| Memory exhaustion via never-replied requests | Tracker.PendingMaxAge evicts stale entries (default 5 min); MaxInflight caps tracker size. |
| Unbounded planner queue | -planner-queue caps work in flight; full queue triggers passthrough fallback, never blocks the hot path. |
| Pprof / metrics exposed publicly | Admin server defaults to 127.0.0.1:9099. Bind to public addresses only behind a trusted LB. |
Side-channel kclient to broker |
One outbound TCP conn; dial-timeout bounds connect; failure degrades to passthrough, never crashes proxy. |
| Sensitive data in logs | The proxy logs only metadata (api key, version, conn counts). It never logs payload bytes. (Hex-dumping is gated behind decode-error paths only.) |
- TLS termination — kproxy currently speaks PLAINTEXT Kafka only. TLS must be terminated above the proxy (service mesh, NLB, etc.).
- SASL authentication — kproxy does not authenticate the client to the broker; it forwards SASL frames as opaque bytes if attempted.
- Multi-tenant authorisation — broker ACLs still apply; kproxy does not perform AuthZ.
- Denial-of-service from the broker side — a malicious broker is out of scope.
| Surface | Default |
|---|---|
-listen |
:9092 (operator must override) |
-admin |
127.0.0.1:9099 (loopback only) |
-conn-limit |
4096 |
-idle |
5m per-iteration read deadline |
-plan-timeout |
2s |
-drain-timeout |
30s |
-subscription-cap |
100000 (across all groups) |
| Pending max-age | 5m |
If you must expose kproxy to traffic from outside the trusted network:
- Terminate TLS in front of the proxy. Pin client certificates if possible.
- Keep
-adminbound to loopback (127.0.0.1:...) and reach it via SSH port-forward or a sidecar sidecar exporter — never exposepprofto the public internet. - Set
-conn-limitto a value matching your fleet's expected fan-in. - Run kproxy as a non-root user in a hardened container image
(e.g.
gcr.io/distroless/static).
The proxy binary (cmd/kproxy) has zero non-stdlib runtime dependencies.
Test dependencies are limited to:
github.com/twmb/franz-go(used only byexample/test rigs, not by the proxy).
govulncheck ./... runs in CI on every PR and must pass before merge.
- Reproducible builds: pin Go version in
go.modand.github/workflows/. - Container images (when published) should carry SBOM via
syftand be signed viacosign keylessagainst the workflow OIDC identity.
kproxy performs no cryptography today. It does not generate keys,
sign messages, or encrypt traffic. This is by design — TLS belongs above
the proxy.
If a future change introduces TLS termination or SASL pass-through, this document and the threat model must be updated before the change is merged.