About Restricted Execution Contexts

The PURE keyword can be specified on MLE environments and JavaScript inline call specifications to create restricted JavaScript execution contexts.

In-database JavaScript code can leverage database functionality, such as SQL execution, using APIs like the MLE JavaScript SQL Driver and SODA. PURE execution disallows access to stateful database APIs inside JavaScript, meaning the execution is completely unprivileged. In a PURE environment, JavaScript code cannot read or write any database state, such as tables, procedures, and objects.

The only possible interaction with the database during PURE execution is through inputs and outputs to JavaScript code. This can be in the form of data provided to MLE from the database through user-defined function arguments for call specifications, as well as symbols exported using DBMS_MLE.EXPORT_TO_MLE. Reference types, such as LOBs passed to MLE, can be accessed (read or written) during PURE execution. Additionally, PURE execution does not restrict access to supported data types.

In many situations, JavaScript user-defined functions are purely computational and don't require access to powerful APIs such as the MLE JavaScript SQL driver or the Foreign Function Interface (FFI). PURE execution serves as a method to isolate certain code, such as third-party JavaScript libraries, from the database itself. This isolation can reduce the attack surface of supply chain attacks, in which access to the database state is a security concern. Using PURE execution also allows less-privileged developers to create these restricted user-defined functions without requiring additional access or privileges to the database state or network.

The following JavaScript APIs and global classes and functions are not available during PURE execution:

  • JavaScript APIs:
    • mle-js-oracledb
    • mle-js-plsql-ffi
    • mle-js-fetch
  • Global classes and functions:
    • session
    • soda
    • plsffi
    • oracledb
    • require

JavaScript APIs that do not interact with database state, such as mle-js-plsqltypes and mle-js-encodings remain accessible during PURE execution.

The PURE keyword can be specified in inline call specifications, in module call specifications, and using DBMS_MLE. The following are examples of the syntax in each case:

  • Module call specification:

    CREATE OR REPLACE MLE MODULE pure_mod
    LANGUAGE JAVASCRIPT AS
    export function helloWorld() {
        console.log('Hello World, this is a JS module');
    }
    /
    
    CREATE OR REPLACE MLE ENV pure_env
    IMPORTS( 'pure_mod' MODULE pure_mod) PURE;
    
    CREATE OR REPLACE PROCEDURE helloWorld
    AS MLE MODULE pure_mod ENV pure_env SIGNATURE 'helloWorld';
    /
  • Inline call specification:

    CREATE OR REPLACE PROCEDURE helloWorld 
    AS MLE LANGUAGE JAVASCRIPT PURE
    {{
        console.log('Hello World, this is a JS inlined call specification');
    }};
    /
  • Using DBMS_MLE:

    SET SERVEROUTPUT ON;
    DECLARE
        l_ctx     dbms_mle.context_handle_t; 
        l_snippet CLOB; 
    BEGIN
        -- to specify PURE execution with DBMS_MLE, use an environment 
        -- that has been created with the PURE keyword
        l_ctx := dbms_mle.create_context(environment => 'PURE_ENV'); 
        l_snippet := q'~
            console.log('Hello World, this is dynamic MLE execution');
        ~'; 
        dbms_mle.eval(l_ctx, 'JAVASCRIPT', l_snippet); 
        dbms_mle.drop_context(l_ctx); 
    EXCEPTION 
        WHEN OTHERS THEN 
            dbms_mle.drop_context(l_ctx); 
            RAISE; 
    END; 
    /