-
Notifications
You must be signed in to change notification settings - Fork 850
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
Allow freezing of NativeJavaObject
and subclasses
#1541
Conversation
Rhino allows to invoke `Object.freeze` for any `ScriptableObject`, but does not allow it for `NativeJavaObject` and its various subclasses. Furthermore, there is no Java API that can be invoked to obtain that effect. This commit adds a new API `NativeJavaObject::freezeObject` and allows `Object.freeze` to work with all implementations of `NativeJavaObject`.
Just some random questions:
@rPraml as you've done a lot in the area of Java interop: any thoughts on this PR? Am also wondering how this PR related to #1085 (if at all) |
At the moment they are "modifiable" in the sense that you can do
Not sure what that is; can you give me some pointers?
Not sure, but for |
Info about sealed (shared) scopes be be found here #1085 has been stuck indeed, but that is due to not having a clear-cut direction to proceed:
Given all of the above, I'm not sure if the approach taken in this PR is the best approach to take for the long term. Like to get some other opinions...
Assume this also goes for there being a public getter/setter pair on the Java class? |
This PR implements also a java API to freeze a
That doesn't really apply to this PR, because this one only touches
Yes, I know they don't work. These objects also don't have parent or prototype. So, while you cannot mark a single property as
IMHO this PR is not trying to be a big revolutionary change in freezing stuff. It's just a small enhancement to allow to also freeze the
Yeah, or a public field. And you cannot mutate methods. |
Related to the getter/setter methods, I don't think it's possible to prevent called java methods from mutating fields. A javascript function that performs But a java method will mutate fields as it sees fit, even if the var l = new Packages.java.util.ArrayList()
l.add('abc')
Object.freeze(l);
l[0] = 'def'; What is preventing someone from doing this after the object is frozen? l.set(0, 'def') I'm not sure if it should mess with NativeJavaMap either. Freezing an object which is an instance of a javascript Map does not prevent you from setting values in the map, it only prevents you from setting properties on the object. With a javascript Map, var m = new Map()
m['a'] = 1 // sets a property on the object
m.set('a', 2) // assigns a value to a key in the map
Object.freeze(m)
m['a'] = 3
m.set('a', 4)
assert(m['a'] === 1) // because the object was frozen when attempting to set to 3
assert(m.get('a') === 4) // not affected by the freeze Your test case requires that I'm sure someone could also get around the measures you are putting in place for actual fields using java reflection. I'm curious what the use case is for wanting to freeze a java object? |
In our case, we don't have setter, but public fields. This PR fixes mutations of them.
Agreed, there's not much I think we can do about this.
We have a sandbox environment where we want to prevent modifications to the java objects that we expose (because some clever people have found security problems by mutating them). |
I think I have a problem with the I think the The rest of the changes are probably fine, but I don't think they'll actually solve your problem. Most java classes are written with public accessor and mutator methods and private fields, so they'll bypass the freeze without even trying. A motivated user with access to java can also use java reflection to set public and private fields. If you have specific objects to which you are giving the user access which you want to protect, the best solution I can think of would be to create custom Scriptable objects which wrap those java objects and provide a public API for your users so they don't have direct access to them. I am on the fence about putting in changes that "freeze" java objects, when it is clearly only a half-measure which is trivial to circumvent, and it is impossible to fully freeze them. |
@rPraml any thoughts on this one, given that you/your team seems to use Java Interop-related in Rhino a lot |
Like @tonygermano I'm a bit on the fence on this one as well It sounds like you control the the code to some extent of you would be able to call freeze on the NativeJavaObject instances before an untrusted (user-provided) js code wood be able to interact with it If so, other strategies may be better, like instead of direct access to Java classes, just expose custom wrappers, existing just those methods/properties you want exposed. Or make the Java classes you want your users to have access to to implement Scriptable and use annotations to tell Rhino what to expose and how How feasible the suggestions are in your Rhino integration I cannot know, but given the limitations of the proposed freezing option, it might be a more viable way forward |
Sorry, I missed the mention. I'll try to summarize, what we have now:
The difference between freeze and seal is, that seal allows to write to existing properties, as long as they are writeable. Both do currently only work on ScriptableObjects, if language level is at least EcmaScript 6.
I'm unsure if Can you describe your exact use case? Do you want to protect objects passed into the rhino engine? |
Closing because I don't think there's a consensus on this one. 🙂 |
Rhino allows to invoke
Object.freeze
for anyScriptableObject
, but does not allow it forNativeJavaObject
and its various subclasses. Furthermore, there is no Java API that can be invoked to obtain that effect. This commit adds a new APINativeJavaObject::freezeObject
and allowsObject.freeze
to work with all implementations ofNativeJavaObject
.