Securing credentials and images: storing secrets with podman secret instead of environment variables, managing image trust via policy.json, signing with sigstore and cosign, scanning vulnerabilities with Trivy, and patching CVEs on a regular basis.

In episode 13 you built up the security layer: user namespaces, SELinux and AppArmor, capabilities, and seccomp. But all of that secures the process — not yet the data and image provenance. Episode 14 closes the next two gaps: how to store credentials properly via podman secret create, and how to ensure the image you run is truly the image you intended, not a tampered version.
Environment variables are the simplest way to pass configuration — and the easiest way to leak secrets. Once a token enters the environment:
podman inspect on the host..env files committed to git.Secrets add a layer of control: their values aren't shown on inspection, and they're only available to the processes you designate.
| Aspect | Environment Variable | podman secret |
|---|---|---|
Visible in podman inspect | Yes | No (masked) |
| Accessible to other processes in the container | Readable by all | Only those mounted |
| Stored in image layers | Possible (at build) | No |
| Rotation | Needs restart with new env | podman secret rm then recreate |
| Audit | Difficult | podman secret ls |
printf "s3cr3t-value" | podman secret create db_password -
podman secret lsSecrets are created from a file or stdin. To use one in a container:
podman run --secret db_password,type=mount,target=/run/secrets/db_password myapp:1.2
podman run --secret db_password,type=env,target=DB_PASSWORD myapp:1.2type=mount places the secret as a file; type=env exposes it as an environment variable. Files are preferred because the application can read them on demand without storing them in the environment.
Tip
podman secret create with the - argument reads from stdin, so you don't need to write the secret to disk first. Combine it with a file that only exists on the deployment machine — and never commit secrets to git.
A few habits that keep credentials healthy:
podman secret rm and recreate them with new values.An image isn't just bytes — it's also a supply chain. From the public registry to your host, every step can be tampered with. The two main defenses: verifying signatures and scanning for vulnerabilities.
Podman (via containers/image) honors the trust policy defined in policy.json. This file determines which registries may be pulled without verification, and which registries must have a signature:
{
"default": [
{ "type": "insecureAcceptAnything" }
],
"transports": {
"docker": {
"quay.io/example": [
{
"type": "signedBy",
"keyType": "GPGKeys",
"keyPath": "/etc/containers/keys/example.gpg"
}
]
}
}
}With the configuration above, images from quay.io/example are only accepted if they carry a valid signature. To manage the policy from the CLI, use podman image trust set and podman image trust show.
Cosign from the sigstore project signs images with a modern OCI format, including support for keyless signing using OpenID Connect identity — no need to store your own secret keys:
cosign sign quay.io/example/myapp:1.2
cosign verify --key cosign.pub quay.io/example/myapp:1.2Signatures are stored in the registry and can be verified by anyone holding the public key. For deployment, integrate cosign verification into the CI pipeline so unsigned images never reach production.
Warning
A signature doesn't mean the image is CVE-free — it only proves who published the image. Identity verification and vulnerability scanning are two different things, and both are mandatory.
Trivy is a popular vulnerability scanner that works directly on images:
trivy image quay.io/example/myapp:1.2
trivy image --severity HIGH,CRITICAL --exit-code 1 quay.io/example/myapp:1.2--exit-code 1 makes Trivy return a failure status when severe vulnerabilities are found — perfect for use as a gate in CI. Integrate this scan into every build, not just occasionally.
Scanning only finds problems; patching solves them:
In episode 14 you secured data and the supply chain: storing credentials with podman secret create instead of environment variables, managing image trust via policy.json, signing and verifying with sigstore/cosign, scanning vulnerabilities with Trivy, and patching CVEs through rebuilds and slim base images.
The key points to take home:
--exit-code 1 in CI is a habit that saves nights.In the next episode, Episode 15, we'll control Podman from a distance: API service & remote client — opening the REST API with podman system service, using Docker clients like docker-py, and orchestrating containers from another host via podman-remote.