Unable to resolve class Number from Groovy script

Hi, guys!

I'm developing plugin for Elasticsearch 2.3 which does simple conversion of found documents for search client. This plugin uses Groovy scripts which does this conversion. I'm faced with curious problem: for example, when this script is evaluated by Elasticsearch's script service:

if (doc.field instanceof Double) {
    // do some conversion under field
}

Here is ok, script works fine, but this:

// changed Double to Number to cover all types of numbers
if (doc.field instanceof Number) {
    // do some conversion under field
}

gives strange exception in logs:

ScriptException[failed to compile groovy script]; nested: MultipleCompilationErrorsException[startup failed:
fd3511425ed9b373349aefab43c955d014d045e4: 1: unable to resolve class Number

So, I dug deeper and found that real exception is SecurityException wrapped into ClassNotFoundException, which is done in GroovyScriptEngineService:

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    if (sm != null) {
        try {
            engineContext.checkPermission(new ClassPermission(name));
        } catch (SecurityException e) {
            throw new ClassNotFoundException(name, e);
        }
    }
    return super.loadClass(name, resolve);
}

but nothing of them has been logged.

Then I found a place in class org.elasticsearch.script.ClassPermission where the list of permitted classes is created:


// this is the list from the old grovy sandbox impl (+ some things like String, Iterator, etc that were missing)
public static final Set<String> STANDARD_CLASSES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
        // jdk classes
        java.lang.Boolean.class.getName(),
        java.lang.Byte.class.getName(),
        java.lang.Character.class.getName(),
        java.lang.Double.class.getName(),
        ...

and there is no java.lang.Number, but mentioned java.lang.Double is added.

Questions of this topic:

  1. Why I had to do non-trivial actions to know that I have to just grant access to some "forbidden" class in policy file ?
  2. How do you think, is it normal to make grant to java.lang.Number in policy file, and other classes from java.lang not enumerated in STANDARD_CLASSES ?

Not a direct answer to your questions, but at least some wider context:

Groovy has had security problems in the past, and so we have tried to restrict which java classes scripts can access, resulting in the very restrictive security policy you came up against.

As of ES 5.0 we've deprecated Groovy scripting in favor of the new painless scripting: https://github.com/elastic/elasticsearch/pull/20244

Mike McCandless

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.