How to clean SSJS in Domino server after someone used javascript prototype in a nsf?
Asked Answered
S

2

11

How to clean SSJS (Server Side Javascript) in Domino server after someone used javascript prototype in a nsf?

Mark Roden discovered a huge weakness in XPages SSJS: (thanks to David Leedy for tell me about this and show me the article).

If you have the following SSJS code:

var dummyObj = {}
dummyObj.prototype.NAME = "Johann"

XPages SSJS doesn't care that you uses var (var means the variable must be local) and it makes dummyObj.NAME visible in the whole server with the value Johann. So if another nsf in the same server uses a var with the same name it inherits the whole prototype:

var dummyObj = {}
println(dummyObj.NAME) /*prints "Johann" */ 

This is a huge bug (one that makes unreliable XPages SSJS IMO). Even if you don't use prototype at all, if someone else in his application do something like this:

String.prototype.split = function(){ return "I broke this method" }

It will broke all applications in the same server that uses the innocent split().

So, the question is: if someone "by mistake" writes the following SSJS (XPages Server Side Javascript) in a NSF:

String.prototype.split = function(){ return "I broke this method" }

How can I fix String.prototype.split() to his original value?

As Mark Roden said, restarting HTTP task doesn't fix it.

///////////////////////////////////////////////////////////

Edit 1: Why I think this is a huge bug:

I'm a Javascript fan but IMHO @MarkyRoden has discovered a huge bug in SSJS. Shims and polyfills aren't really the main problem. Eval is known to be a bad practice but the prototype object is a fundamental element of basic Javascript. It's the standard and preferred way to add methods to Javascript classes, it's also needed for inheritance and all kind of OOP stuff. So you will need some kind of namespace at server level in order to avoid collisions. All this is really bad but the huge problem is that just a line of code in one application can broke all applications in a server. Yes, you can trust in your developers but one of them can write a bad line by mistake and also a Domino server can have hundreds of applications from different software vendors. Set the responsability in code reviews is not a reliable enought procedure. Maybe it's time to have a real javascript engine in SSJS, like V8, Spidermonkey, Chakra or Rhino. As a workaround, I'm thinking in something like Tommy Valand's idea with Rhino in SSJS.

Edit 2: It's even worse. You can do things like:

prototype.importPackage = null

or

prototype.Array = null

As you can see in @SvenHasselbach's article: http://hasselba.ch/blog/?p=1371

Edit 3: IBM: you told me I could use SSJS. COME ONE! PLEASE FIX THIS, it's AWFUL. Please let's officially report this issue to IBM.

Sulfathiazole answered 2/11, 2014 at 2:30 Comment(4)
Regarding your EDIT comments. I think the key takeaway is that SSJS is NOT "true JavaScript". So you need to manage your expectations of SSJS accordingly. Especially with OOP. You can't really do objects in SSJS. If you put code in your functions then they're not Serializable. Honestly I believe that the real workaround is to use Java rather then SSJS.Leanneleanor
It's one more reason to you use as much as possible Java and EL in XPages development instead of SSJS.Desuetude
I agree with Knut and David. Consider also what Jesse Gallagher did some years ago to enable you to code Ruby in XPages: XPages is a JSF-based platform, running in a Java Virtual Machine, so to enable people to code Ruby, Jesse had to write a parsing engine to allow Java to parse Ruby. The Rhino parser is doing the same thing - it's using a Java class to tell Java how to parse Rhino. So unless I'm misunderstanding things, you can't have a real javascript engine in SSJS, because you'll be using a Java parser for that javascript engine. Debugging may also be a challenge.Hobbledehoy
I would strongly discourage anyone trying to use String.prototype to fix deficiencies in the core APIs (JavaScript or Java). There are a myriad of Java classes designed to add missing functionality in Java (and so SSJS). com.ibm.commons.util.StringUtil is in-built with XPages. With some workarounds you can add in org.apache.commons.lang.StringUtils intec.co.uk/two-java-libraries-to-know-for-xpages-development. importPackage() allows you to use any Java class in SSJS as long as it's accessible to the server.Hobbledehoy
A
8

You can reset the SSJS interpreter with the following Java code:

FacesContextExImpl fc = (FacesContextExImpl) FacesContextExImpl.getCurrentInstance();
UIViewRootEx2 uiRoot = (UIViewRootEx2) fc.getViewRoot();
JSContext jsContext = uiRoot.getJSInterpreter().getJSContext();
jsContext.getRegistry().init(jsContext);

This reinitializes the registry and all prototype functions.

EDIT: Changed the declaration of fc to the correct type.

EDIT 2: Here is the SSJS version:

var uiRoot = facesContext.getViewRoot();
var jsContext = uiRoot.getJSInterpreter().getJSContext();
var reg = jsContext.getRegistry();
reg.init( jsContext );

Does I understand you correctly, that you want to clean up the SSJS interpreter to avoid a collision with your own prototype extension? Just to clarify the answer above: This reinitializes the SSJS interpreter once. And only once. You have to do this over and over again, because directly after reinitializing, another application on the server can overwrite the prototype functionality again. That's why this is not a real solution, it is an answer to your initial question.

It will have interessting consequences if another application will do the same while your code tries to use your extension...

Adelric answered 3/11, 2014 at 14:36 Comment(10)
In fact, it will affect every application the same way restarting http task does. IMO code review is the only safe way to avoid the problem (I do not expect IBM to fix it anytime soon - no SPR, no fix ).Brack
@FrantisekKossuth: No, this can be done during runtime. When the server is restarted, everything is lost (session data, authentication etc.). But to be safe, this has to be done over and over again. The only way which really prevents problems is not to use SSJS.Adelric
You are right, restart will wipe much more data. My point is: application may loose "state" stored in context and malfunction the same way.Brack
@FrantisekKossuth: What do you mean with "context"? Scoped Variables etc. are not affected...Adelric
@Sven Nice! This could be a good workaround. I'd like to use your code on top of my SSJS pollyfills: gist.github.com/katio/08bf3f5e058b950cd957. I tried: importPackage( com.ibm.xsp.context); var fc:FacesContext = FacesContextExImpl.getCurrentInstance(); var uiRoot:UIViewRootEx2 = fc.getViewRoot(); var jsContext:JSContext = uiRoot.getJSInterpreter().getJSContext(); jsContext.getRegistry().init(jsContext); But I get the error: "Script interpreter error, line=2, col=28: Ambiguity when calling getCurrentInstance() and getCurrentInstance()". Am I importing the right package?Sulfathiazole
Johann - I would not consider this as much as a "workaround" as it is a good "defense" mechanism. The best "workaround" for this is just moving the logic to Java itself. It is so much better then SSJS and you can do real custom objects which you can't do in SSJS as well.Leanneleanor
@David I know there is some kind of JAVA vs SSJS opinions here. I know Java is faster in XPages and SSJS is a second class citizen in Domino but I really like Javascript notation and it's elegant and modern features like Lambda expressions. Java only added Lambda expressions in Java 8. I don't have Java 8 in Domino 8.5.3 so moving several applications to Java would be really awful. I have to protect my current SSJS applications. And Sven's idea sounds promising.Sulfathiazole
@SvenHasselbach I'm in trouble, I tried the SSJS above & also tried in a Java: package com.ssjspatch.ssjspat; import javax.faces.context.FacesContext; import com.ibm.xsp.context.FacesContextExImpl; import com.ibm.xsp.component.UIViewRootEx2; import com.ibm.jscript.JSContext; public class ssjsfix { FacesContext fc = (FacesContextExImpl) FacesContextExImpl.getCurrentInstance(); UIViewRootEx2 uiRoot = (UIViewRootEx2) fc.getViewRoot(); JSContext jsContext = uiRoot.getJSInterpreter().getJSContext(); jsContext.getRegistry().init(jsContext); } error on token "getRegistry", Identifier expectedSulfathiazole
Johann - I wasn't trying to start the whole Java vs. JavaScript debate again. I don't know what a "Lambda expression" is and I don't care that Java might be technically a microsecond faster then SSJS. Just look at the problem in front of you. If you get past this then what's next? SSJS is not true JavaScript. It's, I believe, an OLD version of EcmaScript that's been customized and is limited. We'll likely get a new JVM before we get an upgrade to SSJS. I humbly suggest that since XPages is Java, and you can clearly handle Java, that might be the best overall solution for you in the long run.Leanneleanor
@SvenHasselbach & David Thank you. You're right, this is not a fix :( but answer my question. It works Ok with the SSJS version. Fredrik Norling also answered my question but your answer is better because I don't need to restart the http task. If someone run: prototype.importPackage = null We must execute the Java version. How would you do this? Using a Java design element? A Java library? A Java agent? I'm having problems executing the Java version. I should be missing something simple. Details in my comment above.Sulfathiazole
S
3

try to do a Restart Task Http instead tell http restart will not do a full restart of the http task

Systaltic answered 2/11, 2014 at 11:48 Comment(7)
Restart Task Http cleans all prototypes. Nice!. But what to do when the bad application with the bad prototype code is executed again? How can I protect my XPage Application against this? I'm very worried about this. It's a huge bug. IBM really should fix it. If there is no solution for this, how can anybody keep trusting in XPages SSJS?Sulfathiazole
It is not a bug IMHO it is an unfortunate feature of the way that SSJS is implemented. I trust SSJS, developers not so. So I would discourage you from using the shim and don't encourage others to use prototype I am afraid - sorry :(Isolationist
@JohannEchavarria: You can not trust SSJS. It is broken by design when lookig at it for security reasons. But this does not mean that you cannot use it in a "trusted environment": The admins have to look at the bad fragments, and have to shoot the developers which overwrites internal functions (it is more than just the "prototype" thing). And using of "eval" is a no-go too.Adelric
@Isolationist & Sven: I edited my question and added why I think this is a huge bug.Sulfathiazole
How could an admin even really detect that someone's using "prototype"? should they do a code scan for that specifically? I'll go out on a limb here and suggest that this might be another good reason to prefer Java over SSJS for XPages Business Logic....Leanneleanor
@DavidLeedy: sure, they should scan for this. It is a huge problem, because IT can affect other applications on a server. See hasselba.ch/blog/?p=1371. And yes, you can override other functions...Adelric
@SvenHasselbach "Wanna have a lot of fun in the office?" lol. I just read your article. Nice and funny. hasselba.ch/blog/?p=1371Sulfathiazole

© 2022 - 2024 — McMap. All rights reserved.