Your app is logging emails, OTPs, and credit cards.
logcloak intercepts them before they hit kubectl logs,
/var/log/containers/, or anywhere else.
No code changes. Just install and forget.
The problem
Most teams lock down their database with encrypted connections, strict RBAC, and audit logging —
then ship the same plaintext data out through every log pipeline they operate.
A developer adds one debug line: log.info("order for {}", user.email).
That line ends up in Datadog, Elasticsearch, an S3 bucket, your SIEM, and six terminals
belonging to people who were only supposed to see latency metrics. Nobody notices.
This is the default state of most Kubernetes deployments.
True — and that is a separate control. kubectl exec requires explicit RBAC that is
typically restricted, audited, and often disabled in production.
kubectl logs is handed out far more broadly — to developers, support teams,
CI pipelines, and log agents.
logcloak defends the log surface. RBAC defends exec. Use both.
kubectl logs in a developer’s terminal | ✓ stopped |
/var/log/containers/ on the node | ✓ stopped |
| Log shippers (Fluent Bit, Fluentd, Promtail) | ✓ stopped |
| Third-party platforms (Datadog, Splunk, Elastic) | ✓ stopped |
| S3 / GCS log archives | ✓ stopped |
| CI/CD pipelines that capture stdout | ✓ stopped |
kubectl exec into a running container | out of scope — use RBAC |
| Application memory / heap dumps | out of scope |
How it works
The webhook injects a sidecar that reads from an in-memory pipe. Your app writes normally. Masking happens before containerd sees a single byte.
Nothing changes in your app. It writes logs exactly as before. The webhook has already redirected its file descriptor to a named pipe.
The sidecar reads from the FIFO, applies your regex rules in microseconds, and writes clean output to its own stdout. Raw data never leaves the pipe.
kubectl logs and /var/log/containers/ only ever see the sidecar's output. The app container's stdout is effectively silent.
If masking fails for any reason (timeout, panic, pattern error), logcloak drops the line and writes a [LOGCLOAK-DROP] sentinel instead. The raw line never passes through. You can alert on the sentinel in your log aggregator.
Writing to a FIFO is identical to writing to any fd. Your app doesn't wait for masking. It doesn't even know logcloak exists.
Rules system
Platform team sets the baseline. Developers extend per service. Annotations can add rules — they can never remove them.
| Annotation / Resource | Who uses it | What it does |
|---|---|---|
MaskingPolicy CRD |
Platform / security team | Applies to all matching pods in a namespace. The source of truth for company-wide PII rules. Developers cannot override or remove these. |
logcloak.io/patterns |
Developer | Enable built-in patterns per pod: logcloak.io/patterns: "uuid,iban" |
logcloak.io/regex-<name> |
Developer | Add a custom RE2 regex per pod: logcloak.io/regex-order-id: "ORD-[0-9]{8}" |
logcloak.io/skip: "true" |
Developer | Opt this pod out of injection entirely. Useful for debug pods or batch jobs where masking is unwanted. |
logcloak.io/exclude-containers |
Developer | Comma-separated list of sidecar containers to leave unwrapped. For postgres sidecars, monitoring agents, etc. Service mesh proxies (Istio, Linkerd, Envoy…) are excluded automatically. |
Built-in patterns
Enable by name. Use the pattern tool to preview against your actual log lines before deploying.
One helm install. Pick your patterns. Done.