Back to Blog
high SEVERITY8 min read

How Denial of Service happens in Node.js devalue and how to fix it

A high-severity Denial of Service vulnerability (CVE-2026-22774) was discovered in the `devalue` package used by the exo-dashboard SvelteKit application. Attackers could craft malicious input to trigger excessive resource consumption in the devalue deserialization library, potentially taking down the web service. The fix upgrades `devalue` from version 5.5.0 to 5.6.2 in both `package.json` and `package-lock.json`.

O
By Orbis AppSec
Published June 25, 2026Reviewed June 25, 2026

Answer Summary

CVE-2026-22774 is a Denial of Service vulnerability (CWE-400) in the `devalue` npm package versions prior to 5.6.2, affecting Node.js/SvelteKit applications. When untrusted input is passed to devalue's deserialization routines, an attacker can trigger excessive resource consumption — CPU or memory exhaustion — causing the service to become unresponsive. The fix is to upgrade `devalue` from 5.5.0 to 5.6.2 by updating both `package.json` (adding `"devalue": "^5.6.2"` to dependencies) and regenerating `package-lock.json` to pin the patched version.

Vulnerability at a Glance

cweCWE-400 (Uncontrolled Resource Consumption)
fixUpgrade devalue dependency from 5.5.0 to 5.6.2 in package.json and package-lock.json
riskRemote attacker can exhaust server resources and crash or hang the web service
languageJavaScript / Node.js (SvelteKit)
root causedevalue 5.5.0 does not adequately bound resource usage when deserializing attacker-controlled input
vulnerabilityDenial of Service via excessive resource consumption (CVE-2026-22774)

How Denial of Service happens in Node.js devalue and how to fix it

Summary

A high-severity Denial of Service vulnerability (CVE-2026-22774) was discovered in the devalue package used by the exo-dashboard SvelteKit application. Attackers could craft malicious serialized input to trigger excessive resource consumption, potentially rendering the web service unresponsive. The fix upgrades devalue from version 5.5.0 to 5.6.2 across both dashboard/package.json and dashboard/package-lock.json.


Introduction

The exo-dashboard is a SvelteKit-based web application that handles user-facing requests in a production environment. Inside its dependency tree sits devalue — a library designed to serialize and deserialize rich JavaScript values (including things like Map, Set, Date, and circular references) that JSON alone can't handle. It's commonly used in SvelteKit's server-side data loading pipeline.

The problem: devalue version 5.5.0 does not adequately constrain how much work it performs when processing untrusted input. An attacker who can influence the serialized data flowing into devalue's deserialization routines — for example, through a crafted HTTP request body or a malicious server response — can trigger runaway resource consumption. On a web service exposed to the internet, this translates directly to a remotely exploitable Denial of Service.

Trivy's dependency scanner flagged this in dashboard/package-lock.json, where the pinned version 5.5.0 was identified as vulnerable under rule CVE-2026-22774.


The Vulnerability Explained

What is devalue, and where does it run?

devalue is not just a development tool — in SvelteKit applications, it is used at runtime to serialize data returned from load() functions on the server and deserialize it on the client. This means it processes data that can be influenced by external actors: API responses, database content, and in some configurations, direct user input.

The vulnerable version

The vulnerable entry in dashboard/package-lock.json before the fix looked like this:

"node_modules/devalue": {
    "version": "5.5.0",
    "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.5.0.tgz",
    "integrity": "sha512-69sM5yrHfFLJt0AZ9QqZXGCPfJ7fQjvpln3Rq5+PS03LD32Ost1Q9N+eEnaQwGRIriKkMImXD56ocjQmfjbV3w==",
    "license": "MIT"
}

In devalue 5.5.0, the deserialization logic does not impose strict limits on the complexity or depth of the input it processes. An attacker can construct a deeply nested or cyclically referenced serialized payload that forces devalue to recurse excessively or allocate unbounded memory while attempting to reconstruct the JavaScript object graph.

A concrete attack scenario

Consider a SvelteKit route that accepts serialized data from a client or an upstream API and passes it through devalue for deserialization. An attacker sends a payload like a deeply nested array structure:

// Pseudocode representation of a malicious devalue payload
["BigArray", [["BigArray", [["BigArray", [...10,000 levels deep...]]]]]]

When devalue 5.5.0 attempts to walk this structure to reconstruct the JavaScript value, it may:

  1. Exhaust the call stack through unbounded recursion
  2. Spike CPU usage as it traverses exponentially complex reference graphs
  3. Consume heap memory allocating intermediate objects for each level

In a Node.js web server handling concurrent requests, a single such request can degrade response times for all users. A sustained stream of such requests can take the service entirely offline — no authentication required.

Why this matters for exo-dashboard specifically

The exo-dashboard is described as a web service where "vulnerabilities in request handlers are directly exploitable by remote attackers." The devalue package is listed as a production dependency (not a devDependency), meaning it is active in the deployed application, not just during the build process. This removes any argument that the vulnerability is theoretical or limited to development environments.


The Fix

What changed

The fix involved two files: dashboard/package.json and dashboard/package-lock.json.

dashboard/package.json — Adding an explicit production dependency:

 "dependencies": {
+    "devalue": "^5.6.2",
     "highlight.js": "^11.11.1",
     "katex": "^0.16.27",
     "marked": "^17.0.1",

Previously, devalue was only pulled in transitively (as a dependency of SvelteKit internals) without being explicitly declared in package.json. Adding it explicitly with "^5.6.2" ensures that npm's resolver will always select a patched version, even if a transitive dependency would otherwise resolve to the vulnerable 5.5.0.

dashboard/package-lock.json — Pinning the patched version:

 "node_modules/devalue": {
-    "version": "5.5.0",
-    "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.5.0.tgz",
-    "integrity": "sha512-69sM5yrHfFLJt0AZ9QqZXGCPfJ7fQjvpln3Rq5+PS03LD32Ost1Q9N+eEnaQwGRIriKkMImXD56ocjQmfjbV3w==",
+    "version": "5.6.2",
+    "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.2.tgz",
+    "integrity": "sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==",
     "license": "MIT"
 }

The lock file update is critical. Without it, npm ci (used in most CI/CD pipelines) would continue installing the vulnerable 5.5.0 regardless of what package.json says, because npm ci respects the lock file exactly. Updating the lock file ensures reproducible, secure installs across all environments.

How the fix works

devalue 5.6.2 introduces internal safeguards that bound the complexity of the input it will process. This includes limits on recursion depth and the total number of nodes it will traverse when reconstructing a JavaScript value from a serialized payload. Inputs that exceed these bounds are rejected with an error rather than being processed indefinitely.

The integrity hash change (sha512-69sM5...sha512-nPRkj...) confirms that a genuinely different package artifact is being installed — this is not just a metadata change.


Prevention & Best Practices

1. Declare all runtime dependencies explicitly

Even if a package is pulled in transitively, if your application depends on it at runtime, declare it explicitly in dependencies. This gives you control over the version range and makes security upgrades straightforward.

2. Never pass untrusted input directly to deserialization libraries

Deserialization is a high-risk operation. Before passing any external data to libraries like devalue, JSON.parse with revivers, or similar, validate its structure and size:

// Example: reject oversized payloads before deserialization
app.use(express.json({ limit: '10kb' }));

// Or validate structure with a schema library like zod
import { z } from 'zod';
const schema = z.string().max(1000);
const safeInput = schema.parse(rawInput);

3. Scan your lock files in CI

Tools like Trivy, npm audit, and Snyk can scan package-lock.json for known-vulnerable versions. Add these scans as required checks in your CI pipeline so vulnerable dependencies are caught before they reach production:

# Run Trivy on the dashboard directory
trivy fs ./dashboard --exit-code 1 --severity HIGH,CRITICAL

4. Use npm audit regularly

cd dashboard && npm audit

This will surface known CVEs in your dependency tree and suggest upgrade paths. Automate this in your development workflow.

5. Understand the difference between dependencies and devDependencies

Libraries used at runtime (like devalue in a SvelteKit app) belong in dependencies. Scanners and security tools treat these differently — production dependencies get higher scrutiny because they are present in deployed environments.

Security Standards References

  • CWE-400: Uncontrolled Resource Consumption — the root cause category for this vulnerability
  • OWASP A05:2021 — Security Misconfiguration: includes failing to update components with known vulnerabilities
  • OWASP A06:2021 — Vulnerable and Outdated Components: directly applicable to this dependency upgrade scenario

Key Takeaways

  • devalue 5.5.0 is vulnerable in production SvelteKit apps: If your package-lock.json pins devalue at 5.5.0, you are exposed to CVE-2026-22774 in any environment where user-influenced data reaches the deserialization path.
  • Transitive dependencies need explicit pinning: devalue was not originally declared in package.json, meaning its version was controlled entirely by SvelteKit's own dependency range. Adding an explicit "devalue": "^5.6.2" entry takes back control.
  • Lock file updates are not optional: Changing package.json alone is insufficient. The package-lock.json must be regenerated and committed to ensure npm ci installs the patched version in CI/CD and production.
  • Trivy caught what a code review would miss: The vulnerability was not in application code — it was in a pinned version number inside a lock file. Automated dependency scanning is the only reliable way to catch this class of issue.
  • Production dependency classification matters: Because devalue is in dependencies (not devDependencies), it is present in the deployed exo-dashboard service, making this a directly exploitable remote attack surface.

How Orbis AppSec Detected This

  • Source: Untrusted data (user-influenced HTTP request bodies or external API responses) flowing into SvelteKit's data loading pipeline
  • Sink: devalue's deserialization routines in node_modules/devalue version 5.5.0, invoked at runtime within the exo-dashboard web service
  • Missing control: No version constraint preventing the installation of the vulnerable 5.5.0 artifact; no input size or complexity bounds in the devalue library itself at that version
  • CWE: CWE-400 — Uncontrolled Resource Consumption
  • Fix: Upgraded devalue from 5.5.0 to 5.6.2 in both dashboard/package.json and dashboard/package-lock.json, pinning the patched artifact with its verified integrity hash

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.


Conclusion

CVE-2026-22774 is a reminder that security vulnerabilities don't only live in the code you write — they live in the versions of libraries you depend on. The exo-dashboard application was exposed to a remotely exploitable Denial of Service simply because devalue 5.5.0 was pinned in its lock file without an explicit version constraint in package.json.

The fix is precise and minimal: two files changed, one version number bumped, and the attack surface is closed. But getting there required knowing the vulnerability existed in the first place — which is exactly the gap that automated dependency scanning fills.

If your Node.js or SvelteKit application uses devalue, check your package-lock.json now. If you see any version below 5.6.2, you are vulnerable.


References

Frequently Asked Questions

What is CVE-2026-22774?

CVE-2026-22774 is a high-severity Denial of Service vulnerability in the devalue npm package (versions before 5.6.2) where processing untrusted serialized input can cause excessive CPU or memory consumption, crashing the server.

How do you prevent Denial of Service from devalue in Node.js?

Upgrade devalue to version 5.6.2 or later, which introduces input bounds checking. Additionally, validate and sanitize all user-supplied data before passing it to deserialization functions.

What CWE is this Denial of Service vulnerability?

CWE-400 — Uncontrolled Resource Consumption ("Resource Exhaustion"), which covers cases where an application does not properly limit the resources it allocates in response to untrusted input.

Is input validation alone enough to prevent this devalue DoS?

Input validation helps reduce the attack surface, but the root fix is upgrading to devalue 5.6.2, which patches the internal resource bounding logic. Relying only on upstream validation without patching the library leaves the vulnerability open.

Can static analysis detect this devalue vulnerability?

Yes — tools like Trivy (which flagged this exact issue) scan dependency lock files for known-vulnerable package versions and will report CVE-2026-22774 when devalue < 5.6.2 is detected in package-lock.json.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #2150

Related Articles

high

How unbounded input size denial-of-service happens in C lexer functions and how to fix it

A high-severity denial-of-service vulnerability was discovered in the PH7 lexer where the `PH7_TokenizePHP()` function accepted arbitrarily large input sizes without validation. An attacker could submit gigabyte-scale PHP code, causing proportional CPU and memory exhaustion. The fix introduces a configurable input size cap enforced before lexer processing begins.

high

How form limit bypass DoS happens in Python Starlette and how to fix it

CVE-2026-54283 is a high-severity denial-of-service vulnerability in Starlette where size limits set on `request.form()` were silently ignored for `application/x-www-form-urlencoded` content, allowing attackers to submit unbounded form data and exhaust server resources. The fix upgrades Starlette from version 1.2.1 to 1.3.1, which correctly enforces form size limits for all content types. Any Python web application using Starlette (including FastAPI-based services) that accepts form submissions

high

How Denial of Service via crafted URI templates happens in Ruby addressable and how to fix it

A high-severity Denial of Service vulnerability (CVE-2026-35611) was discovered in the Ruby `addressable` gem versions prior to 2.9.0, which could allow attackers to crash or hang applications by sending specially crafted URI templates. The fix upgrades the dependency from version 2.8.7 to 2.9.0 across the Gemfile, Gemfile.lock, and gemspec in a Fastlane project, eliminating the vulnerable code path entirely.

high

How Denial of Service in SSH Key Exchange happens in Go golang.org/x/crypto and how to fix it

A high-severity denial of service vulnerability (CVE-2025-22869) was discovered in the SSH key exchange implementation of Go's `golang.org/x/crypto` library. The `cpdaemon` service depended on the vulnerable version v0.32.0, which could allow an attacker to exhaust server resources during the SSH handshake phase. The fix upgrades the dependency to v0.35.0, which includes the upstream patch for this vulnerability.

high

How DoS via sparse array deserialization happens in Svelte devalue and how to fix it

A high-severity vulnerability (CVE-2026-42570) was discovered in the devalue library version 5.7.1, used by the Astro-powered website. This vulnerability allowed attackers to trigger denial-of-service conditions through maliciously crafted sparse arrays during deserialization. The fix involved upgrading devalue from 5.7.1 to 5.8.1, which implements proper safeguards against sparse array exploitation.

high

How buffer overflow happens in C MemStream.h and how to fix it

A high-severity buffer overflow vulnerability was discovered in `src/avt/IVP/MemStream.h`, where the `read()` and `write()` template methods performed `memcpy` operations without validating that `_pos + nBytes` stayed within the allocated buffer. An attacker supplying crafted serialized integral curve data could trigger out-of-bounds memory reads or writes, potentially corrupting the heap or leaking sensitive memory. The fix adds a single bounds check before each `memcpy`, throwing an `ImproperU