Safeguard
Security Guides•

Does kubectl apply copy your manifest into an annotation?

Yes. Client side kubectl apply stores your file contents in the last-applied-configuration annotation. Here is why that matters for Secrets.

Safeguard Security Team
3 min read

Yes. Client side kubectl apply writes the contents of your configuration file into the kubectl.kubernetes.io/last-applied-configuration annotation on the live object. Anything in the manifest therefore travels with the object. That matters most for Secret manifests, because plaintext values in the file can end up readable in object metadata.

What the annotation is

The Kubernetes documentation on declarative object management says that applying a directory of files sets the annotation on each object, and that the annotation contains the contents of the object configuration file used to create it. The labels and annotations reference calls it a legacy mechanism kubectl uses to track changes, and says it has been superseded by server side apply.

You can see it for yourself on any object you applied:

kubectl get deployment example -o yaml

Look under metadata and annotations.

Why this is a security issue

Whoever can read an object can read its annotations. Reading a Deployment is a common permission. Reading Secrets is usually restricted. If you put a Secret manifest with real values through client side apply, the annotation may carry those values, in a place that does not get the same access control as the Secret's data field.

Treat this as a reasonable inference from the documented behaviour and verify it on a test Secret in your own cluster before relying on it either way.

It also affects non secret data: internal hostnames, comments, or anything else in your files.

How to avoid leaking through it

PracticeWhy
Do not commit or apply plaintext Secret manifestsThe file contents are what gets copied
Create Secrets from an external store or an operatorThe value never sits in your manifest
Use server side apply where your tooling supports itThe docs say it supersedes this mechanism
Restrict get on workload objects as well as on Secrets in sensitive namespacesAnnotations travel with every read
Scan live objects for the annotation containing secret like stringsFinds past exposure

Our guide on where each Kubernetes value goes covers the config versus secret split.

Cleaning up existing objects

  1. List objects that carry the annotation in sensitive namespaces.
  2. Search the annotation text for credentials or tokens.
  3. Rotate anything you find, since the old value may have been read.
  4. Recreate the object without the secret in the file.

Quick check

Does server side apply store the same annotation?

The Kubernetes docs say server side apply supersedes the mechanism. Check how your version and tooling behave rather than assuming.

Is the annotation encrypted like a Secret?

Do not assume so. It is metadata on the object, so check how your cluster treats it and who can read it.

Safeguard runs policies and gates on pull requests, so a failed rule can hold a merge, and its dependency and SBOM scanning covers the packages your infrastructure code pulls in. You can try a free scan at gold.safeguard.sh/scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.