Home / OCI

OCIRunbookAdvanced

Sev1: an OCI Object Storage bucket with sensitive data was made public. Contain, investigate, report

A bucket was switched to public or a long-lived pre-authenticated request was shared. Make it private and revoke PARs within minutes, use audit and access logs to learn what was read and by whom, and close the gaps that allowed it.

Deepak Bhardwaj3 min read

Applies toOCI Object Storage, pre-authenticated requests (PARs), OCI Audit, Object Storage service logs (read/write), Cloud Guard, OCI CLI 3.x

Symptoms

  • Cloud Guard problem: Bucket is public.
  • Someone reports a bucket URL that opens without sign-in.
  • A pre-authenticated request (PAR) link for a bucket or prefix shows up in a ticket, chat or public site.

Step 1: contain (5 minutes)

Make the bucket private:

oci os bucket update --namespace $NS --bucket-name finance-exports --public-access-type NoPublicAccess
oci os bucket get --namespace $NS --bucket-name finance-exports --query 'data."public-access-type"'

List and delete PARs:

oci os preauth-request list --namespace $NS --bucket-name finance-exports --all \
  --query 'data[].{id:id, name:name, type:"access-type", object:"object-name", expires:"time-expires"}' --output table

for id in $(oci os preauth-request list --namespace $NS --bucket-name finance-exports --all --query 'data[].id' --raw-output | tr -d '[]",'); do
  oci os preauth-request delete --namespace $NS --bucket-name finance-exports --par-id $id --force
done

Deleting a PAR invalidates its URL immediately.

Warning

Do not delete or overwrite the objects yet. They, their metadata and their access logs are evidence. If deletion is legally required, take a copy into a locked-down bucket first.

Stop the person or automation from re-opening it: check who made the change (step 2) and suspend that path if it is not trustworthy.

Step 2: who changed it, and when

oci audit event list --compartment-id $COMP \
  --start-time 2026-10-20T00:00:00Z --end-time 2026-10-29T23:59:59Z \
  --query 'data[?contains("event-type", `updatebucket`) || contains("event-type", `createpreauthenticatedrequest`)].{t:"event-time", type:"event-type", who:data.identity."principal-name", ip:data.identity."ip-address", bucket:data."resource-name"}' \
  --output table

Audit retention is limited (configurable at tenancy level); export to a bucket or Logging Analytics if the incident window is long. Event type strings vary in case; widen the filter if nothing matches.

Step 3: what was read

Object reads are not in Audit. They are in Object Storage service logs (read), only if those were enabled before the incident:

oci logging log list --log-group-id $LOG_GROUP --query 'data[].{name:"display-name", type:configuration.source.category}'

In Logging search:

search "<compartment-ocid>/<log-group-ocid>/<read-log-ocid>"
| where data.bucketName = 'finance-exports' and data.requestAction = 'GET'
| summarize count() by data.clientIpAddress, data.objectName

Field names follow the service log schema; check one raw record and adjust.

Situation What you can say
Read logs enabled, no external GETs Exposure without evidence of access
External IPs listed Those objects were downloaded; scope notification on them
Read logs not enabled You cannot prove what was accessed; assume everything public was accessible for the whole window

Step 4: assess and report

  • List what was exposed: oci os object list --bucket-name finance-exports --all --fields name,size,timeCreated.
  • Classify the data (personal data, credentials, financial).
  • If any credentials or keys were in the bucket, rotate them now.
  • Follow your incident process for legal and privacy notification; exposure windows and data types drive the obligations.

Step 5: confirm

  • Anonymous request fails:
curl -s -o /dev/null -w "%{http_code}\n" "https://objectstorage.eu-frankfurt-1.oraclecloud.com/n/$NS/b/finance-exports/o/"
# expect 404 or 401, not 200
  • No PARs remain on the bucket; Cloud Guard problem resolved.

Prevent it next time

  • Security Zones on compartments holding sensitive data: they deny public buckets outright.
  • IAM: only a small group gets BUCKET_UPDATE; use where request.permission conditions.
  • Limit PAR creation (PAR_MANAGE permission) and set short expiries by policy and habit.
  • Enable Object Storage read and write service logs on sensitive buckets now, so the next investigation has data.
  • An Events plus Functions rule that reverts public buckets automatically within seconds.