Minimize Container Registries To Only Those Approved
More Info:
Use approved container registries. If using OCI Container Registry, utilize OCI IAM policies to control access to the container registry.
Risk Level
Low
Address
Security
Compliance Standards
- APRA CPS 234 (Australia)
- BSI C5 (Germany)
- Brazil LGPD
- CCPA / CPRA (California)
- CIS Critical Security Controls v8
- CIS OKE
- CMMC 2.0
- CSA Cloud Controls Matrix v4
- DPDPA
- Digital Operational Resilience Act (EU)
- Essential 8
- ISO/IEC 27017
- ISO/IEC 27018
- ISO/IEC 27701
- KSA PDPL
- MAS Technology Risk Management (Singapore)
- MITRE ATT&CK (Cloud)
- NIS2 Directive
- NIST SP 800-171
- NYDFS 23 NYCRR 500
- SWIFT Customer Security Controls Framework
- Sarbanes-Oxley IT General Controls
- UK NCSC Cyber Assessment Framework
Triage and Remediation
- Remediation
Remediation
Manual Steps
-
Identify all registries currently used by cluster workloads
- On any machine with
kubectlaccess, list all images used in the cluster and extract their registries:kubectl get pods -A -o jsonpath='{range .items[*]}{.spec.containers[*].image}{"\n"}{.spec.initContainers[*].image}{"\n"}{end}' \| tr ' ' '\n' | sed '/^$/d' | sort -u - From this list, note the distinct registry domains (e.g.
iad.ocir.io,docker.io,gcr.io,quay.io, internal registries).
- On any machine with
-
Define and document the approved registries list
- Out-of-band (documentation / policy), compile a list of registries that are explicitly approved for use (e.g. specific OCIR regions and repositories, specific third‑party registries).
- Compare the discovered registry list from step 1 against this approved list and flag any non‑approved registries for follow‑up.
-
Review OCI Container Registry (OCIR) usage and IAM controls
- In the OCI Console, navigate to Developer Services → Container Registry and list all repositories being used by the cluster (match against images from step 1).
- For each relevant compartment, review IAM policies via OCI CLI (run from any machine with OCI CLI configured):
oci iam policy list --compartment-id <COMPARTMENT_OCID> --all
- Verify that only intended groups/principals have
read/pullpermissions on the OCIR repositories used by the cluster, and that broader policies (e.g.inspect repos in tenancy) are justified and documented.
-
Tighten or create OCI IAM policies for OCIR as needed
- For flagged overly-broad access, update or create policies in the OCI Console or via IaC to:
- Restrict OCIR access to specific groups (e.g. cluster nodes, CI/CD service accounts).
- Limit scope to specific compartments and, where applicable, to specific repos.
- Example (conceptual) policy snippet to allow only a build group to push and cluster nodes to pull, scoped to a compartment:
- “Allow group
<build-group>to manage repos in compartment<compartment-name>” - “Allow group
<cluster-nodes-group>to read repos in compartment<compartment-name>”
- “Allow group
- Apply equivalent constraints in your Terraform/other IaC if used.
- For flagged overly-broad access, update or create policies in the OCI Console or via IaC to:
-
Assess and harden third‑party registries (if any)
- For each non‑OCIR registry discovered in step 1, consult that vendor’s access control and security best practices (e.g. repository‑scoped credentials, read‑only tokens, IP allowlists, enforced TLS, signed images).
- In the vendor console/CLI/IaC, ensure:
- Only required identities (CI/CD, node pools) can pull images.
- Multi‑factor auth / strong credentials are enforced for human access.
- Public repositories are used only where explicitly intended.
-
Verify only approved registries are in current and new workloads
- Re-run the image discovery and validation from step 1 and confirm all registries now appear in the approved list.
- Optionally, implement admission controls (OPA/Gatekeeper, Kyverno, or managed policy features) out-of-band to prevent future use of unapproved registries, and then validate by attempting (and seeing rejection of) a deployment using an unapproved registry.
Using kubectl
kubectl cannot be used to restrict which container registries are allowed or to configure OCI IAM/third‑party registry access; this is controlled at the cloud/provider and registry/IAM configuration layer. Apply the changes using your cloud console, CLI, or IaC as described in the Manual Steps section.
Automation
#!/usr/bin/env bash
#
# Report all container image registries in the cluster for review
# Run on: any machine with kubectl access and correct KUBECONFIG
#
# Usage:
# ./report-image-registries.sh > image-registries-report.txt
set -euo pipefail
# Optional: define your approved registries here (space-separated substrings or FQDNs)
# Examples for OCI:
# iad.ocir.io mytenancy/ myregion.ocir.io
APPROVED_REGISTRIES=(
"iad.ocir.io"
"phx.ocir.io"
# add more approved registry hostnames or patterns here
)
# Helper: print header to stderr so stdout stays machine-friendly if needed
echo "Collecting image registry usage from all namespaces..." >&2
# Get all images from all pods, including initContainers, across all namespaces
# Output format: NAMESPACE POD CONTAINER_TYPE CONTAINER_NAME IMAGE
kubectl get pods --all-namespaces -o json \
| jq -r '
.items[]
| . as $pod
| [
$pod.metadata.namespace,
$pod.metadata.name,
"container",
( .spec.containers[]? | .name, .image )
],
[
$pod.metadata.namespace,
$pod.metadata.name,
"initContainer",
( .spec.initContainers[]? | .name, .image )
]
| select(length>0)
' 2>/dev/null \
| paste - - - - - \
| sed 's/\t/ /g' \
| sort -u \
> /tmp/_all_pod_images.txt
echo "Discovered the following unique container images (namespace pod type name image):" >&2
cat /tmp/_all_pod_images.txt >&2
# Extract registry host (or 'docker.io' for implicit Docker Hub) from image reference
# E.g.:
# iad.ocir.io/tenant/repo/image:tag -> iad.ocir.io
# nginx:latest -> docker.io
# library/nginx:1.21 -> docker.io
# registry.k8s.io/pause:3.9 -> registry.k8s.io
awk '
{
ns=$1; pod=$2; ctype=$3; cname=$4; image=$5;
registry=image;
# Split image by /
n=split(image, parts, "/");
if (n == 1) {
# No slash -> implicit Docker Hub
registry="docker.io";
} else if (n == 2 && index(parts[1], ".") == 0 && index(parts[1], ":") == 0) {
# Form: namespace/repo (no dots or port) -> Docker Hub
registry="docker.io";
} else {
# First element is registry host
registry=parts[1];
}
print ns, pod, ctype, cname, image, registry;
}
' /tmp/_all_pod_images.txt > /tmp/_all_pod_images_with_registry.txt
echo "" >&2
echo "Unique registries in use:" >&2
cut -d" " -f6 /tmp/_all_pod_images_with_registry.txt | sort -u >&2
# Check against APPROVED_REGISTRIES list
echo "" >&2
echo "Checking for images that do NOT match approved registry patterns..." >&2
# Build a simple grep pattern from APPROVED_REGISTRIES
APPROVED_PATTERN=""
if [ "${#APPROVED_REGISTRIES[@]}" -gt 0 ]; then
for r in "${APPROVED_REGISTRIES[@]}"; do
# Escape dots for grep
esc=$(printf '%s\n' "$r" | sed 's/\./\\./g')
if [ -z "$APPROVED_PATTERN" ]; then
APPROVED_PATTERN="$esc"
else
APPROVED_PATTERN="$APPROVED_PATTERN|$esc"
fi
done
fi
if [ -z "$APPROVED_PATTERN" ]; then
echo "No APPROVED_REGISTRIES configured in script; listing all images grouped by registry." >&2
echo "" >&2
echo "=== ALL IMAGES GROUPED BY REGISTRY (for manual review) ===" >&2
sort -k6,6 /tmp/_all_pod_images_with_registry.txt \
| column -t \
| sed 's/^/ /' >&2
echo "" >&2
echo "NOTE: Manually determine which registries are approved (e.g., your OCI Container Registry endpoints)" >&2
echo " and ensure that only images from those registries are in use." >&2
else
# Print non-approved images to stdout (machine-readable)
# Format: NAMESPACE POD CONTAINER_TYPE CONTAINER_NAME IMAGE REGISTRY
grep -Ev " (${APPROVED_PATTERN})$" /tmp/_all_pod_images_with_registry.txt || true
echo "" >&2
echo "=== NON-APPROVED REGISTRY USE (if any) ===" >&2
if grep -Ev " (${APPROVED_PATTERN})$" /tmp/_all_pod_images_with_registry.txt >/tmp/_non_approved.txt; then
cat /tmp/_non_approved.txt \
| sort -k6,6 \
| column -t \
| sed 's/^/ /' >&2
echo "" >&2
echo "INTERPRETATION:" >&2
echo " Lines above show pods using images whose registry hostname does NOT match any approved pattern:" >&2
printf ' - Approved patterns: %s\n' "${APPROVED_REGISTRIES[@]}" >&2
echo " For each entry, review whether this registry should be approved or the workload should be updated" >&2
echo " to use an image from your approved registries (e.g., OCI Container Registry with proper IAM policies)." >&2
else
echo "No images from non-approved registries detected based on current APPROVED_REGISTRIES list." >&2
fi
fi
echo "" >&2
echo "DONE. For OCI Container Registry, ensure OCI IAM policies restrict who can push/pull images." >&2
What output indicates a problem
- Any lines printed under
=== NON-APPROVED REGISTRY USE (if any) ===show pods using images from registries that are not in yourAPPROVED_REGISTRIESlist. - If you did not configure
APPROVED_REGISTRIES, manually review the “ALL IMAGES GROUPED BY REGISTRY” section and treat any registry that is not an explicitly approved OCI Container Registry endpoint (or other vetted third‑party registry) as a potential issue.