Skip to content

Conversation

youngj
Copy link
Contributor

@youngj youngj commented Jun 28, 2021

As discussed in #911, currently, if a script catches an error that originated from a native Java Exception, Rhino exposes an error object to the catch block with a message like "JavaException: java.lang.RuntimeException: exception message".

However, users running JavaScript code via systems using Rhino do not necessarily know that their JavaScript code is being executed with Rhino/Java, so it's confusing that some error messages are prefixed by "JavaException: (Java class name):". I'd like some way to avoid exposing these implementation details to the user, but it currently doesn't seem possible to override this behavior, which is implemented in the static function ScriptRuntime.newCatchScope.

This PR implements one possible way to override this behavior, by adding a feature flag to the ContextFactory. If the feature flag Context.FEATURE_HIDE_WRAPPED_EXCEPTIONS is set, the error message will hide the Java implementation details, and the exception message would look like "InternalError: exception message".

Possible alternative approaches:

  • change the behavior for everyone, since it doesn't appear that any tests rely on the old behavior
  • create a new method in the Context class to generate the message for a Java exception, allowing a custom ContextFactory subclass to return a custom Context subclass that could override that method

Closes #911

@tonygermano
Copy link
Contributor

I think the feature flag is a good approach for this. I run Rhino in an environment where users are aware they are running on Java, and frequently utilize Java libraries in their scripts, so I would not want to lose the current behavior, as it helps with troubleshooting.

@gbrail
Copy link
Collaborator

gbrail commented Jun 29, 2021 via email

@youngj
Copy link
Contributor Author

youngj commented Jun 29, 2021

Sounds good to me. This PR currently names the feature flag FEATURE_HIDE_WRAPPED_EXCEPTIONS and it is only used when JavaScript code catches an exception thrown by Java code. Potentially there could be other parts of Rhino that expose Java/Rhino implementation details to JavaScript code as well. What would be a good name for this feature flag? Could this feature flag be used to hide other Java/Rhino implementation details?

@p-bakker
Copy link
Collaborator

Wondering if you are also already disabling stuff like:

  • Packages
  • direct access to classes via org/java/com.xxxxx
  • JavaImporter
  • etc.

Just wondering if this calls for yet another, quite specific flag or if there's some other way we can be clever about this. For example only include the Java Exception details if the above stuff is also initiated

@youngj
Copy link
Contributor Author

youngj commented Jun 30, 2021

Good idea. We're already using Context.setClassShutter to hide all Java classes:

cx.setClassShutter(new ClassShutter() {
    @Override
    public boolean visibleToScripts(String className)
    {
        return false;
    }
});

so we could use ScriptRuntime.isVisible without adding a new ContextFactory flag:

                if (!isVisible(cx, javaException)) {
                    type = TopLevel.NativeErrors.InternalError;
                    errorMsg = javaException.getMessage();
                } else {
                    type = TopLevel.NativeErrors.JavaException;
                    errorMsg =
                            javaException.getClass().getName() + ": " + javaException.getMessage();
                }

Thoughts?

@p-bakker
Copy link
Collaborator

p-bakker commented Jun 30, 2021

If you're not exposing any classes (visibleToScripts always returning false), how are you initializing your standard objects?

Because if you go through ScriptRuntime.initSafeStandardObjects (and never through ScriptRuntime.initStandardObjects), isn't the ability to access Java Classes disabled completely (without having to implement the classShutter)?

My idea was to only enable the Java Exception details inside JavaScript when the init was done through ScriptRuntime.initStandardObjects, which enables Java class access, so it would make sense to then also have access to the Java Exception details

Not sure if this would work for you and what others think about this approach

@gbrail
Copy link
Collaborator

gbrail commented Jun 30, 2021

This seems like a pretty handy feature to me and looks good. But I'll see if others have opinions on the alternative approach that's being suggested for a day or so.

@youngj
Copy link
Contributor Author

youngj commented Jun 30, 2021

Because if you go through ScriptRuntime.initSafeStandardObjects (and never through ScriptRuntime.initStandardObjects), isn't the ability to access Java Classes disabled completely (without having to implement the classShutter)?

We use initSafeStandardObjects, but the ClassShutter is still used in ScriptRuntime.newCatchScope to avoid making the Rhino-specific properties javaException, rhinoException, and __exception__ available within the JavaScript catch scope.

@gbrail
Copy link
Collaborator

gbrail commented Jul 2, 2021

This looks good to me. If no one else has any objections I'll merge it soon.

@gbrail gbrail merged commit e721bb4 into mozilla:master Jul 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Hiding Java exception implementation details from catch block
4 participants