Container images pulled from a compromised or outdated registry are one of the quietest ways vulnerabilities slip into production. If your team pushes images to Oracle Cloud Infrastructure Registry (OCIR) as part of a CI/CD pipeline, every layer — base OS packages, language runtimes, third-party libraries — is a potential entry point for a known CVE. OCIR vulnerability scanning closes that gap by inspecting images for known vulnerabilities before and after they reach production, so a bad build doesn't quietly become a bad deployment. In this guide, you'll set up automated scanning using OCI's native Vulnerability Scanning Service, wire it into your registry and compute instances, interpret the results, and layer in image signing so only verified, scanned images actually run. By the end, you'll have a repeatable pipeline that catches vulnerable images before they ship, with clear steps for troubleshooting common scan failures along the way.
Step 1: Understand What OCIR Vulnerability Scanning Covers
Before configuring anything, it helps to know what you're actually getting. Oracle Container Registry scanning works through OCI's Vulnerability Scanning Service (VSS), which performs two related but distinct jobs:
- Container image scanning — inspects images stored in OCIR for known vulnerabilities (CVEs) in OS packages and, depending on configuration, application dependencies.
- Host/instance scanning — checks the OS and installed packages on running Compute instances, which matters if those instances are pulling and running your OCIR images.
For this walkthrough we're focused on the registry side: catching issues in the image itself before it's ever deployed. VSS uses Oracle's vulnerability database (informed by CVE feeds and Oracle Linux security advisories) and reports findings with CVSS severity scores directly in the OCI Console and via API/CLI.
Step 2: Enable the Vulnerability Scanning Service for Your Compartment
VSS scanning isn't on by default — it needs to be enabled per compartment and requires the right IAM policy so the service can read from OCIR.
First, create a dynamic group that covers the scanning service (or use an existing one scoped to your compartment):
# Dynamic group matching rule
ALL {resource.type = 'instance', resource.compartment.id = 'ocid1.compartment.oc1..xxxxx'}
Then add an IAM policy granting the Vulnerability Scanning Service access to inspect repositories:
Allow service vulnerabilityscanning to read repos in compartment security-compartment
Allow service vulnerabilityscanning to read vaults in compartment security-compartment
With policies in place, enable scanning from the console (Identity & Security → Vulnerability Scanning → Container Scan Recipes) or via the CLI:
oci vulnerability-scanning container-scan-recipe create \
--compartment-id ocid1.compartment.oc1..xxxxx \
--display-name "prod-ocir-scan-recipe" \
--scan-schedule '{"type":"DAILY"}'
This creates a recurring scan recipe that will apply to repositories you target in the next step.
Step 3: Create a Container Scan Target for Your OCIR Repositories
A scan recipe alone doesn't scan anything — you need a scan target that binds the recipe to specific repositories or a compartment-wide scope.
oci vulnerability-scanning container-scan-target create \
--compartment-id ocid1.compartment.oc1..xxxxx \
--display-name "prod-ocir-target" \
--container-scan-recipe-id ocid1.containerscanrecipe.oc1..xxxxx \
--target-registry '{"compartmentId":"ocid1.compartment.oc1..xxxxx"}'
You can scope targets narrowly (a single repository like myteam/api-service) or broadly (an entire compartment), depending on how granular your ownership boundaries are. Most teams start broad and narrow scope later once scan volume and noise become clear.
Once the target is active, OCIR vulnerability scanning kicks off automatically according to the schedule you set — daily is a reasonable default, but image-push-triggered scanning (via Events + Functions, covered below) gives tighter feedback loops.
Step 4: Trigger Scans on Image Push, Not Just on a Schedule
Daily scans are fine for drift detection, but they're too slow to block a bad image before it's deployed. Wire scanning into the push event itself using OCI Events and Functions:
- Create an Events rule that fires on
com.oraclecloud.containerregistry.pushImage. - Target an OCI Function (or a webhook to your CI system) that calls the VSS API to request an on-demand scan, or simply polls scan results and blocks the deployment pipeline until a "clean" verdict is returned.
oci events rule create \
--compartment-id ocid1.compartment.oc1..xxxxx \
--display-name "ocir-push-scan-trigger" \
--is-enabled true \
--condition '{"eventType":["com.oraclecloud.containerregistry.pushImage"]}' \
--actions '{"actions":[{"actionType":"FAAS","functionId":"ocid1.fnfunc.oc1..xxxxx","isEnabled":true}]}'
This turns your pipeline from "we scan eventually" into "nothing deploys until it's scanned," which is the actual security guarantee most teams think they already have.
Step 5: Review and Triage Scan Results
Once scans run, results appear under the repository in the OCI Console, or via CLI:
oci vulnerability-scanning container-scan-result list \
--compartment-id ocid1.compartment.oc1..xxxxx \
--image-id ocid1.containerimage.oc1..xxxxx
Each finding includes a CVE identifier, CVSS severity, the affected package/version, and (when available) a fixed version. Triage with a simple rule of thumb:
- Critical/High + fixed version available → block the image, rebuild with the patched base or dependency.
- Critical/High + no fix available → assess exploitability and exposure; consider compensating controls (network policy, runtime restrictions) if you must ship anyway.
- Medium/Low → track in backlog, don't block releases by default.
Export results into your existing vulnerability management workflow (ticketing, SIEM, or a dedicated ASPM tool) rather than treating the OCI Console as the system of record — scan data that isn't tracked against remediation SLAs tends to get scanned once and ignored forever.
Step 6: Sign Images So Only Scanned, Verified Builds Run
Scanning tells you an image is safe at a point in time; signing tells you that the image running in production is the exact one that passed the scan. Without OCI image signing, nothing stops a tag from being overwritten or a stale, unscanned image from being pulled by mistake.
Set up a signing key in OCI Vault, then sign the image after it passes scanning:
oci artifacts container image-signature create \
--compartment-id ocid1.compartment.oc1..xxxxx \
--image-id ocid1.containerimage.oc1..xxxxx \
--kms-key-id ocid1.key.oc1..xxxxx \
--signing-algorithm SHA_256_RSA_PKCS_PSS
Then enforce signature verification at deploy time using an image verification policy on your OKE cluster, so unsigned (and therefore unscanned) images are rejected outright rather than merely flagged.
Verification and Troubleshooting
A few issues come up repeatedly when teams set this up for the first time:
- Scan target shows "no images scanned" — usually an IAM policy gap. Double-check the dynamic group matches the resource actually calling the service, and that the
read repospolicy targets the correct compartment (not a parent or child compartment by mistake). - Scans complete but report zero vulnerabilities on an image you know has issues — confirm the scan actually completed rather than failed silently; check
lifecycleStateon the scan result viaoci vulnerability-scanning container-scan-result get. AFAILEDstate often means the image manifest format wasn't supported or the layer was unreadable. - Push-triggered scans aren't firing — verify the Events rule condition matches your registry's exact event type and compartment, and check the Function's logs for permission errors invoking the VSS API.
- Signature verification fails at deploy time — confirm the KMS key used for signing is accessible to the verifying component, and that the signature was created after the final scan pass, not against an earlier, since-modified image digest.
- Duplicate or noisy findings across repositories — narrow your scan target scope from compartment-wide to specific repositories, or apply severity thresholds so low-value findings don't drown out what needs action.
Run a manual end-to-end check periodically: push a known-vulnerable test image, confirm the push-triggered scan fires, confirm it's flagged correctly, and confirm your deployment gate actually blocks it. This exercise catches silent policy drift long before an incident does.
How Safeguard Helps
Native OCIR vulnerability scanning is a solid foundation, but most organizations run workloads across more than one registry — OCIR alongside ECR, GCR, GHCR, or a private Harbor instance — and stitching together consistent policy, triage, and remediation tracking across all of them by hand doesn't scale. Safeguard gives you a single control plane for software supply chain security that sits on top of OCI's native scanning: it aggregates vulnerability findings from OCIR and other registries into one view, applies consistent severity and SLA policy regardless of where an image lives, and correlates scan results with signing and provenance data so you can prove — not just assert — that what's running in production is exactly what passed review.
For teams building toward SOC 2 or similar compliance requirements, Safeguard also turns scan and signing evidence into audit-ready reporting automatically, instead of someone screenshotting the OCI Console every quarter. If you're already using OCI's Vulnerability Scanning Service, Safeguard doesn't replace that plumbing — it makes the results actionable, comparable across environments, and defensible when someone asks "how do you know?"