← Back to Feed CACHED · 2026-10-22 08:51:09 · CACHE_KEY CVE-2026-91503
CVE-2026-91503 · CWE-863 · Disclosed 2026-10-20

Oracle Database Server VPD policy-context bypass via CREATE TABLE privilege over Oracle Net

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

It is like a bank vault where any teller with a desk key can walk through the safety-deposit wall

CVE-2026-91503 is a flaw in the Virtual Private Database (VPD) component of Oracle Database Server, affecting versions 19.3–19.32, 21.3–21.23, and 23.4.0–23.26.3. A database user who holds the CREATE TABLE privilege — a common grant for application service accounts, ETL users, and developers — can manipulate how VPD security-policy contexts are evaluated during data operations over Oracle Net. The result: the attacker bypasses row-level and column-level VPD predicates entirely, gaining read *and* write access to every row the VPD was supposed to hide. Confidentiality and integrity are both rated HIGH; availability is unaffected.

Oracle rates this HIGH at CVSS 8.1, and that is *broadly fair but slightly generous*. The 8.1 score already accounts for the PR:L authentication requirement, but it does not discount two important real-world factors: (1) VPD is an *optional* feature — only databases that actively use it are affected, and (2) Oracle Database listeners on port 1521 are almost never internet-exposed in well-run enterprises, which means the attacker typically needs internal network positioning or compromised application credentials first. On the other hand, VPD exists specifically to guard the *most sensitive* data (PII, financial records, healthcare data), so when the bypass lands, the blast radius is the worst data in the house. We downgrade marginally to 7.5 while keeping the verdict at HIGH.

"VPD policy bypass hands low-priv DB users the keys to every protected row."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Obtain authenticated Oracle Net session

The attacker needs a valid database account with network connectivity to the TNS listener (default port 1521). This could be a compromised application service account, a developer credential harvested from a config file, or an insider. The CVSS vector specifies PR:L — no DBA or SYSDBA role is needed, just a standard session.
Conditions required:
  • Valid database credentials for the target instance
  • Network route to Oracle TNS listener (port 1521/1522)
Where this breaks in practice:
  • Oracle TNS listeners are rarely exposed to the internet; Shodan historically shows <20,000 globally, most in cloud dev environments, not production
  • Credential theft requires a prior compromise stage (phishing, config leak, lateral movement)
Detection/coverage: Network IDS/IPS signatures for Oracle TNS handshake from unexpected source IPs; Oracle Audit Vault login-event alerts
STEP 02

Confirm CREATE TABLE privilege

The attacker verifies they hold the CREATE TABLE system privilege (or CREATE ANY TABLE). This privilege is commonly granted to application schemas, ETL service accounts, and development users. It is *not* a default grant for read-only reporting accounts, which limits the vulnerable population to a subset of database users.
Conditions required:
  • Database account holds CREATE TABLE or CREATE ANY TABLE privilege
Where this breaks in practice:
  • Read-only and reporting accounts typically lack this grant
  • Principle-of-least-privilege shops revoke DDL from production service accounts
Detection/coverage: Oracle Database Vault realm violations; audit policy on CREATE TABLE system privilege usage
STEP 03

Craft DDL-based VPD policy bypass

The attacker issues crafted SQL that exploits improper policy-context evaluation in the VPD engine during table-creation or table-modification operations. Based on the disclosed attack class and prior VPD bypass research (e.g., the 2024 DDL-permissions bypass documented by DatabaseSecurityNinja), the technique involves creating a new table via CREATE TABLE ... AS SELECT that copies data from VPD-protected tables, or manipulating policy group arguments during DDL execution. The VPD predicate that should filter rows is not applied to the DDL path, so the attacker's new table contains every row.
Conditions required:
  • Target table must be protected by a VPD policy
  • Attacker can issue DDL statements against the schema
Where this breaks in practice:
  • Database Vault realms can block DDL in protected schemas even if the privilege exists
  • SQL firewall / Database Activity Monitoring (DAM) tools flag anomalous DDL patterns
Detection/coverage: Oracle Audit trail: watch for CREATE TABLE ... AS SELECT on VPD-protected schemas; Imperva/Guardium DAM rules for bulk copy operations
STEP 04

Exfiltrate or modify protected data

With the VPD bypass achieved, the attacker can read all supposedly restricted rows and columns. The CVSS vector rates both C:H and I:H, meaning the attacker can also issue UPDATE/DELETE/INSERT against protected data. In regulated environments (healthcare, finance), this is a reportable breach of the most sensitive records — exactly the data VPD was deployed to protect.
Conditions required:
  • Successful VPD policy bypass from step 3
Where this breaks in practice:
  • Data Loss Prevention (DLP) tools may flag large result-set exports
  • Oracle Database Vault and privilege analysis can detect anomalous data access volumes
Detection/coverage: Database Activity Monitoring alerts on bulk SELECT or data export from sensitive tables; Oracle Unified Audit with fine-grained audit policies on VPD-protected objects
03 · Compensating Control

1
HIGH 7.5→MEDIUM 5.5
SEVERITY REDUCED
Revoke unnecessary CREATE TABLE and CREATE ANY TABLE privileges — Audit all database accounts and revoke DDL privileges from any account that does not strictly require them. Application service accounts performing only DML (SELECT/INSERT/UPDATE/DELETE) do not need CREATE TABLE. This directly breaks the attack chain at step 2. Deploy within 30 days per the noisgate mitigation SLA for HIGH-severity findings. Use SELECT * FROM DBA_SYS_PRIVS WHERE PRIVILEGE LIKE '%CREATE%TABLE%' to enumerate grants.
2
HIGH 7.5→LOW 3.5
SEVERITY REDUCED
Enable Oracle Database Vault realms on VPD-protected schemas — Database Vault realms prevent DDL operations against protected schemas even if the user holds system-level DDL privileges. This directly blocks step 3 of the attack chain. Configure realms for every schema that carries VPD policies. Deploy within 30 days. Note: Database Vault requires separate licensing and configuration effort.
3
HIGH 7.5→HIGH 6.5
Deploy Database Activity Monitoring (DAM) rules for anomalous DDL — Configure your DAM solution (Imperva SecureSphere, IBM Guardium, Oracle Audit Vault) to alert on CREATE TABLE ... AS SELECT statements targeting VPD-protected schemas. This does not prevent the exploit but provides near-real-time detection, enabling rapid incident response. Deploy within 30 days.
4
HIGH 7.5→IGNORE 0.0
SEVERITY REDUCED
Apply the October 2026 CPU (19.33 / 21.24 / 23.27) — This is the definitive fix. Apply the Oracle Release Update via OPatch. Schedule within the 180-day noisgate remediation SLA for HIGH-severity findings. Test in non-production first, as Oracle CPUs can introduce regressions in PL/SQL behavior and optimizer plans.
5
HIGH 7.5→MEDIUM 5.0
SEVERITY REDUCED
Restrict TNS listener access via network segmentation — Ensure Oracle TNS listeners (port 1521) are only reachable from authorized application servers and DBA jump hosts. Use firewall rules or Oracle Connection Manager to enforce source-IP restrictions. This limits the attacker population to only those already on the authorized network segment. Deploy within 30 days.
What doesn't work
  • Oracle Advanced Security (TDE/network encryption) — Transparent Data Encryption and network encryption protect data at rest and in transit, but do nothing to prevent an authenticated user from bypassing VPD policies at the SQL layer. The attacker's session is already authenticated and encrypted.
  • Oracle Label Security (OLS) alone — While OLS provides an additional access-control layer, it is a separate feature from VPD. Unless OLS policies are independently configured on the same tables, it does not compensate for VPD bypass.
  • Web Application Firewall (WAF) — WAFs inspect HTTP traffic, not Oracle Net (TNS) protocol traffic. They provide zero coverage for this attack vector.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationNo known exploitation. Not listed on CISA KEV as of 2026-10-22. No threat-intel reports of active campaigns targeting this CVE. The October 2026 CPU was released only 2 days ago.
Proof-of-Concept AvailabilityNo public PoC found. Checked pocindex.io, GitHub (no repos named CVE-2026-91503), ExploitDB, and Nuclei templates — all negative. However, the related 2024 VPD DDL-bypass technique by DatabaseSecurityNinja provides a conceptual roadmap that lowers the barrier for skilled attackers.
EPSS Score0.00278 (approximately 72nd percentile). Low probability of exploitation in the next 30 days, consistent with the authentication requirement and Oracle Database's typically non-internet-facing posture.
CISA KEV StatusNot listed. No due date set by CISA.
CVSS Vector InterpretationCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N — Network-reachable, low complexity, low privilege required, no user interaction, unchanged scope. High confidentiality and integrity impact, no availability impact. The S:U (unchanged scope) means the attacker stays within the VPD-protected database context.
Affected Version RangesOracle DB 19.3–19.32 (19c), 21.3–21.23 (21c), 23.4.0–23.26.3 (23ai). All three active long-term-support and innovation release trains are affected.
Fixed VersionsOctober 2026 CPU patches: 19.33 (19c RU), 21.24 (21c RU), 23.27 (23ai RU). Apply via OPatch or Oracle Release Update mechanism.
Internet Exposure (Shodan/Censys)Shodan historically indexes <20,000 Oracle TNS listeners globally on port 1521, and the vast majority are development/test instances. Production Oracle databases are almost universally behind firewalls. This significantly limits unauthenticated remote attack surface, though the CVE requires authentication anyway.
Disclosure Date2026-10-20 via Oracle Critical Patch Update October 2026. Coordinated disclosure; no prior public knowledge.
Reporting ResearcherNot publicly credited. Oracle CPU advisories typically do not name researchers for database-component vulnerabilities.

Sources.

  1. Oracle CPU October 2026 Advisory
  2. Strix.ai CVE-2026-91503 Detail
  3. Tenable: Oracle October 2026 CPU Analysis
  4. SecurityWeek: Oracle Patches 1200+ Vulnerabilities
  5. DatabaseSecurityNinja: Breaking VPD Through DDL Permissions
  6. Oracle Docs: Using VPD to Control Data Access
  7. UK Gov: Open Port 1521 Oracle Database Risk
05 · The Call

Final Verdict
= UNCHANGED to HIGH (7.5/10)

Why this verdict

  • Authentication gate is real friction: The attacker needs valid database credentials with CREATE TABLE privilege. This is not unauthenticated remote code execution — it presupposes either insider access, compromised application credentials, or a prior breach stage. The CVSS PR:L already discounts this, but real-world credential-theft difficulty further narrows the attacker population.
  • VPD-specific scope limits the affected population: VPD is an optional feature used primarily in regulated, multi-tenant, or row-level-security deployments. Not every Oracle Database instance uses VPD. Enterprises without VPD policies are unaffected regardless of version. This narrows the blast radius compared to a generic Oracle DB RCE.
  • Internal-network positioning required in practice: Oracle TNS listeners are almost never internet-exposed in production. The attacker needs internal network access or a tunneled connection, which implies a prior compromise stage or insider threat. This compounds the friction beyond what the CVSS AV:N suggests.
  • Role multiplier: Oracle Database is canonically a high-value-role component — production database engines host regulated data (PII, PHI, financial records). VPD specifically protects the *most sensitive* subset of that data. If the chain succeeds on a production Oracle instance with VPD, the outcome is mass data egress of the most sensitive records — a reportable breach. This sets a verdict floor of HIGH. The floor holds even with the authentication friction, because (a) application service accounts with CREATE TABLE are common, and (b) the data at risk is, by VPD's own design, the crown jewels.
  • No active exploitation or PoC tempers urgency: With EPSS at 0.00278, no KEV listing, no public PoC, and disclosure only 2 days old, the immediate risk of opportunistic exploitation is low. This prevents the verdict from reaching CRITICAL despite the high-value-role floor.

Why not higher?

A CRITICAL rating would require either unauthenticated access, active exploitation, or a scope change enabling lateral movement beyond the database. This CVE demands valid credentials with a specific privilege (CREATE TABLE), has no availability impact, no scope change (S:U), no public PoC, and no observed exploitation. The VPD-specific scope means many Oracle installations are simply unaffected. These factors collectively cap the verdict at HIGH.

Why not lower?

Oracle Database is a canonical high-value component hosting regulated production data. VPD protects the *most sensitive* rows by design — PII, PHI, financial records. Bypassing VPD on a production instance means full access to exactly that data, which constitutes a reportable breach. The CREATE TABLE prerequisite is common among application service accounts, and the exploit complexity is LOW. Dropping below HIGH would understate the blast radius when the chain lands on its intended target.

06 · Verification

Crowdsourced verification payload.

Run this script on any host with sqlplus installed and network access to the target Oracle instance. Invoke as: bash check_cve_2026_91503.sh <ORACLE_SID_OR_SERVICE> <HOST> <PORT>. The script connects as a DBA-privileged user (it will prompt for credentials) and checks the database patch level against the fixed Release Update versions. No changes are made to the database.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_91503.sh — Detect CVE-2026-91503 (Oracle VPD policy bypass)
# Usage: bash check_cve_2026_91503.sh <SERVICE_NAME> <HOST> [PORT]
# Requires: sqlplus on PATH, DBA-level credentials (prompted)
# Output: VULNERABLE / PATCHED / UNKNOWN
set -euo pipefail

SERVICE="${1:?Usage: $0 <SERVICE_NAME> <HOST> [PORT]}"
HOST="${2:?Usage: $0 <SERVICE_NAME> <HOST> [PORT]}"
PORT="${3:-1521}"

echo "[*] Checking CVE-2026-91503 on ${HOST}:${PORT}/${SERVICE}"
read -rp "DB Username: " DBUSER
read -rsp "DB Password: " DBPASS
echo

CONN="${DBUSER}/${DBPASS}@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=${HOST})(PORT=${PORT}))(CONNECT_DATA=(SERVICE_NAME=${SERVICE})))"

# Query the current Release Update version
RESULT=$(sqlplus -S "${CONN}" <<'EOSQL'
SET HEADING OFF FEEDBACK OFF PAGESIZE 0 LINESIZE 200 TRIMOUT ON TRIMSPOOL ON
SELECT VERSION_FULL FROM V$INSTANCE;
EXIT;
EOSQL
)

if [ -z "${RESULT}" ] || echo "${RESULT}" | grep -qi "error\|ORA-"; then
  echo "[!] UNKNOWN — could not connect or query V\$INSTANCE."
  echo "    Raw output: ${RESULT}"
  exit 2
fi

VERSION=$(echo "${RESULT}" | tr -d '[:space:]')
echo "[*] Detected Oracle version: ${VERSION}"

# Parse major.minor.0.0.RU from VERSION_FULL (e.g., 19.0.0.0.33 or 23.4.0.26.3)
IFS='.' read -ra PARTS <<< "${VERSION}"
MAJOR="${PARTS[0]}"

case "${MAJOR}" in
  19)
    # 19c: fixed in 19.33 (RU component is PARTS[4])
    RU="${PARTS[4]:-0}"
    if [ "${RU}" -ge 33 ] 2>/dev/null; then
      echo "[+] PATCHED — 19c RU ${RU} >= 19.33"
      exit 0
    else
      echo "[-] VULNERABLE — 19c RU ${RU} < 19.33 (affected range: 19.3-19.32)"
      exit 1
    fi
    ;;
  21)
    # 21c: fixed in 21.24
    RU="${PARTS[4]:-0}"
    if [ "${RU}" -ge 24 ] 2>/dev/null; then
      echo "[+] PATCHED — 21c RU ${RU} >= 21.24"
      exit 0
    else
      echo "[-] VULNERABLE — 21c RU ${RU} < 21.24 (affected range: 21.3-21.23)"
      exit 1
    fi
    ;;
  23)
    # 23ai: fixed in 23.27 — version format is 23.X.0.Y.Z; use PARTS[4]
    SUBRU="${PARTS[4]:-0}"
    MINORRU="${PARTS[3]:-0}"
    # Construct comparable integer: e.g. 23.26.3 -> 2603, 23.27.0 -> 2700
    COMP=$(( MINORRU * 100 + SUBRU ))
    FIXED=2700  # 23.27.0
    if [ "${COMP}" -ge "${FIXED}" ] 2>/dev/null; then
      echo "[+] PATCHED — 23ai version ${VERSION} >= 23.27"
      exit 0
    else
      echo "[-] VULNERABLE — 23ai version ${VERSION} < 23.27 (affected range: 23.4.0-23.26.3)"
      exit 1
    fi
    ;;
  *)
    echo "[!] UNKNOWN — major version ${MAJOR} is not in the affected range (19, 21, 23)."
    exit 2
    ;;
esac