Not all scripted queries can be safely converted to an encoded query

James Fricker
Tera Guru

I would like to point out the issue that not all scripted queries can be safely converted to encoded queries.

In this wiki article it suggests using a single encoded query instead of using a series of addQuery calls for complex GlideRecord queries.

The danger with this approach is when any of the text used to construct the encoded query is user supplied.

For example you would expect these two scripts to be equivalent, but they are not.

var gr = new GlideRecord("incident");

gr.addQuery("short_description", current.u_field);

gr.query();

var gr = new GlideRecord("incident");

gr.addEncodedQuery("short_description=" + current.u_field);

gr.query();

This is a very simple unusual example designed just to prove my point.

If the value of current.u_field is "avalue^NQanyfieldANYTHING"

then the first example above would only return incidents with that exact string as the short description.

Whereas in the second example the encoded query becomes...

short_description=avalue^NQanyfieldANYTHING

and it would return all incidents in the system

In other words, in the second example the user who entered the value of current.u_field has just successfully injected extra query terms into your code and changed its behavior.

Unfortunately there is no way I know of to escape the carat character in encoded query search values.

If you could, then you could safely create encoded query strings with user supplied text.

For example, if we could use the back slash character to escape the caret character in a search value, the encoded query above would become

short_description=avalue\^NQanyfieldANYTHING

And the addEncodedQuery method would need to know the difference between '^' and '\^'

The carat character on its own would be a search term separator, whereas backslash-carat would mean include the carat in the search string.

1 ACCEPTED SOLUTION

TylerTeter
Kilo Guru

I ran into this same issue, and had to find a solution for it. After a lot of digging, it turns out ServiceNow has a function for this!

Effectively their form of escaping is like '^' to '^^'. It's probably best practice to use this method for future expand-ability.

I haven't fully tested it to make sure it catches all special search terms (ie %*<>!= and CONTAINS, STARTSWITH, etc)... so YMMV

 

Example:

var gr = new GlideRecord("incident");

gr.addEncodedQuery("short_description=" + GlideStringUtil.escapeQueryTermSeparator( current.u_field ) );

gr.query();

 

https://developer.servicenow.com/app.do#!/api_doc?v=london&id=GSUS-escapeQTermSeparator_S

View solution in original post

9 REPLIES 9

randrews
Tera Guru

if you dumped current.u_field into a string variable you could then run a reg ex etc to parse out the ^'s etc but you would have to develop/steal your own code for types of characters to escape out...


Removal of the caret from the encoded query using a regex means the 2 versions of the code are no longer equivalent.



How do you do the following addQuery using an encoded query?



gr.addQuery("short_description", "avalue^NQanyfieldANYTHING");



Answer: you can't, because SN have not implemented a caret escaping mechanism for encoded queries.



The best you can do is remove the caret characters and that is not the same thing as escaping them. You should be able to search for any character without it breaking, and you should be able to generate a valid encoded query, for every addQuery type query. Without being able to escape the caret character that is not possible.



Try this for example...


Create an incident template, add the "Short Description" field to the template and in the value box type "test1^description=test2". Then save the template and see what happens. You will see we have managed to add the "Description" field to the template without selecting it from one of the drop-downs. If we had a mechanism to escape the caret this would not happen. How do you create a template which includes a caret in the text of one of the fields, when you can not escape the special meaning of caret?


bianca_vaccarin
ServiceNow Employee
ServiceNow Employee

It seems "^NQANYTHING" is a reserved keyword. Hence encoded query return all the records as mentioned. I am guessing this is expected functionality.




Thanks pradeepksharma for doing the digging!


^NQ in a querry strings is new querry which is a complex or condition...



so ^NQANYTHING will return all records.