Your Window of Exposure is the Attacker's Window of Opportunity

How attackers exploit the first hours after a package is published and what actually reduces the risk.

January 12th, 2026
Share

Despite decades of security advances, even technically sophisticated users can be easily tricked into installing malware on their computer. Malicious actors have myriad attack surfaces they can leverage to quickly deploy unverified code.

Take npm, a JavaScript package manager that many developers use to install third-party code in their projects. It’s common practice to run the npm install command (and many other commands) without knowing the exact source code you’re pulling into your project. Blindly trusting npm as a personal assistant that fetches unknown code isn’t exactly a good security practice. It’s thus no surprise that amongst the growing number of supply chain attacks this year, npm was a major vector, including in September, when attackers injected malware into 18 npm packages with over 2.6 billion weekly downloads.

The window of exposure and opportunity

These supply chain attacks led us to ask: If you are a developer, what is your window of exposure, and if you are an attacker, what is your window of opportunity?

Imagine that someone releases a new package, whether via npm or another vector, that includes malware. The window of exposure and opportunity starts when the package is published and ends when independent security researchers and security vendors conclude whether the package is safe. After a researcher or vendor detects malware, they report it, and the window of exposure and opportunity is limited (in the case of npm, the package manager would take the package out so that it cannot be installed).

The Nx build attack was live for four hours. While every attack is different, in this case, if you’re a developer that uses Nx, you would have been impacted if you install or update Nx in the first four hours.

Can generative AI tools help?

During this window of exposure and opportunity, you can leverage generative AI tools to help detect malware. The effectiveness of using AI, however, depends on the payload in question.

We ran a few experiments using LLMs to see if it could detect malicious code across scenarios:

  • Readable malicious code from the Nx attack was easy to parse. Claude quickly concluded the code’s intent as “Short version: it’s malware.” For cases like this, you don’t need to apply a deny-by-default policy, since you already know what the code does.

  • For minified code, Claude struggled to help. We uploaded a worm three times, and three times Claude said it was safe. You cannot apply a deny-by-default policy for such cases because there are legitimate packages that use minified code. Minified code is not necessarily malicious; we need to know what it does.

  • For obfuscated code, Claude helped, although just like with minified code, the accuracy is debatable. We uploaded a file with obfuscated code three times, and three times Claude was able to detect that it was malware. You could argue for a deny-by-default policy because normal packages usually do not contain obfuscated code. If there is obfuscated code, it is highly likely that the creator wants to cause damage.

  • We could not run our experiments on binary files. While ChatGPT can run static analysis on a binary and detail what it is designed to do, the process is not as simple as uploading the code and asking what it does. Binaries require both static and dynamic analysis, since you need to know what the code does at runtime. You thus cannot use a deny-by-default policy for binaries.

Even if these results were promising, we do not recommend relying on generative AI as your sole analysis tool. We found a slew of potential issues, including LLMs making mistakes if the file was greater than their context window, LLMs giving false positives and false negatives as a result of their nondeterministic nature, and adversarial code specifically designed to avoid analysis or attempting to circumvent safeguards by using prompt injection techniques to mislead LLMs.

For all the above reasons, having a human in the loop is still necessary. This additional time requirement may be tedious, but it’s a good use of time to eat into your window of exposure.

Tips and tricks to narrowing the window

Smaller organizations or individual developers may not have the resources to deeply analyze every dependency before installing it. In those cases, reducing when code executes is often more practical than trying to perfectly understand what it does. 

If you can avoid the FOMO around installing the latest version immediately, the following steps significantly reduce your exposure during the most dangerous period after a package is published:

1. Pin dependency versions

Pinning avoids unintentionally pulling in newly published versions before the ecosystem has reviewed them.

2. Limit install-time execution using --ignore-scripts (or equivalents)

Many recent npm supply-chain attacks such as Shai-Hulud and Shai-Hulud 2 relied on lifecycle scripts (preinstall, postinstall) to execute malware immediately during installation. Disabling scripts reduces this blast radius by preventing arbitrary code execution at install time. This is not a universal solution: ignoring scripts can break legitimate packages that rely on build steps or binary downloads, and it does not protect against malicious code that executes at runtime. However, as a default posture, it materially reduces risk during the window of exposure.

3. Delay automated dependency updates

Waiting even just 24 or 48 hours before merging Dependabot PRs gives security researchers, vendors, and registry maintainers time to detect and respond to malicious releases. pnpm has a minimumReleaseAge feature as of version 10.16 that does this for you. Many large supply-chain incidents are identified and mitigated within this window. Waiting comes with a trade-off, of course: you are accepting the risk that the new version might be a critical security patch. In short, you are accepting the risk of being vulnerable for a day or two to ensure that the new version is a proper update.

Note that If you only did Step 2 and chose to ignore scripts, you would have avoided most of the major attacks this year, including Shai-Hulud and Shai-Hulud 2. Making a point to merge after one or two days avoids a lot of headache, because by that time, npm would have already removed a package if it had malware.

If you keep your packages pinned to the latest versions that you know are safe, use flags to limit script execution, and do not merge PRs as soon as Dependabot prompts you, you will avoid most malware, including via npm. Taken together, these steps shift risk away from the most dangerous period immediately after publication — when attackers are most active and defenses are least informed. These techniques do not eliminate supply-chain risk, but they reliably reduce exposure during the short window when attacks are most likely to succeed. Additionally, If you are the developer or maintainer of multiple libraries, make sure to use short-lived, granular tokens so that each library has a different token that expires within a week or a month (npm now enforces this).

In short, let security researchers and vendors reach a conclusion before you use a new package. Note that this wait-and-see approach is applicable beyond the npm ecosystem: there’s more downside than upside if you get the latest package immediately and get infected with malware.

Let the window of opportunity expire and drastically reduce the window of exposure.



We first shared this information in our BSides Delaware 2025 presentation. To learn more, watch our talk here and check out the slides here.


About

semgrep logo

Semgrep enables teams to use industry-leading AI-assisted static application security testing (SAST), supply chain dependency scanning (SCA), and secrets detection. The Semgrep AppSec Platform is built for teams that struggle with noise by helping development teams apply secure coding practices.