← all writeups
CVE

Four CVEs in Progress Software Products: Command Injection, SSRF and Chart-Tooltip XSS

Oct 14, 2026 · 9 min · by Abhishek Bhaskar (Abhi HackZ)
Four CVEs in Progress Software Products: Command Injection, SSRF and Chart-Tooltip XSS — cover

In October 2026, Progress Software published four CVE records that credit me as the finder: CVE-2026-91140, CVE-2026-92931, CVE-2026-106138 and CVE-2026-106139. All four came in through the vendor's Bugcrowd vulnerability disclosure programs (VDPs), and all four were assigned by Progress acting as its own CVE Numbering Authority (CNA), the organisation entitled to issue CVE IDs for its products.

Update, 15 October 2026: Progress has since published eight further records credited to me — CVE-2026-106147 through CVE-2026-106161, all in Kendo UI for jQuery — bringing the total to 12. The full list, with affected and fixed versions, is on the CVE index.

This is not a write-up of exploitation steps. Proof-of-concept details are withheld, and I am sticking to what the public records, vendor bulletins and Telerik knowledge base articles say. What I want to do instead is explain the three bug classes, show how each works in a generic lab setting, and give you a concrete way to check whether your codebase pulls in an affected version.

Why these four matter together

They span three bug classes: OS command injection (CWE-78), server-side request forgery (CWE-918) and cross-site scripting through improperly neutralised HTML (CWE-80). Each violates a different trust assumption, which I will spell out section by section.

They also sit at three layers of a modern stack: a developer-side code generator, a CMS rendering SDK for Next.js, and two front-end charting libraries. None of these is "the application". They are dependencies, with supply-chain-style reach: one fix propagates to every product that upgrades, and one unpatched install sits in every product that does not.

Finally, CVE-2026-106138 (KendoReact) and CVE-2026-106139 (Kendo UI for Vue) are the same bug in two frameworks, sharing a CWE, a CVSS vector and a root cause. When you find a pattern in one port of a library, check the siblings.

CVE-2026-91140: OS command injection in ARCGenAI-Generator 2.0

Product. Progress Autonomous REST Connector GenAI Agents, specifically ARCGenAI-Generator 2.0. It is developer tooling: you feed it an API description and it generates connector code.

What the record says. "Shell-based temporary-file cleanup instructions in ARCGenAI-Generator 2.0 contain an OS command injection flaw. An attacker who supplies a crafted Swagger/OpenAPI document can run arbitrary commands on a developer's machine when a user invokes the generator."

Rating. CWE-78. CVSS 3.1 base score 9.6 Critical, vector AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H. Affected: 2.0. Fixed: 2.1. Published 2026-10-06. The patch commit is public on GitHub in progress/datadirect-arc-ai-model-gen, and the vendor issued the "Progress DataDirect Critical Security Alert Bulletin, September 2026".

How the class works. OS command injection happens when a program builds a shell command by concatenating strings, and one of those strings came from input the program does not control. The shell cannot tell which part the developer wrote and which part the attacker wrote; it just parses metacharacters like ;, &&, | and backticks.

The misconception to kill here: people assume a document format is "just data". A Swagger/OpenAPI file is JSON or YAML, so it feels inert. But any tool that reads field values out of it and later passes them to a shell has turned data into code. In generator-style tooling, filenames, titles and paths derived from the spec are the usual suspects.

Generic vulnerable shape versus safe shape:

# Vulnerable pattern (generic): string goes straight into a shell
import subprocess
subprocess.run(f"rm -f /tmp/{name}.tmp", shell=True)

# Safer pattern: no shell, argument list, validated name
import os, re
if not re.fullmatch(r"[A-Za-z0-9_-]{1,64}", name):
    raise ValueError("bad name")
os.remove(os.path.join("/tmp", f"{name}.tmp"))

The second form works because there is no shell to interpret metacharacters, and the allow-list rejects anything that is not a plain token. Both halves matter; validation alone is brittle, and dropping the shell alone still leaves path tricks.

Why UI:R and S:C? A user has to run the generator on the crafted file (user interaction required), but the commands execute on the developer's machine, outside the generator's own security scope (scope changed). That is what pushes a "needs a click" bug to 9.6.

Check if you are affected. Find every install of the generator on developer machines and in CI, and confirm it reports 2.1 or later.

Fix. Upgrade to 2.1 or later. Until you can, do not process untrusted Swagger/OpenAPI documents with the generator: specs from third-party repos, customer-supplied specs and anything fetched from a URL you do not own.

CVE-2026-92931: SSRF in @progress/sitefinity-nextjs-sdk

Product. The Sitefinity Next.js Renderer SDK, shipped as the npm package @progress/sitefinity-nextjs-sdk. It renders Sitefinity CMS content in a Next.js application.

What the record says. "Remote attackers may be able to make server-side requests to attacker-controlled hosts, potentially exposing sensitive information."

Rating. CWE-918. CVSS 3.1 base score 8.8 High, vector AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H. Affected: 15.1.8326 through 15.4.8637. Fixed: 15.4.8638. Published 2026-10-05. Vendor advisory: "Sitefinity Critical Security Advisory for Addressing Security Vulnerabilities in Next.js, September 2026".

How the class works. Server-side request forgery (SSRF) is when an attacker gets a server to issue a request to a destination of the attacker's choosing. The violated assumption is that outbound requests are trusted because the server wrote the code that sends them. In practice the destination is often derived from the inbound request: a query parameter, a header, a path segment, or a URL embedded in content the renderer fetches.

A server-side rendering (SSR) layer is exactly that risk profile: the renderer's job is to fetch things, so the only question is whether what it fetches can be steered. The public record says the target host can be attacker-controlled; I am not going to speculate beyond that.

Generic illustration:

// Vulnerable pattern (generic): origin taken from the request
const origin = req.headers["x-forwarded-host"] || req.query.host;
const data = await fetch(`https://${origin}/api/content`).then(r => r.json());

// Safer pattern: origin from server configuration only
const data = await fetch(`${process.env.CMS_ORIGIN}/api/content`).then(r => r.json());

The fix works because the destination no longer passes through any attacker-reachable channel. When a renderer legitimately must follow URLs from content, it needs an allow-list of hosts and schemes, and it should treat redirects as new destinations to re-check.

Check if you are affected.

npm ls @progress/sitefinity-nextjs-sdk
grep -n "sitefinity-nextjs-sdk" package.json package-lock.json

Any resolved version from 15.1.8326 up to and including 15.4.8637 is in range.

Fix. Upgrade to 15.4.8638 or later, rebuild and redeploy. Lockfiles pin versions, so editing package.json alone is not enough; verify with npm ls after install.

CVE-2026-106138: XSS via Chart tooltip in @progress/kendo-react-charts

Product. KendoReact Charts, the npm package @progress/kendo-react-charts.

What the record says. "The default Chart tooltip renders the formatted point value as raw HTML without encoding, in both the single-point and shared tooltip. A low-privileged attacker who can influence a string value bound to the chart can supply HTML with event handlers that run JavaScript in a user's browser when the user hovers over the affected data point."

Rating. CWE-80 (improper neutralisation of script-related HTML tags). CVSS 3.1 base score 5.4 Medium, vector AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N. Affected: 1.1.0 before 16.2.0. Fixed: 16.2.0. Published 2026-10-10. Telerik KB: kb-security-chart-tooltip-xss-cve-2026-106138.

How the class works. Cross-site scripting (XSS) is attacker-supplied markup executing in another user's browser. The sub-pattern here is a UI component that formats a value into a string and writes it into the DOM as HTML rather than as text.

The misconception: "the chart only shows numbers, so there is no injection surface". But charts bind to data, and data includes labels, category names and series names that come from a database. In a multi-tenant application, a low-privileged user who can set a label that another user's dashboard renders has a stored XSS path, and the trigger is just hovering.

Generic illustration:

// Vulnerable pattern (generic): formatted value becomes HTML
tooltipEl.innerHTML = format(point.value);

// Safer pattern: formatted value becomes text
tooltipEl.textContent = format(point.value);

textContent works because the browser never parses the string as markup; <img onerror=...> stays a literal string on screen.

Check if you are affected.

npm ls @progress/kendo-react-charts

Fix. Upgrade to 16.2.0 or later.

CVE-2026-106139: the same bug in @progress/kendo-vue-charts

Product. Kendo UI for Vue Charts, the npm package @progress/kendo-vue-charts.

What the record says. Same class as the React one: the chart tooltip renders the formatted point value as raw HTML in both the single-point and shared tooltips.

Rating. CWE-80. CVSS 3.1 base score 5.4 Medium, same vector AV:N/AC:L/PR:L/UI:R/S:C/C:L/I:L/A:N. Affected: 2.5.0 through 10.0.0. Fixed: 10.1.0. Published 2026-10-10. Telerik KB: kb-security-chart-tooltip-xss-cve-2026-106139.

Check if you are affected.

npm ls @progress/kendo-vue-charts

Fix and workaround. Upgrade to 10.1.0 or later. If you cannot upgrade immediately, the Telerik KB gives a workaround: provide a custom render template to the ChartTooltip component for both the single and the shared tooltip. This works because Vue encodes interpolated text in templates, so {{ value }} is escaped rather than parsed as HTML. The key word is "both": patching only the single-point tooltip leaves the shared one open.

Patterns worth noticing

One shared lesson: a library's default path is also an application's attack surface. Three patterns to grep for in your own code and your dependencies:

Checklist: if you use Progress or Telerik products

Disclosure notes

All four issues went through Bugcrowd VDPs (the Progress DataDirect VDP and Progress Sitefinity VDP among them) under coordinated disclosure. Progress, as the CNA, assigned the IDs and published advisories and KB articles alongside the records. Proof-of-concept details stay private. The records are listed on my Hall of Fame page; the path from VDP submission to published record is covered in a separate post.

Takeaways

Learn more

Related: From a Bugcrowd VDP Report to a Published CVE · Framework-Level Bugs: Middleware Bypasses, SSR Fetches and the SSRF Hiding in Your Renderer. Need this tested on your product? Book a free 30-minute scoping call.

KEEP READING
Abhishek Bhaskar (Abhi HackZ)
Security Analyst & VAPT Engineer
Book a free 30-min security scoping call →