You Can Run But You Can't Hide: Runtime Protection Against Malicious Package Updates For Node.js
Marc Ohm, Timo Pohl, Felix Boes
TL;DR
This work tackles software supply chain attacks in Node.js by proposing a runtime protection that automatically infers the minimal capabilities a package needs and enforces them at runtime. It generates policies through static analysis of a package and its dependencies and enforces them via a patched Node.js runtime, offering coarse- and fine-grained modes. Large-scale experiments across 200k npm packages show the approach can avert 9 of 10 historic attacks, with median policy-generation times around 0.5–0.6 s and startup enforcement overhead around 198 ms, while keeping policy files to a few kilobytes. The results indicate a practical, low-overhead defense that substantially reduces the attack surface of software updates, with future work aimed at extending to other languages and further refining capability weighting and handling of dynamic code paths.
Abstract
Maliciously prepared software packages are an extensively leveraged weapon for software supply chain attacks. The detection of malicious packages is undoubtedly of high priority and many academic and commercial approaches have been developed. In the inevitable case of an attack, one needs resilience against malicious code. To this end, we present a runtime protection for Node.js that automatically limits a package's capabilities to an established minimum. The detection of required capabilities as well as their enforcement at runtime has been implemented and evaluated against known malicious attacks. Our approach was able to prevent 9/10 historic attacks with a median install-time overhead of less than 0.6 seconds and a median runtime overhead of less than 0.2 seconds.
