Back to blog

CVE-2026-74820: how an unsanitized ORDER BY clause turned ServiceNow's AI Platform into an unauthenticated database backdoor

· · 20 min read
CVE-2026-74820: how an unsanitized ORDER BY clause turned ServiceNow's AI Platform into an unauthenticated database backdoor

On August 27, 2026, ServiceNow published a security bulletin disclosing three maximum severity vulnerabilities in its AI Platform, patched quietly across its hosted fleet before the advisory ever went public. One of the three, CVE-2026-74820, is a SQL injection reachable through a dynamic schema ORDER BY clause, and it does not require a login, a session token, or any interaction from a victim. ServiceNow rated it 10.0 on CVSS v4.0, the ceiling of the scale, and the vector string leaves nothing to interpretation: network reachable, low complexity, no privileges required, no user interaction, and high impact to confidentiality, integrity, and availability of both the platform and the data behind it. The striking part is not the score. It is that ServiceNow instances are the operational backbone of a large share of the Fortune 500, and a flaw like this sits in the query layer that every one of those instances shares, reachable before a single credential is ever checked.

This article is a two layered breakdown. The first part is written for people who need to know, in the next ten minutes, whether their organization has anything to do and what exactly. The second part reconstructs the technical chain the way a researcher auditing a dynamic query builder would approach it: where user input enters a schema aware SQL generator, why an ORDER BY clause is a particularly easy place to smuggle a payload past a filter built for WHERE clauses, and what an unauthenticated attacker can actually pull out of an instance once that gate falls. It closes by looking at how the Pragma Core platform is built to catch exactly this category of bug, the kind that lives in the relationship between an input path and a query builder rather than in any single obviously bad line.


Part I. Executive breakdown

What happened

ServiceNow's Now Platform, the engine behind its AI Platform and the vast majority of its products (ITSM, HR Service Delivery, Security Operations, and the newer AI Agent and Now Assist features), is built on a low-code data model. Administrators and applications define tables, fields, and relationships at runtime, and the platform generates SQL against those definitions on the fly rather than against a fixed, hand-written schema. That flexibility is the product's core selling point. It is also exactly where CVE-2026-74820 lives.

Somewhere in that dynamic query generation path, a value that an unauthenticated user could influence was being spliced into the ORDER BY clause of a generated SQL statement without being properly neutralized first. Think of it like a restaurant that lets any customer scribble a note on the "please sort my order by" card, and the kitchen reads that note back verbatim into its ticketing system instead of matching it against a fixed list of valid categories. Most SQL-safety training focuses on WHERE clauses and input parameters, because that is where attacker-supplied values obviously belong. An ORDER BY clause, which is supposed to accept only a column name or a sort direction, is easy to overlook, and it cannot be parameterized the normal way most database drivers support, which pushes engineering teams toward hand-rolled validation that is easy to get wrong.

The concrete result: an attacker with no ServiceNow account, hitting an exposed instance over plain HTTPS, could inject arbitrary SQL that the database would execute with the platform's own privileges, reading or altering data across the instance well beyond whatever a normal, authenticated low-privilege user could ever touch.

Who is affected

Component Status
ServiceNow AI Platform, cloud-hosted instances Patched by ServiceNow directly, no customer action required for the platform update itself
ServiceNow AI Platform, self-hosted and partner-hosted instances Vulnerable until the customer applies the update, ServiceNow supplied the fix to partners and self-hosted customers directly
Xanadu release family Vulnerable below Patch 11 Hot Fix 7a
Yokohama release family Vulnerable below Patch 12 Hot Fix 3b (or Patch 13 Hot Fix 4)
Zurich release family Vulnerable below Patch 7b Hot Fix 3 / Patch 8 Hot Fix 5 / Patch 9 Hot Fix 6 / Patch 10 Hot Fix 2m or 3 / Patch 11 / Patch 12
Australia release family Vulnerable below Patch 2 Hot Fix 3 / Patch 3 Hot Fix 2 / Patch 3m / Patch 4 / Patch 5

ServiceNow says it is not currently aware of malicious exploitation, and other advisories tracking the same disclosure report no known in-the-wild activity either. That is good news today, but it is not a durable guarantee. The advisory landed alongside two other CVSS 10.0 code injection bugs (CVE-2026-18885 and CVE-2026-18886) in the same platform, and it followed an earlier ServiceNow sandbox escape, CVE-2026-6875, that Searchlight Cyber had reported months prior and that a threat intelligence firm later observed being exploited using a payload matching the researcher's own published proof of concept. Public writeups and reproducible PoCs for one ServiceNow flaw tend to accelerate scrutiny of the platform generally, and self-hosted instances that lag on patching are the exposure that persists the longest.

Why this matters beyond ServiceNow

CVE-2026-74820 is not really a story about one vendor's schema engine. It is a story about what happens when a platform's core value proposition, letting customers and applications define their own data structures at runtime, collides with SQL's assumption that a query's shape is fixed at development time. Any low-code platform, internal admin panel, BI tool, or reporting feature that lets a user pick "sort by" from a dynamic list of fields is one incomplete allowlist away from the same bug class. The pattern shows up constantly in ORM wrappers that expose order_by or sort parameters straight from an HTTP query string, and it shows up in home-grown query builders that carefully parameterize filter values but treat the sort column and direction as "just an identifier" that does not need the same scrutiny.

Recommended actions

  1. Upgrade self-hosted and partner-hosted ServiceNow instances to the fixed hot fix or patch level for your release family (Xanadu Patch 11 HF7a or later, Yokohama Patch 12 HF3b / Patch 13 HF4 or later, Zurich Patch 7b HF3 / Patch 8 HF5 / Patch 9 HF6 / Patch 10 HF2m or HF3 / Patch 11 / Patch 12, Australia Patch 2 HF3 / Patch 3 HF2 / Patch 3m / Patch 4 / Patch 5). Cloud-hosted customers should confirm with ServiceNow that their instance received the update, rather than assume it.
  2. Inventory every ServiceNow instance your organization runs, including partner-managed and non-production instances, since test and staging environments are frequently the last to get patched and the first to be internet-exposed by accident.
  3. Review web server and reverse proxy access logs for unauthenticated requests to endpoints that accept sort, order, or field-selection parameters, particularly anomalous SQL keywords, comment sequences, or UNION-style patterns in those parameter values, covering the window back to the CVE's reservation date of August 17, 2026.
  4. If immediate patching is not possible, restrict network exposure of the instance's public-facing endpoints as tightly as your business allows, and enable any available web application firewall rule set targeting SQL injection in query and sort parameters as an interim compensating control, not a substitute for patching.
  5. Audit database-level logging for unusual query shapes, especially ORDER BY clauses containing subqueries, string concatenation functions, or conditional expressions, which is where this class of injection tends to surface in query logs even when application logs look clean.
  6. Treat this advisory as a trigger to review every other dynamic query surface in your own ServiceNow customizations, scripted REST APIs, and business rules, since custom code built on top of the platform can reintroduce the same pattern independently of ServiceNow's own fix.

Part II. Technical breakdown

Background: why ServiceNow's query layer is dynamic in the first place

The Now Platform's data model is table driven and largely defined through configuration rather than fixed application code. Administrators create tables, extend existing ones, add fields, and build relationships through the platform's UI, and every one of those definitions has to be turned into real SQL against the underlying database at request time. A list view, a report, or an AI Platform search endpoint does not run against a hand-written SELECT statement with a known, fixed set of columns. It runs against a query that the platform assembles dynamically from the current schema definition plus whatever sort, filter, and field-selection parameters the request carries.

That is a reasonable architecture for a configurable platform, but it inverts the usual assumption that makes SQL injection defenses effective. Standard guidance says: parameterize everything a user can influence, and never string-concatenate a value into a query. That guidance works cleanly for WHERE clause values, because database drivers support bind parameters for values compared against a column. It works far less cleanly for the shape of a query, the column names and sort order, because a bind parameter can supply a value to compare, but it cannot supply an identifier or a ASC/DESC keyword. A query builder that needs to let a caller pick which of several dynamically defined fields to sort by is forced to build that fragment of SQL as a string, then validate the fragment some other way, typically against an allowlist derived from the schema. CVE-2026-74820 is what happens when that allowlist-and-assembly step has a gap.

The vulnerability: unsanitized identifier passed into a dynamic ORDER BY

ServiceNow has not published the vulnerable source, which is normal practice for a SaaS platform vendor patching a critical flaw. The advisory's own description is precise about the mechanism, though: user-influenced input reaches a dynamic schema ORDER BY clause without adequate sanitization, and that lets an unauthenticated caller inject arbitrary SQL. The pattern that description describes is a well understood one in query builders that resolve a caller-supplied "sort field" against a runtime schema, and it is worth walking through in the abstract to see exactly where the gap tends to open.

A schema-aware query builder for a table-driven platform typically looks something like this, resolving a caller's sort request against the table's known fields before handing a string to the database driver:

-- Illustrative reconstruction of the vulnerable pattern, not ServiceNow's
-- actual source. Represents how a dynamic schema query builder resolves
-- a caller-supplied sort field before handing SQL to the driver.

-- 1. Caller-controlled input, taken from a request parameter such as
--    sysparm_query or an equivalent sort/order field on an unauthenticated
--    or lightly authenticated endpoint:
--       sort_field = "priority"
--       sort_dir   = "desc"

-- 2. The builder is supposed to resolve sort_field against the table's
--    live schema definition (sys_dictionary) and only then splice the
--    *resolved, known-safe* column name into the ORDER BY clause:
SELECT *
FROM   incident
ORDER BY <resolved_column> <resolved_direction>;

The intended control is the resolution step: look the caller's requested field up in the table's schema metadata, and only pass through a value that exists there. The flaw sits in how that resolution can be bypassed. In query builders of this shape, the resolution logic commonly handles the simple case correctly (a plain field name matches a schema entry and is passed through) but fails to fully re-validate compound or dotted paths used for dynamic joins across related tables, a feature the Now Platform relies on heavily for dot-walking between records. A crafted sort value that looks like a legitimate dotted field reference, but that also carries a trailing SQL fragment, a UNION, a subquery, or a comment terminator, can pass the "does this look like a schema path" check while still being concatenated into the final ORDER BY string rather than being ultimately reduced to a single validated column identifier:

-- Illustrative payload shape, not the real request. The sort field is
-- built to superficially resemble a valid dot-walked schema path while
-- carrying an injected fragment the resolver does not fully strip.
ORDER BY (SELECT CASE WHEN (<attacker predicate>) THEN priority ELSE state END)

Because the entry point sits ahead of any authentication check, on functionality exposed for anonymous access such as certain AI Platform search or lookup endpoints, the attacker never needs valid credentials to reach the vulnerable code path at all.

Root cause: identifiers are not values, and allowlists have to cover every input shape

The root cause is a validation gap, not a missing parameterization. Bind parameters, the standard fix for SQL injection in filter values, cannot be used for identifiers or sort direction keywords, so a schema-driven ORDER BY clause has to be built by resolving the caller's request against a trusted list of real column names and then emitting only that trusted value. CVE-2026-74820 shows what happens when that resolution logic has an input shape it does not fully cover: a dotted or otherwise structured field reference, used for the platform's cross-table dot-walking, that gets partially validated and then partially trusted. The minimal trigger condition is exactly what the advisory states: reach an endpoint that accepts a sort or order specification tied to a dynamic table, and supply a value shaped to pass the resolver's surface check while still carrying attacker SQL through to the final query string.

Exploitation: from a sort parameter to arbitrary data access

Once a payload survives the resolver and lands in the ORDER BY clause, the exploitation primitive is a classic SQL injection footprint, constrained to a syntactic position that expects a single expression. That still supports a full range of attacks:

That last point is what pushes the CVSS v4 vector to VC:H/VI:H/VA:H, high confidentiality, integrity, and availability impact on the vulnerable component itself, and SC:H/SI:H/SA:H, the same high impact carried into subsequent systems, since ServiceNow instances routinely hold data synchronized from HR, ITSM, and security tooling across an entire organization.

Affected versions

No CVSS v3.1 vector was published for this CVE; ServiceNow scored it under CVSS v4.0 only.

Timeline

Date Event
2026-08-17 CVE-2026-74820 reserved by ServiceNow (CNA)
2026-08-27 ServiceNow publishes the security bulletin and CVE record; fix already deployed to ServiceNow-hosted (cloud) instances
2026-08-27 Advisory ships alongside CVE-2026-18885 and CVE-2026-18886, two additional CVSS 10.0 code injection flaws in the same AI Platform
2026-08-28 CVE record updated (Vulnrichment enrichment)
2026-08-29 NVD record modified; third-party trackers and security news outlets publish independent coverage

A note on the discovery methodology

ServiceNow's advisory does not credit an external researcher for CVE-2026-74820, and the bulletin's language matches ServiceNow's own internal or vendor-partner disclosure process rather than a public bug bounty writeup. That is a meaningfully different discovery path from the sandbox escape disclosed earlier in the year, CVE-2026-6875, which Searchlight Cyber found and reported externally, then later published a proof of concept for. Internally discovered SQL injection bugs of this shape are most often found through systematic code or configuration review of query-building code paths, tracing which functions accept a caller-controlled "sort" or "order" parameter and following that value through to wherever it is concatenated into a SQL string, rather than through fuzzing a live instance from the outside. The lesson for defenders is that a platform's own vendor may find and quietly fix a bug like this well before any public researcher does, which is exactly why patch cadence, not incident response, is the primary control here.


What we should learn from CVE-2026-74820

  1. Identifiers need their own validation discipline, separate from values. Parameterized queries solve injection for values compared in a WHERE clause, but they do nothing for column names, table names, or sort directions. Any code path that builds an ORDER BY, GROUP BY, or dynamic column list from user input needs an explicit, exhaustive allowlist check against the real schema, re-applied at the point the string is emitted, not just at the point the request is parsed.
  2. Compound or structured input shapes are where allowlists break. A validator that correctly rejects a single malformed value often still accepts a compound value, like a dotted path or a JSON-shaped field selector, that only partially resembles the expected pattern. Any feature supporting nested or relational field references (ServiceNow's dot-walking, an ORM's related__field syntax, a GraphQL-style field path) deserves its own dedicated test suite for injection, distinct from the tests covering simple flat inputs.
  3. Unauthenticated reachability multiplies the blast radius of every other bug. The same ORDER BY flaw behind a login would still be serious, but it would require a valid low-privilege account first. Any endpoint intentionally exposed without authentication, for search, lookup, or public-facing widgets, deserves the highest bar for input handling precisely because there is no compensating access control layered in front of it.
  4. A platform's core flexibility is usually also its highest-risk surface. Low-code and configuration-driven platforms sell dynamism as a feature, but every place that dynamism touches SQL generation, permission evaluation, or serialization is a place where the normal static assumptions engineers rely on (fixed schema, fixed query shape, fixed set of valid inputs) stop holding, and needs review proportional to how much flexibility it grants.
  5. Response-based inference channels (timing, ordering, boolean differences) do not require a visible error message to be exploitable. Defenders who test for SQL injection by looking for stack traces or database error strings in responses will miss this entire class, since a working exploit here can be built purely from how row order or response latency changes, with the application returning a perfectly normal-looking page every time.

How Pragma Core addresses this class of problem

Pragma Core is built for exactly the failure mode behind CVE-2026-74820: a bug that is not one obviously bad line, but a relationship between an entry point, a resolver function, and a query builder several calls downstream, where each individual piece looks reasonable in isolation. Classical SAST tools tuned to flag string + userInput next to a db.execute() call routinely miss this, because the injection point here is a sort parameter passed through a schema resolver, not a raw concatenation into a WHERE clause.

Autonomous AI agents for attack chain investigation

Pragma Core's autonomous agents reason over the full path a value travels, not just the line where it is used. Pointed at a dynamic query builder, the agent would ask the exact question that surfaces this bug: does every input shape this sort-field resolver accepts (flat names, dotted paths, computed expressions) get reduced to a single validated column identifier before it reaches string assembly, or does one shape slip through with a weaker check than the others?

Interactive call graphs with vulnerability overlay

The bug in CVE-2026-74820 hides in the relationship between an unauthenticated endpoint, a schema resolver, and a SQL string builder, three components that each look safe read in isolation. Pragma Core's auto-generated call graphs visualize exactly that relationship for a connected repository, overlaying where untrusted request parameters flow into query-construction functions, so a reviewer can see at a glance which sort or order parameters reach a raw SQL string without passing through a hard allowlist first.

SAST tuned for the relevant pattern, not just injection sinks

Off-the-shelf static analysis is tuned to flag concatenation directly into a query string, and it is comparatively blind to a resolver-based allowlist that has an incomplete branch for compound identifiers. Pragma Core's static analysis can be tuned to that specific pattern, identifier resolution with an incomplete input-shape check ahead of a dynamic ORDER BY or GROUP BY, and surface it as a high-confidence finding rather than relying on a human to notice the missing branch during review.

White-Box Pentest

Because this flaw is unauthenticated and reachable purely through crafted request parameters, it is squarely the kind of issue Pragma Core's source-assisted pentesting is designed to chase: an AI agent that reads the actual resolver code alongside probing the live endpoint can construct the exact compound sort-field shape that bypasses validation, rather than relying on generic SQL injection payload lists that target WHERE clauses and miss ORDER BY-position injection entirely.

Human-guided AppSec investigations

The kind of systematic review that most plausibly found CVE-2026-74820, tracing every function that accepts a "sort" or "order" parameter through to its eventual SQL string, is exactly what Pragma Core's expert-led research module is built to run at scale, with an AppSec operator directing autonomous agents against a team's own dynamic query surfaces rather than waiting for a vendor advisory to prompt the search.

Continuous tracking of third-party packages

Organizations running ServiceNow as a dependency of their broader stack, whether as the platform itself or via connectors and integrations built on top of it, would have this component's CVSS 10.0 rating and fixed-version path surfaced by Pragma Core's dependency tracking the moment the CVE entered its catalog, closing the gap between an advisory's publication and a security team actually noticing it applies to them.


Closing thoughts

CVE-2026-74820 is not, fundamentally, a bug about ServiceNow's ORDER BY clause. It is a bug about the gap between validating a value and validating a shape: an allowlist that correctly handles the simple case it was written for, and quietly trusts a more complex case it was never explicitly tested against. That same gap lives in any system that resolves user input against a dynamic schema before building a query, a report, or a permission check, from low-code platforms to ORMs to home-grown admin tools, and it will keep reappearing under a different vendor name and a different CVE number until teams start testing identifier-resolution logic with the same rigor they apply to value sanitization.

The same pattern lives in a lot of modern architectures, and the difference between reading this as a curiosity and using it as an audit trigger for your own dynamic query surfaces comes down to AppSec maturity and code visibility. Organizations that want to move from "we scan and report" to "we systematically investigate what is fragile" can reach Pragma Core at pragma-core.com for a demo.


Sources

Related posts
CVE-2026-85978: how one path normalization mismatch turned Akana's admin console into unauthenticated remote code execution
Sep 9, 2026
CVE-2026-78174: how an unredacted session token in a diagnostic log turned a low-privileged WatchGuard Dimension admin into super admin
Sep 1, 2026
Qwen 3.8 27B and the year the open weights caught up: how a 17GB download started beating the frontier
Aug 19, 2026

Start securing your codebase today

Connect your repositories and let AI agents handle continuous scanning, research, and triage.

Have questions? Get in touch →