- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 10-04-2021 11:11 AM
Hi everyone,
I had an issue today with getting the user's group ( simple gs.getUser().isMemberOf('<group name here>') ) from Catalog UI Policy. As I suspected, g_user doesn't have that and there was no other easy way to do it (everything else seemed not a good idea in my case) so I had to use AJAX. But when I gave it a little thought, I ended up thinking that this will happen again for something else. It took me a while but now you can pass any piece of code you want to be executed in the server side and get the result. Like I said, the example is for Catalog UI Policy, checking if the user is part of a group.
Of course, you can use this in any client side JS, passing any GS method - gs.now(), etc. - in gereral everythign that works only on the server side.
Hope this will help you if you encounter similar as mine situation.
Reference to my question asked :
https://community.servicenow.com/community?id=community_question&sys_id=1a0044341bcf3c14acdc54e56b4bcbd1
Catalog UI Policy:
function onCondition() {
var ga = new GlideAjax('ServerHelperUtilsAJAX');
ga.addParam('sysparm_name', 'runServerScript');
ga.addParam('sysparm_script', "gs.getUser().isMemberOf('admin')");
ga.getXML(callback);
function callback(response) {
var answ = response.responseXML.documentElement.getAttribute("answer");
if(answ == "true"){
answer = true;
} else {
answer = false;
}
//For testing. Uncomment if you need the result
//g_form.addInfoMessage("ServerHelperUtilsAJAX returned " + answ);
}
}
AJAX Script Include:
var ServerHelperUtilsAJAX = Class.create();
ServerHelperUtilsAJAX.prototype = Object.extendsObject(AbstractAjaxProcessor, {
/*
* To add delegation filter to glide encodedQuery
* @input: server script to run as string (i.e. gs.getUserID())
* @output: string
*/
runServerScript: function(){
var myScript = this.getParameter('sysparm_script');
var result = new ServerExecuteHelper().runScript(myScript);
return result;
},
type: 'ServerHelperUtilsAJAX'
});
Script include
var ServerExecuteHelper = Class.create();
ServerExecuteHelper.prototype = {
initialize: function() {
},
/*
* To add delegation filter to glide encodedQuery
* @input: server script to run as string (i.e. gs.getUserID())
* @output: string
*/
runScript: function(func){
var res = new Function("return " + func);
return (res());
},
type: 'ServerExecuteHelper'
};
- 4,124 Views

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Well, you just opened pandora's box by allowing every one (even without admin rights) to run arbritary scripts on the server. Imagine a skilled employee running something like "gs.setProperty('my very important property', 'any value helping the employee to make life easier for him or attack the company');" through the console functionality of the browser.
This is a wonderful example of a specific problem being solved too general.
Also your formulation of runScript is just a rarely seen workaround to prevent eval(...) to be found in your source code -- it just really does the same. There is a good reason that in the current implementation of ServiceNow just GlideScopedEvaluator allows to interprete user-entered JavaScript sources (and only if they are stored in a field of a GlideRecord). I have it already in my security check-list.
There are some solutions though:
- provide a client-side wrapper for the specific functions you want to call (like a AJAX version just for the isMemberOf function); if you want to expose the whole user object gs.getUser() returns, you could prefix it in your eval-equivalent but you would have to mess around to make sure the script is clean of any other harmful script. Most secure way is to expose the needed functions only by an AJAX equivalent. This is the way ServiceNow, Inc. itself deals with the problem in many cases.
- use g_scratchpad if possible (like here https://community.servicenow.com/community?id=community_question&sys_id=af0ccb25db9cdbc01dcaf3231f96191b), in this case maybe on catalog item level
- you could write a UI Macro that renders all client-side needed information into a client-side script like
<g:evaluate> var imo = isMemberOf('groupname'); </g:evaluate>
<script type="text/javascript"> var isMemberOfGroup = ${JS:imo} </script>
The macro could be included as a macro variable (you need to check in the UI Policy if the variable isMemberOfGroup is already existing!).
If you are in a Portal, you could use an approach as presented here:
https://community.servicenow.com/community?id=community_blog&sys_id=e60eea2ddbd0dbc01dcaf3231f961972
Best Regards,
Ben
- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
You are absolutely correct, but with GlideScopedEvaluator I need to use extra field (there was some workaround with that , but I wasnt able to recall it) in order to execute the script. And yes, this is in general eval() done in another way - as eval() won't work anymore, but this should be ok as it's part of the JS syntax. Funny thing is that this is used for UI Policy . I might end up doing allowed functions and not everything as your point is way too valid.
Thanks for the input!
Cheers,
Joro

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Yeah I think if you just create a GlideRecord object from a respective table (without .insert()-ing or .update()-ing it) and setting a/the script field before passing it into the Evaluator, you potentially could work around that.
Nevertheless, regardless of Glide(Scoped)Evaluator, eval, or any eval-equivalent: if you need to run code on server that is transferred from a client, you should always revise your solution, because basically anyone could send code to the server (any client-side check can be bypassed).
And it wasn't about if your eval-equivalent is syntactically okay, it was the fact that your solution uses something like eval. The use of eval (or anything alike) should always be prevented, especially when it processes basically user input, as it always has the potential of a Code Injection vulnerability (there are very very rare, very very minor exceptions).