English

ProfMalPlus: Agent-Coordinated Detection of Malicious NPM Packages via Static-Dynamic Analysis Synergy

Software Engineering 2026-07-15 v1 Cryptography and Security

Abstract

Open source software is vulnerable to supply-chain attacks through transitive dependencies, especially malicious code injected into NPM packages. Existing detectors often inadequately model obfuscated behavior, overlook JavaScript's object-centric features, poorly coordinate static and dynamic analysis, and lose semantic information during behavior abstraction. We propose ProfMalPlus, a malicious NPM package detector combining object-sensitive behavior graphs with coordinated LLM reasoning over annotated code slices. It identifies installation commands and entry files, then constructs graphs capturing sensitive APIs, third-party calls, and unresolved calls. From these graphs, ProfMalPlus extracts security-relevant slices and adds inline static analysis evidence. Local judge agents independently assess each slice. Self-consistency consolidates repeated judgements to reduce LLM variance, while a global judge synthesizes their reports into an entry-level verdict. For undetermined cases, a router selects either third-party enrichment, which adds registry derived module and method semantics, or dynamic augmentation, which executes the package in a sandbox to resolve runtime dependent behavior. The enriched evidence is fed back for reassessment. Finally, a localization agent reports malicious code snippets with explanations. ProfMalPlus achieves a 98.1% F1-score, outperforming state-of-the-art detectors by 3.5% to 52.6%. It also identified 597 previously unknown malicious packages, all confirmed and removed from NPM.

Keywords

Cite

@article{arxiv.2607.13965,
  title  = {ProfMalPlus: Agent-Coordinated Detection of Malicious NPM Packages via Static-Dynamic Analysis Synergy},
  author = {Yiheng Huang and Zhijia Zhao and Bihuan Chen and Susheng Wu and Zhuotong Zhou and Yiheng Cao and Kun Hu and Xin Hu and Xin Peng},
  journal= {arXiv preprint arXiv:2607.13965},
  year   = {2026}
}