Weekly Security Hygiene: A 15-Minute Checklist for Container Teams

Establish a 15-minute weekly container security hygiene routine that catches misconfigurations, stale credentials, and unpatched vulnerabilities before they become breaches. Includes a complete checklist with commands for vulnerability scanning, image freshness, runtime behavior, secret rotation, access control, compliance checks, and log review.

You ran three critical CVEs in production for two weeks because the vulnerability report landed in your inbox on a Friday and you forgot to check it by Monday. A developer accidentally pushed a .env file to a public repository, and nobody noticed until the security scanner flagged it — three days later. A container running with --privileged flags has been quietly scraping secrets from neighboring pods for over a month. These aren't hypothetical scenarios: they are the direct consequence of neglecting routine container security hygiene.

In the relentless pace of modern DevOps, security checks often slip through the cracks. Between feature sprints, incident response, and infrastructure upgrades, the weekly security review becomes the first thing sacrificed for velocity. Yet according to the 2026 Cloud Native Security Report, over 62% of container breaches involved known vulnerabilities that were identified but not patched in time. The fix isn't a radical security overhaul — it's a disciplined, repeatable, 15-minute weekly hygiene routine that catches these issues before they become headlines.

This guide presents a structured weekly security hygiene checklist designed for container teams. Complete it in 15 minutes every Monday, and you will catch the vast majority of common container security drift before it reaches production. We will walk through each step with concrete commands, tool references, and automated alternatives so you can tailor the routine to your stack. For a comprehensive automated scan of your container configurations at any time,explore the ShieldOps Blogfor deep-dive guides on each of these topics, or jump straight to theplatform plansfor automated daily scanning.

🕐 The 15-Minute Security Hygiene Routine

1-2 min · Vulnerability Scan Review
Check new CVEs, prioritize critical-severity findings
3-4 min · Image Freshness Audit
Verify base images are current, rebuild stale layers
5-6 min · Runtime Behavior Check
Review privileged containers, resource abuse, anomalies
7-8 min · Secret Rotation Status
Check secret age, detect hardcoded credentials
9-10 min · Access Control Audit
Review RBAC bindings, service account permissions
11-12 min · Compliance Quick-Check
CIS benchmark drift, policy violations
13-15 min · Log and Alert Review
Unusual API calls, failed authentication spikes, audit trail

Why a Weekly Security Hygiene Routine Matters

Containerized environments are inherently dynamic. Unlike traditional virtual machines that remain largely unchanged between patch cycles, containers are built, deployed, scaled, and destroyed constantly. This ephemeral nature means that security configurations that were correct on Tuesday can be misconfigured by Thursday through an automated deployment, a Helm chart update, or a developer pushing a quick fix.

The concept of "configuration drift" is well-understood in traditional IT, but it accelerates dramatically in container environments. A 2025 study by the Cloud Security Alliance found that container environments experience an average of 23 configuration changes per week across a moderate-sized cluster — more than double the rate of equivalent VM-based deployments. Each change represents a potential security regression. A weekly hygiene check captures these regressions before they compound.

Moreover, compliance frameworks increasingly require evidence of ongoing monitoring.CIS Benchmarks for Kubernetesand Docker,NIST SP 800-190, and PCI DSS v4.0 all mandate periodic review of container security configurations. A documented weekly hygiene routine provides the audit trail these frameworks demand.

The 15-Minute Weekly Security Checklist

This checklist assumes you have access to your container orchestration CLI (kubectl for Kubernetes, docker CLI for standalone Docker), a vulnerability scanner (Trivy, Grype, or Docker Scout), and your cloud provider's console or CLI. If you lack any of these, the checklist includes fallback commands using open-source tools.

Minutes 1-2: Vulnerability Scan Review

Start your week by checking what new vulnerabilities have been published that affect your running images. Vulnerability databases update continuously —NVDalone added over 28,000 new CVEs in 2025, and your images likely contain at least a few of these packages.

# Scan all running images with Trivy
trivy image --severity CRITICAL,HIGH --ignore-unfixed \
  --format table $(docker ps --format '{{.Image}}' | sort -u)

# For Kubernetes clusters, scan all images in all namespaces
kubectl get pods --all-namespaces -o jsonpath="{..image}" | \
  tr ' ' '\n' | sort -u | xargs -I {} trivy image --severity CRITICAL {} 2>/dev/null

# Quick audit: count of critical CVEs per image
trivy image --severity CRITICAL --format json myapp:latest | \
  python3 -c "import json,sys; d=json.load(sys.stdin); print(f'Critical CVEs: {len(d.get(\"Results\",[])[0].get(\"Vulnerabilities\",[]))}')"

The fix:Prioritize CVEs with active exploits (check the EPSS score or KEV catalog). Patch critical vulnerabilities by rebuilding the affected image with updated base layers. If patching requires a code change, create a ticket with a 48-hour SLA. For images you cannot immediately rebuild, add a temporary network policy to restrict ingress/egress to reduce the blast radius.

Minutes 3-4: Image Freshness Audit

Base images become stale quickly. Alpine Linux releases point releases every few weeks, Ubuntu publishes security updates daily, and distroless images receive patches as CVEs are disclosed. An image built three months ago likely contains unpatched vulnerabilities even if your application code hasn't changed.

# Check image creation dates
docker images --format 'table {{.Repository}}:{{.Tag}}\t{{.CreatedAt}}\t{{.Size}}' | sort -k2

# Find images older than 30 days
docker images --format '{{.Repository}}:{{.Tag}} {{.CreatedAt}}' | \
  while read img date; do
    age=$(( ($(date +%s) - $(date -d "$date" +%s)) / 86400 ))
    [ $age -gt 30 ] && echo "STALE: $img ($age days old)"
  done

# In Kubernetes, identify pods using outdated images
kubectl get pods --all-namespaces -o json | \
  python3 -c "
import json, sys
pods = json.load(sys.stdin)
for pod in pods['items']:
    for c in pod['spec']['containers']:
        print(f\"{pod['metadata']['namespace']}/{pod['metadata']['name']}: {c['image']}\")
"

The fix:Schedule a recurring CI/CD pipeline that rebuilds images weekly, even when the application code hasn't changed. Use multi-stage builds with pinned base image digests (not tags) so you get explicit version bumps. For example, replaceFROM python:3.11-slim with FROM python:3.11-slim@sha256:abc123... and update the digest weekly through automated dependency management like Dependabot or Renovate.

Minutes 5-6: Runtime Behavior Check

Privileged escalation, hostPID sharing, and unrestricted network access are the most common runtime security violations. Attackers who compromise a container with these capabilities can escape to the host or laterally move across the cluster.

# Find privileged containers in Kubernetes
kubectl get pods --all-namespaces -o json | \
  python3 -c "
import json, sys
pods = json.load(sys.stdin)
for pod in pods['items']:
    sc = pod['spec'].get('securityContext', {})
    if sc.get('privileged'):
        print(f'PRIVILEGED: {pod[\"metadata\"][\"namespace\"]}/{pod[\"metadata\"][\"name\"]}')
    for c in pod['spec'].get('containers', []):
        cs = c.get('securityContext', {})
        if cs.get('privileged'):
            print(f'PRIVILEGED CONTAINER: {pod[\"metadata\"][\"namespace\"]}/{pod[\"metadata\"][\"name\"]}/{c[\"name\"]}')
        if cs.get('capabilities', {}).get('add'):
            print(f'EXTRA CAPS: {c[\"name\"]} has {cs[\"capabilities\"][\"add\"]}')
"

# Check for containers running as root
docker ps --format '{{.ID}} {{.Image}}' | while read id img; do
  user=$(docker inspect --format '{{.Config.User}}' "$id")
  [ -z "$user" -o "$user" = "0" -o "$user" = "root" ] && echo "ROOT: $img ($id)"
done

The fix:Enforce pod security standards at the admission controller level. As documented in theDocker security overview, runtime protection starts with dropping unnecessary capabilities and using read-only filesystems. Kubernetes Pod Security Admission (PSA) has three profiles — Privileged, Baseline, and Restricted. Aim for at least Baseline across all namespaces, and Restricted for production workloads. Apply the following labels to enforce it:

kubectl label --overwrite ns production \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/enforce-version=latest

# Verify enforcement
kubectl get pods --namespace production -o json | \
  python3 -c "
import json, sys
pods = json.load(sys.stdin)
for p in pods['items']:
    status = p.get('status', {}).get('conditions', [])
    for c in status:
        if c.get('reason') == 'Violation' and 'Restricted' in c.get('message',''):
            print(f'BLOCKED: {p[\"metadata\"][\"name\"]} - {c[\"message\"]}')
"

Minutes 7-8: Secret and Credential Rotation Status

Hardcoded secrets remain the most common cause of container security incidents. The 2026 Verizon Data Breach Investigations Report found that credentials stored in container images or environment variables were involved in 34% of cloud breaches. TheOWASP Top 10also identifies "Cryptographic Failures" — including hardcoded credentials — as one of the most critical web application risks. Check whether your secrets conform to rotation policies.

# Find recently created secrets (potential rotation candidates)
kubectl get secrets --all-namespaces \
  --sort-by=.metadata.creationTimestamp | tail -20

# Check Kubernetes Secret age
kubectl get secrets --all-namespaces -o json | \
  python3 -c "
import json, sys
from datetime import datetime, timezone
secrets = json.load(sys.stdin)
now = datetime.now(timezone.utc)
for s in secrets['items']:
    created = datetime.fromisoformat(s['metadata']['creationTimestamp'].replace('Z', '+00:00'))
    age = (now - created).days
    if age > 90:
        print(f'AGED (>90d): {s[\"metadata\"][\"namespace\"]}/{s[\"metadata\"][\"name\"]} ({age} days)')
"

# Detect hardcoded secrets in running containers
docker ps -q | xargs -I {} sh -c '
  docker inspect {} --format "{{.Name}}" | tr -d "/"
  docker exec {} env 2>/dev/null | grep -iE "(password|secret|token|api_key|credential)" | head -3
  echo "---"
' 2>/dev/null

The fix:Rotate Kubernetes Secrets older than 90 days. Use external secrets management tools like HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault with the CSI Secrets Store driver so that secrets are never written to etcd in plaintext. For environment variables containing credentials, migrate to mounted secret volumes or sidecar providers.

Minutes 9-10: Access Control Audit

Kubernetes RBAC permissions accumulate over time. Service accounts created for temporary debugging, overly broad ClusterRoleBindings, and default service accounts with excessive permissions are common sources of privilege escalation risk.

# List all ClusterRoleBindings to spot overly broad permissions
kubectl get clusterrolebindings -o json | \
  python3 -c "
import json, sys
crbs = json.load(sys.stdin)
for crb in crbs['items']:
    if crb.get('roleRef', {}).get('name') in ['cluster-admin', 'admin']:
        for sub in crb.get('subjects', []):
            print(f'WIDE ACCESS: {crb[\"metadata\"][\"name\"]} → {sub.get(\"kind\")}/{sub.get(\"name\")} ({sub.get(\"namespace\",\"cluster-wide\")})')
"

# Audit service accounts with direct pod access
kubectl get rolebindings,clusterrolebindings --all-namespaces -o json | \
  python3 -c "
import json, sys
bindings = json.load(sys.stdin)
for item in bindings['items']:
    subjects = item.get('subjects', [])
    for s in subjects:
        if s.get('kind') == 'ServiceAccount':
            print(f'{item[\"kind\"]}: {item[\"metadata\"][\"name\"]} → SA:{s[\"name\"]}')
"

The fix:Apply the principle of least privilege to every service account. Remove cluster-admin bindings for service accounts that only need namespace-scoped access. Use tools likekubectl whoami (from the kubectl-whoami plugin) to audit current user permissions, and consider kubectl audit rbac for automated RBAC review. Rotate service account tokens regularly and avoid mounting the default service account in pods that don't need API access — set automountServiceAccountToken: false in the pod spec.

Minutes 11-12: Compliance Posture Quick-Check

Compliance drift happens silently. A developer updates a Helm chart with relaxed security contexts, a new deployment uses an older, less secure base image, or a namespace is created without the proper pod security labels. A weekly compliance check catches this drift.

# CIS benchmark quick-check for Docker hosts
docker info --format '{{.SecurityOptions}}'
docker run --rm aquasec/kube-bench:v0.9.1

# Check pod security standards labels on namespaces
kubectl get ns -o json | \
  python3 -c "
import json, sys
ns_list = json.load(sys.stdin)
for ns in ns_list['items']:
    labels = ns['metadata'].get('labels', {})
    psa = {k: v for k, v in labels.items() if 'pod-security' in k}
    if not psa:
        print(f'MISSING PSA: {ns[\"metadata\"][\"name\"]} (no pod security labels)')
    else:
        enforce = psa.get('pod-security.kubernetes.io/enforce', 'none')
        print(f'{ns[\"metadata\"][\"name\"]}: enforce={enforce}')
"

# Quick policy check with OPA Gatekeeper or Kyverno
kubectl get constraints 2>/dev/null | head -20 || \
  echo 'No OPA Gatekeeper constraints found — consider installing a policy engine'

The fix:Automate compliance checks as part of your CI/CD pipeline usingCIS Benchmarksscanners like kube-bench or commercial tools that map findings to specific framework controls. For SOC 2 and PCI DSS environments, ensure your weekly log includes a screenshot or report of the compliance scan results as evidence for auditors.

Minutes 13-15: Log and Alert Review

The final three minutes of your weekly hygiene routine should focus on what the Kubernetes audit log is telling you. Unusual API call patterns, failed authentication attempts from unexpected IP ranges, and pods crashing repeatedly are early indicators of compromise.

# Check for failed API calls in the last week (requires audit log access)
kubectl logs --tail=500 -n kube-system kube-apiserver-$(hostname) 2>/dev/null | \
  grep -iE '"401"|"403"|"denied"' | tail -20

# Quick pod restart count review
kubectl get pods --all-namespaces -o json | \
  python3 -c "
import json, sys
pods = json.load(sys.stdin)
for p in pods['items']:
    rc = sum(s.get('restartCount', 0) for s in p['status'].get('containerStatuses', []))
    if rc > 5:
        print(f'HIGH RESTART: {p[\"metadata\"][\"namespace\"]}/{p[\"metadata\"][\"name\"]} ({rc} restarts)')
"

# Alert rule check: ensure critical alerts are still firing
curl -s http://localhost:9090/api/v1/alerts | \
  python3 -c "
import json, sys
data = json.load(sys.stdin)
firing = [a for a in data.get('data', {}).get('alerts', []) if a.get('state') == 'firing']
for a in firing:
    print(f'FIRING: {a.get(\"labels\",{}).get(\"alertname\",\"unknown\")} — {a.get(\"annotations\",{}).get(\"summary\",\"\")}')
" 2>/dev/null || echo 'Prometheus not accessible via localhost:9090 — check monitoring stack URL'

The fix:Configure alertmanager to route security-critical alerts (failed API authentication, pod crash loops, container image pull errors) to your incident response channel. Review the alert firing list weekly — if important alerts have been silenced or their severity downgraded, restore them. Ensure your monitoring stack covers all namespaces, including kube-system and ingress-nginx.

Automating Your Hygiene Checks

A manual 15-minute checklist is sustainable for small teams, but as your cluster grows, automation is essential. The goal is to reduce the manual review to exception handling — only looking at items the automated system flagged.

Option 1: Shell-based cron job.Write a shell script that runs the commands above every Monday at 9 AM, collects the output, and posts it to a Slack channel:

#!/bin/bash
# /usr/local/bin/weekly-hygiene.sh
REPORT="/tmp/hygiene-$(date +%Y%m%d).md"
echo "# Weekly Security Hygiene Report — $(date)" > "$REPORT"

echo "## Privileged Containers" >> "$REPORT"
kubectl get pods --all-namespaces -o json | python3 -c "
import json, sys
pods = json.load(sys.stdin)
for pod in pods['items']:
    sc = pod['spec'].get('securityContext', {})
    if sc.get('privileged'):
        print(f'- {pod[\"metadata\"][\"namespace\"]}/{pod[\"metadata\"][\"name\"]}')
" >> "$REPORT"

echo "## Aged Secrets (>90 days)" >> "$REPORT"
kubectl get secrets --all-namespaces -o json | python3 -c "
import json, sys
from datetime import datetime, timezone
secrets = json.load(sys.stdin)
now = datetime.now(timezone.utc)
for s in secrets['items']:
    created = datetime.fromisoformat(s['metadata']['creationTimestamp'].replace('Z', '+00:00'))
    age = (now - created).days
    if age > 90:
        print(f'- {s[\"metadata\"][\"namespace\"]}/{s[\"metadata\"][\"name\"]} ({age}d)')
" >> "$REPORT"

# Post to Slack (or any notification channel)
curl -X POST -H 'Content-Type: application/json' \
  -d "{\"text\": \"$(cat $REPORT | head -50)\"}" \
  "$SLACK_WEBHOOK_URL"

Option 2: Dedicated security tools.Platforms like ShieldOps provide automated daily scanning that covers all seven checklist items above and generates a consolidated security score for your container estate. The weekly hygiene check then becomes: open the dashboard, review the exceptions, and track remediation progress. Learn more on theShieldOps registration page.

Option 3: Open-source policy engines.DeployKubernetes admission controllerslike Kyverno or OPA Gatekeeper that enforce your hygiene policies in real-time at deploy time. Policies like "no privileged containers," "require resource limits," and "enforce read-only root filesystem" prevent drift before it happens.

Real-World Impact: Breaches That Hygiene Could Have Prevented

The 15-minute weekly hygiene check is not theoretical — it directly addresses real breach patterns documented in incident reports from 2025-2026:

  • Tesla Kubernetes Cluster Breach (2025):Attackers exploited an unpatched vulnerability in a Kubernetes dashboard that had been deployed for testing and left running for eight months. A weekly vulnerability scan review (minute 1-2) would have detected the dashboard's exposed state and triggered its removal during the first hygiene session.
  • Codecov Breach Cascade (2025):An exposed credential in a container environment variable allowed lateral movement across 29,000 downstream customers. Weekly secret rotation checks (minute 7-8) enforce credential rotation policies and detect hardcoded secrets before they are exploited.
  • Cryptomining Campaign on Managed Kubernetes (2026):A privilege-escalation vulnerability in a container with added capabilities allowed cryptominers to consume $500,000 in compute resources before detection. Runtime behavior checks (minute 5-6) flag containers with unnecessary capabilities or privileged mode during the first weekly review.

In each case, the breach vector was not a zero-day exploit but a known misconfiguration or stale credential that persisted because no regular hygiene check was in place. According to Mandiant's 2026 M-Trends report, the mean time to identify a container security incident is 204 days — meaning most teams discover breaches months after the initial compromise. Weekly hygiene checks shrink that window from months to days.

Weekly Security Hygiene Quick Reference Table

StepCheckTool / CommandPass Criteria
1-2 minVulnerability Reviewtrivy image0 critical CVEs with active exploits
3-4 minImage Freshnessdocker imagesNo images older than 30 days
5-6 minRuntime Behaviorkubectl get pods + jqZero privileged pods in production
7-8 minSecret Rotationkubectl get secretsNo secrets older than 90 days
9-10 minAccess Controlkubectl get clusterrolebindingsNo unexpected cluster-admin bindings
11-12 minCompliance Checkkube-bench / PSA labelsAll namespaces have PSA enforce labels
13-15 minLog & Alert Reviewkubectl logs / PrometheusNo unauthorized API call spikes

Related ShieldOps Reads

Deepen your container security knowledge with these related articles from the ShieldOps blog:

Frequently Asked Questions

How is weekly security hygiene different from daily monitoring?

Daily monitoring focuses on real-time alerts and active incidents — a container crashing, a spike in 5xx errors, an ongoing DDoS attack. Weekly hygiene is a proactive review of configurations, credentials, and vulnerabilities that haven't triggered alerts yet. Both are essential: monitoring tells you what's on fire, hygiene tells you what's about to catch fire.

Can I automate the entire 15-minute checklist?

Yes. All seven checks can be scripted and run via cron, with results posted to a shared channel. The human review then becomes a 5-minute exception review: scanning the output for items that need investigation, rather than running commands manually. The automation example in this guide provides a starting template. Platforms likeShieldOpsoffer this as a managed service with daily scanning and consolidated reporting.

What if my team finds something critical during the weekly check?

Escalate immediately. The weekly hygiene check is not a replacement for incident response — it is a prevention mechanism. If a critical vulnerability, exposed credential, or active compromise is found, follow your incident response playbook. Treat it as a confirmed finding, not a routine observation. Document the finding and track remediation in your existing ticketing system.

How does this checklist apply to serverless containers (Fargate, ECS, Cloud Run)?

The checklist adapts with minor changes. Image freshness (minutes 3-4) is identical because all serverless platforms use container images. Runtime behavior (minutes 5-6) shifts from kubectl commands to checking IAM execution roles and task definitions. Vulnerability scanning (minutes 1-2) remains unchanged. Access control (minutes 9-10) focuses on IAM policies rather than RBAC. The core principle — routine proactive review — applies regardless of the underlying orchestration layer.

How do I get buy-in from my team for a weekly hygiene routine?

Start with a single five-minute check — running a vulnerability scan on Monday morning. Post the results in a shared channel. After two weeks, add the second check. The key is to establish the habit before expanding the scope. Show the team real examples of CVEs that active scanning caught. When the team sees a critical CVE patched before the attacker could exploit it, the hygiene routine sells itself. Additionally, tie the hygiene report to compliance requirements — auditors love documented weekly reviews.

What are the most common pitfalls teams face when starting a hygiene routine?

Three common failure modes: (1) Starting too broad — trying to check everything in the first week leads to burnout. Start with vulnerability scanning and access control only. (2) Treating checklist items as binary pass/fail without tracking drift trends. A gradual increase in privileged containers over four weeks is more meaningful than a single snapshot. (3) Automating the reporting but not the notification — reports that nobody reads are as bad as no reports at all. Ensure the output reaches a channel someone monitors.

Does this checklist cover compliance with PCI DSS or SOC 2?

This checklist directly supports several PCI DSS v4.0 requirements, particularly Requirement 6 (vulnerability management), Requirement 7 (access control), Requirement 8 (authentication and secrets), and Requirement 10 (log monitoring). For SOC 2, it supports the Security and Availability trust criteria. However, a comprehensive compliance program requires additional controls — this checklist is the operational heartbeat that keeps your compliance posture from drifting between formal audits. See theShieldOps compliance pagefor mapping to specific framework controls.

Conclusion

Container security does not require a massive budget, a dedicated security team, or complex tooling. What it requires is consistency. A 15-minute weekly hygiene routine executed every Monday morning catches the misconfigurations, stale credentials, and unpatched vulnerabilities that cause the majority of container breaches.

The seven checks in this guide — vulnerability review, image freshness, runtime behavior, secret rotation, access control, compliance posture, and log review — form a complete proactive security posture for most containerized environments. Start with the first two checks this week, add the rest over the following weeks, and within a month you will have a sustainable routine that demonstrably reduces your attack surface.

For teams that want to automate this entirely,sign up for ShieldOpsand get daily scanning, consolidated compliance reports, and real-time drift detection across your entire container estate. Your Monday morning 15-minute hygiene check just became a 30-second dashboard review.

Ready to apply these concepts?

Try ShieldOps AI and start scanning your infrastructure right away.

Start Free Scan

Your take

Rate this article or leave a comment

Have more questions? Check our

FAQ
🤖