Chapter 20 · Security: Privileges, Roles, Profiles, Unified Auditing, VPD, and Encryption

System/Object Privileges, Roles, Administrative Privileges, Definer/Invoker Rights, and Least Privilege

Build Oracle least privilege from system/object privileges and roles through administrative privileges and PL/SQL security domains, proving why role grants disappear from definer-rights stored-code privilege checks.

Advanced125–145 minutesDirect-grant vs role/PLSQL least-privilege labOracle AI Database 26ai · RU 23.26.3 baselineFree-compatible · local PDB security labLast reviewed: August 2026

Learning outcomes

ServiceHub has three very different identities: a schema that owns tables, a PL/SQL API that implements trusted business operations, and an application runtime that should only connect and invoke that API. Granting DBA to all three “because it fixes permission errors” destroys the security boundary. Oracle authorization distinguishes system privileges, object privileges, roles, powerful administrative privileges, and the privilege domain used by stored PL/SQL.

01

Distinguish system privileges, object privileges, roles and SYSDBA/SYSOPER/SYSBACKUP/SYSKM-style administrative privileges.

02

Explain local versus common users/grants in a CDB and why an application PDB should normally use local identities.

03

Reproduce the definer-rights direct-grant rule: an object privilege received only through a role does not satisfy stored PL/SQL compilation/runtime requirements.

04

Contrast AUTHID DEFINER and AUTHID CURRENT_USER, including INHERIT PRIVILEGES risk for invoker-rights code.

05

Build an owner/API/runtime split in FREEPDB1 and verify the runtime cannot directly read the protected table.

Generation-time security baseline and operational boundary

Mandatory examples target Oracle AI Database Free 26ai, reviewed against RU 23.26.3, SQL Developer 26.2, and SQLcl 26.2.1. Free remains limited to 2 foreground CPU cores, 2 GB combined SGA/PGA memory, 12 GB user data, and one installation per logical environment; Oracle provides neither Release Update patches nor Support service requests for Free. The course CDB/PDB baseline is FREE/FREEPDB1. Security administration is performed in the narrowest required container with dedicated administrative roles such as AUDIT_ADMIN or SYSKM where possible, rather than making the application runtime SYSDBA. Current licensing lists Fine-Grained Auditing, Virtual Private Database (VPD), Data Redaction, Transparent Data Encryption (TDE), Oracle Advanced Security, Database Vault, and Privilege Analysis as available in Free. Network encryption through Native Network Encryption (NNE) and Transport Layer Security (TLS) is available across supported licensed editions and is no longer an Oracle Advanced Security feature. No real password, private key, certificate private material, wallet password, recovery secret, or API credential appears in these files.

1. System privileges authorize classes of database actions

A system privilege authorizes an action such as CREATE SESSION, CREATE TABLE, or CREATE PROCEDURE. Some privileges ending in ANY cross schema boundaries and are correspondingly powerful. Granting SELECT ANY TABLE to an application just to read one table violates least privilege because future tables become readable too.

sql · inventory direct system privileges for the existing ServiceHub identities
SELECT grantee,privilege,admin_option,common,inheritedFROM dba_sys_privsWHERE grantee IN ('SERVICEHUB_OWNER','SERVICEHUB_APP')ORDER BY grantee,privilege;

2. Object privileges authorize operations on named objects

An object privilege targets a specific table, view, sequence, procedure, package or other object. The Chapter 1 runtime pattern—CREATE SESSION plus selected DML on ServiceHub objects and no CREATE TABLE—is intentionally narrower than an owner schema.

sql · object-level evidence
SELECT  grantee,  owner,  table_name,  privilege,  grantableFROM dba_tab_privsWHERE grantee='SERVICEHUB_APP'ORDER BY owner,table_name,privilege;

The dictionary proves grants, not whether the application actually uses them. Privilege Analysis can measure usage on supported deployments, but static least-privilege review remains necessary.

3. Roles group privileges, but roles are not a substitute for every direct grant

A role is a named bundle of privileges. Roles simplify assignment to users and can be enabled/disabled per session. However, definer-rights stored PL/SQL is intentionally compiled/executed with a restricted security domain: required privileges on referenced external objects must be granted directly to the definer, not merely inherited through a role.

sql · admin setup in FREEPDB1
ALTER SESSION SET CONTAINER=FREEPDB1;BEGIN EXECUTE IMMEDIATE 'DROP USER sh20_api CASCADE';EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1918 THEN RAISE; END IF; END;/BEGIN EXECUTE IMMEDIATE 'DROP USER sh20_data CASCADE';EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1918 THEN RAISE; END IF; END;/BEGIN EXECUTE IMMEDIATE 'DROP USER sh20_runtime CASCADE';EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1918 THEN RAISE; END IF; END;/BEGIN EXECUTE IMMEDIATE 'DROP ROLE sh20_reader_role';EXCEPTION WHEN OTHERS THEN IF SQLCODE != -1919 THEN RAISE; END IF; END;/CREATE USER sh20_data NO AUTHENTICATION  DEFAULT TABLESPACE users QUOTA 10M ON users;CREATE USER sh20_api NO AUTHENTICATION  DEFAULT TABLESPACE users QUOTA 10M ON users;CREATE USER sh20_runtime NO AUTHENTICATION;GRANT CREATE TABLE TO sh20_data;GRANT CREATE PROCEDURE TO sh20_api;GRANT CREATE SESSION TO sh20_api,sh20_runtime;CREATE TABLE sh20_data.secure_work_orders (  work_order_id NUMBER PRIMARY KEY,  status_code   VARCHAR2(12) NOT NULL);INSERT INTO sh20_data.secure_work_orders VALUES (1,'OPEN');COMMIT;CREATE ROLE sh20_reader_role;GRANT SELECT ON sh20_data.secure_work_orders TO sh20_reader_role;GRANT sh20_reader_role TO sh20_api;

NO AUTHENTICATION creates schema-only accounts: they can own objects but cannot be used for password login. For this lab, temporarily enable interactive authentication for SH20_API without embedding its password in the lesson.

text · SQLcl/SQL*Plus as security administrator
PASSWORD sh20_api-- SQLcl/SQL*Plus prompts for the new password and confirmation.-- Do not spool, echo, or commit that secret.

4. Deliberate failure: role privilege does not compile a definer-rights procedure

text · connect as SH20_API, then compile with role-only SELECT
CONNECT sh20_api@//localhost:1521/FREEPDB1-- Enter password interactively.CREATE OR REPLACE PROCEDURE get_open_count(  p_count OUT NUMBER)AUTHID DEFINERASBEGIN  SELECT COUNT(*)  INTO p_count  FROM sh20_data.secure_work_orders  WHERE status_code='OPEN';END;/SHOW ERRORS-- Expected compile diagnostics include:-- PL/SQL: ORA-00942: table or view does not exist

The table exists and the session can have the role enabled, but a definer-rights program unit needs the referenced object privilege directly. This prevents an enabled-role change from silently expanding the stored program's authority.

5. Repair: direct grant to the low-privileged API schema

sql · admin repairs the exact missing capability
GRANT SELECT ON sh20_data.secure_work_orders TO sh20_api;
sql · SH20_API recompiles successfully
CREATE OR REPLACE PROCEDURE get_open_count(  p_count OUT NUMBER)AUTHID DEFINERASBEGIN  SELECT COUNT(*)  INTO p_count  FROM sh20_data.secure_work_orders  WHERE status_code='OPEN';END;/SHOW ERRORS-- Expected: No errors.

The safe repair is not GRANT SELECT ANY TABLE and not GRANT DBA. It is the exact direct object privilege required by the API.

6. Runtime gets EXECUTE—not table access

sql · admin grants the application contract only
GRANT EXECUTE ON sh20_api.get_open_count TO sh20_runtime;SELECT grantee,owner,table_name,privilegeFROM dba_tab_privsWHERE grantee='SH20_RUNTIME'ORDER BY owner,table_name,privilege;

The runtime needs CREATE SESSION and EXECUTE on the API. It does not need SELECT on the underlying table.

7. Invoker rights intentionally uses the caller's privilege domain

AUTHID CURRENT_USER creates an invoker-rights unit. At runtime, external SQL references are checked using the invoking user's direct privileges and enabled roles. This is useful for shared utilities that should never gain more authority merely because a privileged schema owns the code.

sql · invoker-rights contrast
CREATE OR REPLACE PROCEDURE sh20_api.count_as_invoker(  p_count OUT NUMBER)AUTHID CURRENT_USERASBEGIN  EXECUTE IMMEDIATE    'SELECT COUNT(*) FROM sh20_data.secure_work_orders'    INTO p_count;END;/

If SH20_RUNTIME invokes this without table privilege, it fails even though the API owner can read the table. Oracle also protects invoker-rights callers with INHERIT PRIVILEGES/INHERIT ANY PRIVILEGES; removing those grants can produce ORA-06598 until the caller explicitly trusts the code owner.

8. Administrative privileges are authentication modes, not application roles

SYSDBA, SYSOPER, SYSBACKUP, SYSDG and SYSKM are purpose-specific administrative privileges. They can authenticate through the password file and bypass ordinary application authorization in powerful ways. Use the narrowest privilege—SYSBACKUP for RMAN, SYSKM for key management—rather than using SYSDBA everywhere.

sql · inspect administrative privilege holders
SELECT  username,  sysdba,  sysoper,  sysbackup,  sysdg,  syskmFROM v$pwfile_usersORDER BY username;

9. Common versus local grants

A local user created in FREEPDB1 belongs only to that PDB. A common user is created in CDB$ROOT and normally uses the common-user prefix. Likewise, CONTAINER=CURRENT versus CONTAINER=ALL changes grant scope. ServiceHub application users should stay local unless a cross-container administrative use case explicitly requires a common identity.

Container check before grants

Always run SYS_CONTEXT('USERENV','CON_NAME')/SHOW CON_NAME before user/role administration. Creating an application account in CDB$ROOT can produce ORA-65096; the repair is to connect to FREEPDB1, not to invent a C## application user.

10. Cleanup

sql · admin cleanup in FREEPDB1
DROP USER sh20_runtime CASCADE;DROP USER sh20_api CASCADE;DROP USER sh20_data CASCADE;DROP ROLE sh20_reader_role;

11. Production judgment

Separate ownership, trusted stored APIs and runtime identities. Prefer direct object grants where stored definer-rights code requires them, roles for human/job privilege bundles, and invoker-rights code when the caller's authority should constrain execution. Review ANY privileges, grant options, administrative privileges and common grants as high-risk surfaces.

No restart, pack, option, or COMPATIBLE increase is required. The lab is PDB-local and Free-compatible. Lesson 2 adds authentication/account lifecycle controls around these identities without confusing password policy with authorization.

Check your understanding

  1. What is the difference between a system privilege and an object privilege?
  2. Why did the role-only SELECT grant fail for the definer-rights procedure?
  3. What does AUTHID CURRENT_USER change?
  4. Should an application runtime normally receive SYSDBA?
  5. Why are local PDB users preferable for ordinary ServiceHub application identities?
Review the answers

A system privilege authorizes a class of database action; an object privilege authorizes an operation on a specific object.

Definer-rights stored PL/SQL requires referenced object privileges to be granted directly to the definer, not only through enabled roles.

It makes the unit run with the invoker's runtime privilege/name-resolution domain, subject to INHERIT PRIVILEGES controls.

No. Administrative privileges are for database administration/recovery/key roles, not application DML/runtime access.

They keep authorization scoped to the application PDB and avoid unnecessary common/root authority.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.