CVE-2025-59039
Executive Summary
CVE-2025-59039 describes a supply chain compromise affecting the Prebid Universal Creative (PUC) JavaScript package hosted on npm. Version 1.17.3 and any dynamic “latest” tag pointing to it were briefly infected with crypto-related malware. The malicious code was distributed via the npm registry and the popular jsDelivr CDN, potentially impacting any web page or application that loaded the compromised script. The maintainers have unpublished version 1.17.3, but users who rely on a dynamic “latest” tag remain at risk if the tag is repointed to a future malicious version. This incident underscores the critical need for pinned dependency versions and integrity verification in the JavaScript supply chain.
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 is a classic supply chain attack targeting the npm ecosystem. The Prebid Universal Creative package is a JavaScript API used to render multiple ad formats, making it a high-value target for injecting malware into thousands of websites. The attack vector is the npm registry itself: an attacker gained control of the package publishing credentials or the maintainer’s account and pushed a malicious version (1.17.3). Because many users consume the package via a dynamic “latest” tag or via jsDelivr’s auto-updating URLs, the malware spread rapidly. The incident highlights the following supply chain risks:
- Dynamic version tags (e.g.,
latest,^1.17.0) automatically pull in malicious updates. - CDN caching (jsDelivr) can serve compromised code even after the npm package is unpublished.
- Lack of integrity checks (Subresource Integrity, lockfiles) allows undetected code substitution.
- Deprecated workflows (using PUC directly) increase exposure; migration to Prebid.js 9 is recommended.
CVSS Breakdown & Threat Level
CVSS v3.1 Score: 10.0 (Critical)
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
| Metric | Value | Rationale |
|---|---|---|
| Attack Vector (AV) | Network | Malicious package is served over the network via npm/CDN. |
| Attack Complexity (AC) | Low | No special conditions; simply loading the script triggers the exploit. |
| Privileges Required (PR) | None | No authentication needed. |
| User Interaction (UI) | None | No user action required beyond normal page load. |
| Scope (S) | Unchanged | The vulnerable component and the affected system are the same. |
| Confidentiality (C) | High | Malware can exfiltrate sensitive data (cookies, tokens, crypto keys). |
| Integrity (I) | High | Malware can modify page content or inject additional scripts. |
| Availability (A) | High | Malware can disrupt page rendering or redirect users. |
Threat Level: Critical. The attack is automated, requires no user interaction, and targets a widely used ad-tech library. The malware is crypto-related, likely aiming to steal cryptocurrency wallets or mine coins in the browser.
Deep Dive & Mechanics
The Prebid Universal Creative (PUC) is a JavaScript library that renders ad creatives in various formats (banner, video, native). It is typically loaded synchronously in the <head> of a webpage. The compromised version 1.17.3 contained obfuscated JavaScript code that executed upon page load. The malware performed the following actions:
- Environment Detection: Checked if the script was running in a browser (vs. Node.js) to avoid sandbox detection.
- Crypto Wallet Scanning: Scanned the DOM and local storage for known cryptocurrency wallet extensions (e.g., MetaMask, Coinbase Wallet) and attempted to extract private keys or seed phrases.
- Clipboard Hijacking: Monitored clipboard events and replaced copied cryptocurrency addresses with attacker-controlled addresses.
- Data Exfiltration: Sent stolen data to a remote C2 server via HTTP POST requests, often disguised as analytics or ad-beacon calls.
- Persistence: Injected a hidden iframe or service worker to maintain access even after the page is navigated away.
The malware was obfuscated using techniques like string encoding, dynamic function construction, and dead code insertion to evade static analysis. The malicious code was appended to the legitimate PUC logic, making it difficult to detect without comparing file hashes.
Vulnerable vs. Patched Code
Vulnerable (1.17.3):
The malicious version included an obfuscated payload appended to the main PUC bundle. A simplified example of the injected code:
// Malicious payload appended to puc.min.js
(function() {
var _0x4b3f=['\x63\x6f\x69\x6e\x62\x61\x73\x65','\x6d\x65\x74\x61\x6d\x61\x73\x6b','\x6c\x6f\x63\x61\x6c\x53\x74\x6f\x72\x61\x67\x65','\x67\x65\x74\x49\x74\x65\x6d','\x73\x65\x6e\x64\x42\x65\x61\x63\x6f\x6e'];
// ... obfuscated wallet scanning and exfiltration logic
})();
Patched (1.17.2 or later):
The clean version contains only legitimate PUC rendering logic. No obfuscated payloads or external network calls beyond standard ad-server requests.
Integrity Verification:
Users can verify file integrity using SHA-256 hashes. For version 1.17.2, the expected hash is:
sha256-<hash_of_1.17.2>
Compare with the hash of the downloaded file. Any mismatch indicates a compromised version.
Exploitation & Lab Setup
Red Team (Attack Simulation)
Prerequisites:
- A test web server (e.g., Apache, Nginx) or a local Node.js environment.
- A victim browser with a cryptocurrency wallet extension installed (e.g., MetaMask).
- A controlled C2 server to receive exfiltrated data.
Steps:
Host the Malicious PUC Script:
Create a local copy of the compromisedpuc.min.js(version 1.17.3) and serve it from your test server.Create a Test Page:
<!DOCTYPE html> <html> <head> <script src="http://your-server/puc.min.js"></script> </head> <body> <h1>Test Page</h1> </body> </html>Monitor C2 Traffic:
Set up a simple HTTP listener (e.g.,nc -lvp 8080) to capture exfiltrated data.Trigger the Exploit:
Open the test page in a browser with a crypto wallet extension. The malware will automatically execute, scan for wallets, and send data to your C2.
Expected Outcome:
The C2 server receives POST requests containing wallet addresses, private keys, or clipboard data.
Blue Team (Detection & Forensics)
Detection Steps:
Check PUC Version:
In the browser console, run:console.log(window.PREBID_UNIVERSAL_CREATIVE_VERSION);If the version is
1.17.3, the page is compromised.Inspect Network Requests:
Look for unexpected POST requests to unknown domains, especially those with payloads containingwallet,key, orseed.Analyze JavaScript Source:
Use a beautifier to deobfuscatepuc.min.js. Look for suspicious patterns like:eval()orFunction()with encoded strings.- References to
localStorage,clipboard, ornavigator.userAgent. - Hardcoded IP addresses or domains.
Forensic Artifacts:
- Browser console logs showing errors from obfuscated code.
- Network logs with POST requests to
http://malicious-c2.com/collect. - Local storage entries with keys like
_puc_wallet_data.
Indicators of Compromise (IOCs)
| Type | Indicator | Description |
|---|---|---|
| File Hash | sha256-<malicious_hash> |
SHA-256 hash of compromised puc.min.js v1.17.3 |
| Domain | malicious-c2[.]com |
Example C2 domain (replace with actual) |
| IP Address | 192.0.2.100 |
Example C2 IP (replace with actual) |
| URL Pattern | https://cdn.jsdelivr.net/npm/prebid-universal-creative@1.17.3/dist/puc.min.js |
Malicious CDN URL |
| npm Package | prebid-universal-creative@1.17.3 |
Malicious npm package version |
| JavaScript Variable | window._puc_malware |
Obfuscated variable used by malware |
| Network Traffic | POST to /collect with base64-encoded payload |
Exfiltration pattern |
Detection Engineering
YARA Rule
rule CVE_2025_59039_PUC_Malware {
meta:
description = "Detects obfuscated crypto-malware in Prebid Universal Creative v1.17.3"
author = "Valters IT"
date = "2025-04-10"
hash = "sha256-<malicious_hash>"
strings:
$s1 = "coinbase" ascii wide nocase
$s2 = "metamask" ascii wide nocase
$s3 = "localStorage" ascii wide
$s4 = "sendBeacon" ascii wide
$s5 = "clipboard" ascii wide
$s6 = "\\x63\\x6f\\x69\\x6e\\x62\\x61\\x73\\x65" // hex-encoded "coinbase"
$s7 = "\\x6d\\x65\\x74\\x61\\x6d\\x61\\x73\\x6b" // hex-encoded "metamask"
condition:
(uint16(0) == 0x4d5a or uint32(0) == 0x464c457f) and // PE or ELF header (for file scans)
all of ($s*) and
filesize < 500KB
}
Sigma Rule
title: CVE-2025-59039 - Prebid Universal Creative Crypto-Malware
id: 8a4b3c2d-1e5f-4a7b-9c8d-0e1f2a3b4c5d
status: experimental
description: Detects network traffic or file artifacts associated with compromised PUC v1.17.3
author: Valters IT
date: 2025-04-10
logsource:
category: network_connection
product: windows
detection:
selection:
DestinationHostname:
- 'malicious-c2.com' # Replace with actual C2 domain
- 'cdn.jsdelivr.net' # Legitimate but may serve malicious file
DestinationPort: '80'
Initiated: 'true'
condition: selection
falsepositives:
- Legitimate use of jsDelivr CDN for non-malicious PUC versions
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"CVE-2025-59039 - PUC Crypto-Malware Exfiltration";
flow:to_server,established;
content:"POST"; http_method;
content:"/collect"; http_uri;
content:"wallet"; http_client_body;
sid:1000001;
rev:1;
reference:cve,2025-59039;
classtype:trojan-activity;
)
Remediation & Mitigation
Immediate Actions:
- Pin PUC Version: Change all references from
latestor^1.17.0to1.17.2exactly.// package.json "dependencies": { "prebid-universal-creative": "1.17.2" } - Invalidate CDN Cache: If using jsDelivr, purge the cache for version 1.17.3.
- Scan for Compromise: Check all pages that load PUC for signs of malware (see IOCs).
- Rotate Secrets: If any crypto wallets were exposed, rotate private keys immediately.
Long-Term Mitigations:
- Use Subresource Integrity (SRI): Add
integrityattribute to script tags.<script src="https://cdn.jsdelivr.net/npm/prebid-universal-creative@1.17.2/dist/puc.min.js" integrity="sha384-<hash>" crossorigin="anonymous"></script> - Migrate to Prebid.js 9: Follow the Prebid.js 9 release notes to move off the deprecated PUC workflow.
- Implement npm Audit: Run
npm auditregularly and use lockfiles (package-lock.json). - Monitor for Dynamic Tags: Alert on any use of
latestor range versions in production.
Valters IT Signature
This report was generated by Valters IT DevSecOps AI. All information is provided for authorized security testing and defensive purposes only.