DEV Community

Stop Trusting npm Scans: Run Untrusted Packages in an Isolated AWS Sandbox

Sarvar Nadaf on November 10, 2026

This started as an AWS Builder Center weekend challenge: take an agent you already built, add one new tool, and show the before and after. Mine we...
Collapse
 
iictp profile image
IICTP •

The before/after framing really lands — v1 saying "looks fine" about a postinstall that pipes a remote script into a shell is exactly the gap static scoring can't close. Running the install in a disposable CodeBuild container and quoting the real build log is a much stronger signal, and the least-privilege service role is a nice touch. Curious whether you've tried the same pattern for pip build steps or Makefile targets yet, since those fire at install time too.

Collapse
 
sarvar_04 profile image
Sarvar Nadaf AWS Community Builders •

I haven't extended the current implementation to pip build steps or Makefile targets yet. The current focus is npm lifecycle scripts, but the underlying approach can be applied to other package managers as well. I think the important part is not just detecting suspicious commands beforehand, but observing what actually executes during the build. pip build backends and Makefile targets are definitely worth exploring next.

Have you worked with any particular Python packages or build workflows where you've seen this kind of behaviour?

Collapse
 
iictp profile image
IICTP •

Thanks, Sarvar — that distinction between detecting suspicious commands beforehand and observing what actually executes during the build is a useful one, and it makes sense that the same approach would carry over to pip and Make. I don't have one standout Python package to point to, but the workflows I'd watch most closely are setup.py build steps and Makefile targets that fetch or run something at install time, since those are the closest equivalents to a postinstall hook. Keen to see how you extend it if you take it that way.

Thread Thread
 
sarvar_04 profile image
Sarvar Nadaf AWS Community Builders •

Thanks for sharing that. I agree, "setup.py" build steps and Makefile targets are good places to start because they can execute commands during the build, just like npm lifecycle scripts.

I want to keep the same principle: don't just inspect what the repository says it will do, actually execute it in an isolated environment and capture the evidence.

I'll keep these use cases in mind when extending RepoPilot. Appreciate the suggestions!

Thread Thread
 
iictp profile image
IICTP •

Thanks, Sarvar — glad the setup.py and Makefile angle resonates. The part I keep coming back to is your point about extending the execution layer while keeping the sandbox itself isolated, so the same evidence-first principle carries over to pip build backends. When you do extend it, would the first signal you'd want captured be network egress during the build, or the files the build step touches?

Thread Thread
 
sarvar_04 profile image
Sarvar Nadaf AWS Community Builders •

I'd probably start with network egress because it gives us visibility into whether a build step is downloading additional scripts, contacting unexpected endpoints, or trying to fetch something outside the expected package sources.
But file activity is important too, especially when a build step modifies shell profiles, startup scripts, or other files outside its expected working directory.
Ideally, I'd capture both. If I had to prioritize one for the first iteration, I'd start with network activity and then add file-system monitoring. What would you prioritize if you were building this?

Collapse
 
sameerqaiser17 profile image
Sameer Qaiser •

The line that hit me: "The dangerous part of a repo is not what you read. It is what runs the moment you type npm install."

This is the exact reason why "static analysis" for security is mostly a false sense of security. A static scanner is just a book report—it reads the README and the package.json but it can't see a postinstall hook dynamically pulling down a payload and executing it in memory.

Building the CodeBuild sandbox to actually press the button in a disposable box is a fantastic architecture.

But I'd love to push on the egress point you mentioned at the end. You noted that CodeBuild has outbound network by default, and a stricter build would pin egress to an allow-list. Realistically, how much of a risk is that? Even if you allow npm traffic, a malicious script can just exfiltrate your env variables by Base64 encoding them into a DNS request or a fake image URL.

I guess the real lesson is that even with a sandbox, assume the code is hostile. Do you strip all AWS credentials and env variables from the container before it starts the build?

Brilliant project. It's the exact kind of tooling the ecosystem needs right now.

Collapse
 
sarvar_04 profile image
Sarvar Nadaf AWS Community Builders •

Thanks! And I completely agree with your point: allowing only npm registry traffic doesn't automatically prevent data exfiltration. DNS tunnelling or requests to seemingly harmless external endpoints can still be abused.

In the current implementation, the focus is on isolated execution and capturing suspicious installation behaviour. I wouldn't consider the sandbox a complete security boundary yet.

On credentials, my approach would be to avoid passing AWS credentials, long-lived secrets, or unnecessary environment variables into the build environment in the first place. The CodeBuild service role should also have only the minimum permissions required, with no access to application secrets.

I think the next improvement should be combining restricted egress, tighter IAM permissions, and a clean environment with no sensitive data exposed to the untrusted build.

One question: would you also consider disabling DNS resolution except through a controlled resolver? I think that's an important part of addressing the exfiltration scenario you described.

Collapse
 
mp3sss31 profile image
mp3sss •

The install-time framing is the right one — static analysis can read every manifest and still miss a preinstall/postinstall hook that executes with the shell's full environment the moment npm runs. Running the install in a throwaway container and reading the real build log turns 'looks fine' into an observed behavior, which is the only signal a supply-chain hook leaves before it does damage. The same discipline applies to bundling a desktop app: a lockfile and script inspection help, but any untrusted dependency's lifecycle scripts should be treated as executable until they've been exercised in an isolated environment.

Collapse
 
sarvar_04 profile image
Sarvar Nadaf AWS Community Builders •

That's the gap I wanted to address with RepoPilot. Reading package.json and checking lifecycle scripts is useful, but it still doesn't tell us what actually happens during installation.

One thing I'm also careful about is that running something in a disposable container doesn't automatically make it safe. Network access and permissions still matter. In my implementation, I'm capturing the actual CodeBuild logs and checking them for suspicious execution patterns. It's a practical first layer, not a complete security guarantee.

I haven't extended it to desktop app packaging yet, but that's an interesting use case. Have you seen any particular lifecycle scripts or dependency behaviours causing problems in desktop app builds?

Collapse
 
maxbuildsdev profile image
Max Kaya •

The base64-wrapped install script inside the buildspec is a nice detail — I've hit exactly that failure mode where a repo's install command contains quotes and the buildspec YAML chokes, and most sandbox tutorials just say "escape it properly". One edge worth thinking about: CodeBuild has outbound network access, so a malicious postinstall that detects it's in a throwaway environment (checks for EC2 metadata endpoints, short uptime, etc.) could behave benignly in the sandbox and maliciously on a dev machine. Did you consider blocking egress by default and whitelisting only the registry hosts? That would also make the log evidence cleaner since the sandbox becomes the only network the code can talk to.

Collapse
 
sarvar_04 profile image
Sarvar Nadaf AWS Community Builders •

That's a valid concern, and I agree that outbound network access is one of the important gaps to consider. In the current implementation, I haven't added default egress blocking or registry-only whitelisting yet. The sandbox focuses on isolating execution and capturing what happens during installation.

Your point about environment-aware malware is also important. A malicious script could behave differently when it detects a disposable environment. Blocking outbound traffic by default and allowing only required registry endpoints would be a good next step. It would also reduce the chances of a script downloading and executing additional payloads.

I'd like to explore this further. Have you implemented registry-only egress restrictions with CodeBuild, or would you approach it through VPC endpoints and network firewall rules?

Collapse
 
paullovelace profile image
Paul Lovelace •

The 'looks fine' before/after is the whole argument in one screenshot — a reader literally cannot see a postinstall fire. I like that you didn't stop at the demo either; the base64-in-buildspec detail is the kind of thing you only learn by actually running it. One thing I'm curious about: you mentioned pip and Makefiles aren't covered yet — is that a 'same tool, different parser' job, or does the sandbox need to change for those?

Collapse
 
sarvar_04 profile image
Sarvar Nadaf AWS Community Builders •

I think the sandbox itself can remain mostly the same. The bigger change would be in how we trigger and inspect the execution.
For pip, we'd need to cover build backends and installation hooks. For Makefiles, we'd need to execute the relevant targets and inspect the commands and logs. So it's not just a parser change; the execution flow and detection rules would also need some work.
I'd prefer to keep the sandbox isolated and extend the execution layer rather than build a completely different environment for each ecosystem. That's something I'd like to explore next.