New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Catch and wrap AssertionError and NoClassDefFoundError in groovy scripts #19958
Conversation
As much as I don't like catching java's LGTM |
Do we need the same protection in the other language plugins? Probably not painless, but lang-javascript and lang-python might need it. |
@@ -293,7 +293,7 @@ public Object run() { | |||
// NOTE: we truncate the stack because IndyInterface has security issue (needs getClassLoader) | |||
// we don't do a security check just as a tradeoff, it cannot really escalate to anything. | |||
return AccessController.doPrivileged((PrivilegedAction<Object>) script::run); | |||
} catch (Exception e) { | |||
} catch (Exception | AssertionError | NoClassDefFoundError e) { // Groovy asserts are not java asserts, and cannot be disabled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should inspect the AssertionError
and make sure that it comes from Groovy (by inspecting the stack trace and looking for assertFailed
and other relevant Groovy calls).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I added a check for this, and a comment explaining why
Also why not simply add StringBuffer for groovy if it makes its assert work? The list is very simple: based on the old groovy sandbox, but that sandbox was not really "working" as well, for example So we may have to add classes like stringbuilder/buffer or other things. |
We may want to add those classes too, but we need something like that so that other asserts floating around groovy don't shoot the JVM. We also don't want asserts users write to shoot the jvm, or any time they call Class.forName somehow. |
Yes: I agree the two things are ... somewhat unrelated. But this is tied to the issue there, and adds a test that groovy's |
public void testGroovyScriptsThatThrowErrors() throws Exception { | ||
assertFailure("assert false, \"msg\";", AssertionError.class); | ||
assertFailure("def foo=false; assert foo;", AssertionError.class); | ||
assertFailure("def bar=false; assert bar, \"msg2\"", NoClassDefFoundError.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is because we are not granting the class permission for StringBuffer
but I think we should?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I added the permissions for that (StringBuffer)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, but that was before we knew that we would need to add a permission for InvokeHelper
too? So maybe we should just not add it since it will not help with getting asserts to work? Sorry.
I can certainly add StringBuffer, however, that isn't the only class required to get groovy asserts to work, it also needs |
yes, lets leave that one out of it, serialization/reflection/etc, its not a good guy. Thanks for checking. |
@@ -123,6 +123,13 @@ public void testEvilGroovyScripts() throws Exception { | |||
} | |||
} | |||
|
|||
public void testGroovyScriptsThatThrowErrors() throws Exception { | |||
assertFailure("assert false, \"msg\";", AssertionError.class); | |||
assertFailure("def foo=false; assert foo;", AssertionError.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For extra super paranoia's sake can you add a test that throws NoClassDefFoundError so we have something independent that checks that user scripts that do that don't halt the jvm?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to do that, we have to add permissions for the java.lang.NoClassDefFoundError
in ClassPermission.java. Are we sure we want to add permissions for that class only to add a test case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense to me.
LGTM. |
Previously, we only caught subclasses of Exception, however, there are some cases when Errors are thrown instead of Exceptions. These two cases are `assert` and when a class cannot be found. Without this change, the exception would bubble up to the `uncaughtExceptionHandler`, which would in turn, exit the JVM (related: elastic#19923). A note of difference between regular Java asserts and Groovy asserts, from http://docs.groovy-lang.org/docs/latest/html/documentation/core-testing-guide.html "Another important difference from Java is that in Groovy assertions are enabled by default. It has been a language design decision to remove the possibility to deactivate assertions." In the event that a user uses an assert such as: ```groovy def bar=false; assert bar, "message"; ``` The GroovyScriptEngineService throws a NoClassDefFoundError being unable to find the `java.lang.StringBuffer` class. It is *highly* recommended that any Groovy scripting user switch to using regular exceptions rather than unconfiguration Groovy assertions. Resolves elastic#19806
f9bee1c
to
aab8c1f
Compare
Previously, we only caught subclasses of Exception, however, there are
some cases when Errors are thrown instead of Exceptions. These two cases
are
assert
and when a class cannot be found.Without this change, the exception would bubble up to the
uncaughtExceptionHandler
, which would in turn, exit the JVM(related: #19923).
A note of difference between regular Java asserts and Groovy asserts,
from http://docs.groovy-lang.org/docs/latest/html/documentation/core-testing-guide.html
"Another important difference from Java is that in Groovy assertions are
enabled by default. It has been a language design decision to remove the
possibility to deactivate assertions."
In the event that a user uses an assert such as:
The GroovyScriptEngineService throws a NoClassDefFoundError being unable
to find the
java.lang.StringBuffer
class. It is highly recommendedthat any Groovy scripting user switch to using regular exceptions rather
than unconfigurable Groovy assertions.
Resolves #19806