X

It's All About the Platform.

Understanding The Groovy Whitelist

Richard Bingham
Senior Development Manager

 

This article explains and illustrates how the use of some APIs and utility functions are restricted by a feature known as the groovy whitelist. This feature, introduced in Release 9, prevents the use of potentially malicious or destabilising APIs from within your groovy scripts. The feature checks the code before execution and raises an exception if it encounters a call which violates the predetermined whitelist.

There is some related documentation and this article looks at applying this in practical terms. In addition to understanding the functionality available today, if you have specific requirements that do not fit then please raise these with Oracle Support for consideration as a product enhancement. There is a short video demo on our YouTube channel that shows the whitelist being enforced.

 

The method 'is not permitted' errors look like the screenshot below, and for constructors you'll see the similar "Calling the constructor for class [yourclass] is not permitted."

Restricted Methods

Note that not all methods for the supported APIs are available for use - a common assumption we have observed. If you look at the documentation it states explicitly the named methods that are available, or states that 'any' of the methods (and constructors) are available for use.

Know The APIs

In some cases it may be unclear if problems are caused by a whitelist restriction or something that is a coding problem. As such we always recommend that you get familiar with the APIs before using them, and rechecking your use if you encounter problems.

For example if you call an API incorrectly or not one of the methods explicitly stated as supported, then you'll get - a MissingMethodException. For example looking at the SecurityContext documentation you might think it possible to get all the users profile details with a direct call such as this:

 

def secCtx = adf.context.getSecurityContext.getUserProfile()

However when you do you'll see the following run-time error.

Here the UserProfile return object is a class with its own specific methods, such as getFirstName(). Therefore the script should initialize the UserProfile object and then call specific methods.

def secCtx = adf.context.getSecurityContext().getUserProfile()
def rslt = secCtx.getFirstName()
setAttribute('UtilityField_c', rslt)

 

Similarly if you try to call the SecurityContext.isUserInRole() API
directly you will also get the error above, however you should first initialize a
context object (using adf.context.getSecurityContext()) and then call the isUserInRole() method on that object. This would only be clear from going through the API documentation.

 

API Source

Note that many common methods (e.g. ArrayList, LinkedHashMap and String) are derived from the Java Development Kit and not from the extensions provided by the Groovy Development Kit where similar APIs also exist. The majority of the Groovy APIs are actually protected by the whitelist as often the utility methods it adds to extend Java interact with parts of the environment outside the use-case for Application Composer groovy scripting. We've seen this as an issue before where the assumption is that the Groovy APIs are being used and therefore the environment is missing specific methods and interface signatures.

 

 

Whitelist Internals

 

As you may be able to determine from the start of the documentation, there is both a blacklist of disallowed APIs and also a whitelist of allowed APIs. This combination allows for more rigorous and complete checking of code. These work together in the following way:
  1. The underlying platform maintains a small blacklist of methods that expose capabilities not intended for use. If such an API is being used the
    script will be immediately rejected. For example the methods from the java.lang.Runtime class are on the blacklist. This internal
    blacklist is not published.
  2. If the call passes the blacklist checking, then it gets processed against a secondary whitelist of
    classes and methods.

 

 

Internally the whitelist definition is set in file extensions.gwx.xml, and is controlled in each application's adf-config.xml file, under entry "EnableExprScanning="true|false". Changes to this file are not supported without approval from Oracle Product Development.

For example, a common request was to allow groovy to make manual HTTP
connections to remote sites, however the very same methods can be used
for malicious purposes. As such you'll find the HttpUrlConnection class is restricted. Similarly everything from filesystem (e.g. Java.IO.*) is blocked. Even seemingly innocuous functions, such as groovys toURL() that may be useful in
working with URLs also allows other
types of connections. Consider the following which would print the content from a local file - clearly a security concern:

def c = "file:///../conf/httpd.conf i".toURL().getText()
print c

Special Cases

In addition to the generic documentation, the whitelist also contains several applications-specific methods that are available for use. Here are some examples:

  • oracle.topologyManager.client.deployedInfo.DeployedInfoProvider - allows access the Topology Manager that stores URL's, available within Setup and Maintenance - Manage Third Party Applications.
  • oracle.apps.fnd.applcore.common.SecuredTokenBean().getTrustToken()  - allows generation of a JWT token for securing integration with external services and systems.
  • oracle.apps.fnd.applcore.common.ApplSessionUtil.getCurrency() - allows access to the users preferred currency.
  • oracle.apps.fnd.applcore.Profile.get("FND_CURRENCY") - allows access to the profile option values set for your user session.
  • adf.context.getSecurityContext() - allows access to various methods for accessing user profile and security data.

We've raised enhancement 22997247 for a definitive listing of these APIs, in the meantime we will share potential useful ones on this blog.

Using Import Statements

For some APIs you'll need to include the full package path, else you'll get an error like "The following field names were not recognized: ADFContext". For longer scripts where multiple uses of the same API may be used, the solution normally would be to use an import statement like:

 

import oracle.adf.share.ADFContext.*

However you will get an Error Parsing Body error popup message:

As such you can still use underlying classes (not restricted by the whitelist), just use the full package.class.method to write out the call in long form, such as:

def myGoodVal = oracle.adf.share.ADFContext.getLocale()

 

 

Join the discussion

Comments ( 2 )
  • Jason Monday, May 16, 2016

    Hi Richard,

    For restriction in Whitelist, it can't access REST api via groovy script after R9 without invoking java method. But now how to do invoking HTTP method, such as ToURL method and etc?


  • Richard Bingham Monday, May 16, 2016

    Hi

    The article explains that you cannot access ToURL(), the whitelist blocks access to all the underlying libraries for the reasons mentioned.

    Regards

    Richard


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.