CVE-2026-97058: 
Grafana vulnerability analysis and mitigation

Overview

CVE-2026-97058 is a Denial of Service vulnerability in the sprintf-js JavaScript library (versions through 1.1.3) caused by improper validation of precision specifiers in format strings. The library passes unbounded precision values directly to ECMAScript's toFixed(), toExponential(), and toPrecision() methods without range checking, causing uncaught RangeError exceptions that can crash the calling Node.js process. The vulnerability was publicly disclosed on September 16, 2026 via a GitHub issue, with CVE assignment and NVD publication on September 24, 2026. It carries a CVSS v3.1 score of 5.3 (Medium) and a CVSS v4.0 score of 6.9 (Medium) (GitHub Issue, Red Hat Advisory, Red Hat Bugzilla).

Technical details

The root cause is classified as CWE-1284 (Improper Validation of Specified Quantity in Input) and CWE-248 (Uncaught Exception). In src/sprintf.js at line 17, the placeholder regex captures the precision field with an unbounded group (\d+) and stores the raw string value without any numeric range validation. At lines 84, 87, and 90, this unvalidated precision is passed directly to parseFloat(arg).toExponential(ph.precision), parseFloat(arg).toFixed(ph.precision), and Number(arg).toPrecision(ph.precision) respectively — none of which are wrapped in a try/catch block. ECMAScript mandates that toFixed and toExponential accept only 0–100, and toPrecision accepts only 1–100; any value outside these ranges throws a RangeError. Additionally, the %g branch tests truthiness of the string ph.precision, meaning "0" is truthy and forces toPrecision(0), which always throws. A minimal ~6-byte payload such as %.101f deterministically triggers the exception (GitHub Issue, sprintf.js source).

Impact

The primary impact is availability loss (Denial of Service) with no confidentiality or integrity impact. When sprintf() is invoked from an asynchronous handler — the common pattern for i18n template rendering — the uncaught RangeError propagates to the Node.js event loop, and Node's default policy terminates the entire worker process with exit code 1, dropping all concurrent and subsequent requests. In synchronous call sites where the caller wraps sprintf() in a try/catch, the impact is limited to a failed individual request (HTTP 500). The attack requires negligible CPU and memory resources, bypassing size-, memory-, and duration-based defenses, and a single malicious request can take down an entire worker (GitHub Issue).

Exploitability

A public proof-of-concept (PoC) is available in the GitHub issue that originally disclosed the vulnerability, demonstrating process termination with a standalone JavaScript script requiring no external infrastructure (GitHub Issue). The vulnerability is network-exploitable, requires no authentication, no user interaction, and no special preconditions beyond the attacker controlling or influencing the format string argument passed to sprintf(). The EPSS score is 0.00366 (~0.37%), indicating low but non-negligible probability of exploitation in the wild. No active in-the-wild exploitation has been observed, and the vulnerability is not listed in the CISA KEV catalog. No threat actor attribution is available (Red Hat Advisory).

Exploitation steps

  1. Identify target: Locate a Node.js application that uses sprintf-js version ≤ 1.1.3 and exposes an endpoint where attacker-controlled input influences a format string passed to sprintf() — common in i18n/template rendering, logging, or API response formatting.
  2. Craft malicious payload: Construct a format string containing an out-of-range precision specifier, such as %.101f, %.101e, %.101g, or %.0g. These are minimal (~6-byte) payloads that deterministically trigger the vulnerability.
  3. Deliver the payload: Submit the malicious format string via the attacker-controlled input channel (e.g., HTTP request parameter, stored template, i18n catalog entry, or API field) so it reaches the sprintf() call.
  4. Trigger RangeError: The library's sprintf_parse function captures the precision 101 without validation; sprintf_format then calls parseFloat(arg).toFixed(101) (or equivalent), which throws RangeError: toFixed() digits argument must be between 0 and 100.
  5. Crash the process: Because no try/catch wraps the Number method calls and no uncaughtException handler is installed, the RangeError propagates to the Node.js event loop, terminating the entire worker process with exit code 1 and dropping all concurrent requests (GitHub Issue).

Indicators of compromise

  • Logs: Node.js process crash logs or stderr output containing RangeError: toFixed() digits argument must be between 0 and 100 (or toExponential/toPrecision variants) with a stack trace originating in sprintf-js/src/sprintf.js at lines 84, 87, or 90.
  • Logs: Application or web server logs showing sudden worker process termination (exit code 1) correlated with specific incoming requests containing format-string-like patterns (e.g., %.101f, %.101e, %.0g).
  • Network: HTTP requests containing format string precision specifiers (e.g., %.101f, %.NNNf where NNN > 100, or %.0g) in query parameters, POST body fields, or headers that are passed to template/i18n rendering functions.
  • Process: Unexpected Node.js process restarts or worker crashes in process managers (PM2, systemd, Docker) with non-zero exit codes, particularly if recurring and correlated with specific request patterns (GitHub Issue).

Mitigation and workarounds

Upgrade sprintf-js to a version newer than 1.1.3 once a patched release is available; a patch has been identified (GitHub Advisory, Red Hat Bugzilla). As an immediate workaround for consumers, never pass attacker-influenced strings as the format argument to sprintf(); wrap all sprintf() calls on untrusted format strings in a try/catch block to prevent uncaught exceptions from reaching the event loop. Additionally, implement input validation to restrict format string precision specifiers to values within valid ECMAScript limits (0–100 for toFixed/toExponential, 1–100 for toPrecision) before passing them to the library. Installing a global uncaughtException handler in Node.js can prevent full process termination but does not fix the underlying vulnerability (GitHub Issue).

Additional resources

Linux Distribution fix status

Fix availability across major Linux distributions and their releases.

Ubuntu

Unknown

bionic (esm-apps)

node-sprintf-js

Unknown

devel

node-sprintf-js

Unknown

focal (esm-apps)

node-sprintf-js

Unknown

jammy

node-sprintf-js

Unknown

jammy (esm-apps)

node-sprintf-js

Unknown

noble

node-sprintf-js

Unknown

noble (esm-apps)

node-sprintf-js

Unknown

resolute

node-sprintf-js

Unknown

RHEL / CentOS

Affected

OpenShift

openshift4/ose-console

Affected

RHEL 8

389-ds:1.4/389-ds-base.src

Affected

RHEL 9

389-ds-base.src

Affected

RHEL 10

389-ds-base.src

Affected

Source: This report was generated using AI

Related Grafana vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-102990HIGH8.2
  • JavaScript logoJavaScript
  • rust-std-static
NoYesSep 30, 2026
CVE-2026-13720MEDIUM5.4
  • Grafana logoGrafana
  • grafana-selinux
NoYesSep 30, 2026
CVE-2026-81841MEDIUM5.3
  • Grafana logoGrafana
  • cpe:2.3:a:grafana:grafana
NoYesSep 29, 2026
CVE-2026-13719MEDIUM4.3
  • Grafana logoGrafana
  • cpe:2.3:a:grafana:grafana
NoYesSep 30, 2026
CVE-2026-81842MEDIUM4.3
  • Grafana logoGrafana
  • grafana-cloudwatch
NoYesSep 29, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management