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."
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.
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.
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.
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:
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()
In addition to the generic documentation, the whitelist also contains several applications-specific methods that are available for use. Here are some examples:
We've raised enhancement 22997247 for a definitive listing of these APIs, in the meantime we will share potential useful ones on this blog.
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:
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()