← Back to context

Comment by jFriedensreich

2 days ago

We just can't trust dependencies and dev setups. I wanted to say "anymore" but we never could. Dev containers were never good enough, too clumsy and too little isolation. We need to start working in full sandboxes with defence in depth that have real guardrails and UIs like vm isolation + container primitives and allow lists, egress filters, seccomp, gvisor and more but with much better usability. Its the same requirements we have for agent runtimes, lets use this momentum to make our dev environments safer! In such an environment the container would crash, we see the violations, delete it and dont' have to worry about it. We should treat this as an everyday possibility not as an isolated security incident.

This is the security shortcuts of the past 50 years coming back to bite us. Software has historically been a world where we all just trust each other. I think that’s coming to an end very soon. We need sandboxing for sure, but it’s much bigger than that. Entire security models need to be rethought.

  • This assumes that we can get a locked down, secure, stable bedrock system and sandbox that basically never changes except for tiny security updates that can be carefully inspected by many independent parties.

    Which sounds great, but the way things work now tend to be the exact opposite of that, so there will be no trustable platform to run the untrusted code in. If the sandbox, or the operating system the sandbox runs in, will get breaking changes and force everyone to always be on a recent release (or worse, track main branch) then that will still be a huge supply chain risk in itself.

    • The secure boot "shim" is a project like this. Perhaps we need more core projects that can be simple and small enough to reach a "finished" state where they are unlikely to need future upgrades for any reason. Formal verification could help with this ... maybe.

      https://wiki.debian.org/SecureBoot#Shim

    •   > This assumes that we can get a locked down, secure, stable bedrock system and sandbox that basically never changes except for tiny security updates that can be carefully inspected by many independent parties.
      

      For the most part you can. Just version pin slightly-stale versions of dependencies, after ensuring there are no known exploits for that version. Avoid the latest updates whenever possible. And keep aware of security updates, and affected versions.

      Don't just update every time the dependency project updates. Update specifically for security issues, new features, and specific performance benefits. And even then avoid the latest version when possible.

      3 replies →

    • >Which sounds great, but the way things work now tend to be the exact opposite of that, so there will be no trustable platform to run the untrusted code in.

      This is the problem with software progressivism. Some things really should just be what they are, you fix bugs and security issues and you don't constantly add features. Instead everyone is trying to make everything have every feature. Constantly fiddling around in the guts of stuff and constantly adding new bugs and security problems.

    • > This assumes that we can get a locked down, secure, stable bedrock system and sandbox that basically never changes except for tiny security updates that can be carefully inspected by many independent parties.

      Not really. You should limit the attack surface for third-party code.

      A linter running in `dir1` should not access anything outside `dir1`.

  • The NIH syndrome becoming best practice (a commenter below already says they "vibe-coded replacements for many dependencies") would also save quite a few jobs, I suspect. Fun times.

    • I've been doing that too. The downside is it's a lot of work for big replacements.

  • I've been thinking the same thing. And it's somewhat parallel to what happened to meditation vs. drugs. In the old world the dangerous insights required so many years of discipline that you could sort of trust that the person getting the insight would be ok. But then any idiot can get the insight by just eating some shrooms and oops, that's a problem. Mostly self-harm problem in that case. But the dynamic is somewhat similar to what's happening now with LLMs and coding.

    Software people could (mostly) trust each other's OSS contributions because we could trust the discipline it took in the first place. Not any more.

    • In the old world the dangerous insights required so many years of discipline that you could sort of trust that the person getting the insight would be ok. But then any idiot can get the insight by just eating some shrooms and oops, that's a problem.

      I would think humans have been using psychedelics since before we figured out meditation. Likely even before we were humans.

      1 reply →

  • What we need is accountability and ties to real-world identity.

    If you're compromised, you're burned forever in the ledger. It's the only way a trust model can work.

    The threat of being forever tainted is enough to make people more cautious, and attackers will have no way to pull off attacks unless they steal identities of powerful nodes.

    Like, it shouldn't be a thing that some large open-source project has some 4th layer nested dependency made by some anonymous developer with 10 stars on Github.

    If instead, the dependency chain had to be tied to real verified actors, you know there's something at stake for them to be malicious. It makes attacks much less likely. There's repercussions, reputation damage, etc.

    • > The threat of being forever tainted is enough to make people more cautious

      No it's not. The blame game was very popular in the Eastern Block and it resulted in a stagnant society where lots of things went wrong anyway. For instance, Chernobyl.

    • > What we need is accountability and ties to real-world identity.

      Who's gonna enforce that?

      > If you're compromised, you're burned forever in the ledger.

      Guess we can't use XZ utils anymore cause Lasse Collin got pwned.

      Also can't use Chalk, debug, ansi-styles, strip-ansi, supports-color, color-convert and others due to Josh Junon also ending up a victim.

      Same with ua-parser-js and Faisal Salman.

      Same with event-stream and Dominic Tarr.

      Same with the 2018 ESLint hack.

      Same with everyone affected by Shai-Hulud.

      Hell, at that point some might go out of their way to get people they don't like burned.

      At the same time, I think that stopping reliance on package managers that move fast and break things and instead making OS maintainers review every package and include them in distros would make more sense. Of course, that might also be absolutely insane (that's how you get an ecosystem that's from 2 months to 2 years behind the upstream packages) and take 10x more work, but with all of these compromises, I'd probably take that and old packages with security patches, instead of pulling random shit with npm or pip or whatever.

      Though having some sort of a ledger of bad actors (instead of people who just fuck up) might also be nice, if a bit impossible to create - because in the current day world that's potentially every person that you don't know and can't validate is actually sending you patches (instead of someone impersonating them), or anyone with motivations that aren't clear to you, especially in the case of various "helpful" Jia Tans.

    • Accountability is on the people using a billion third party dependencies, you need to take responsibility for every line of code you use in your project.

      2 replies →

    • There is no need of that bullshit. Guix can just set an isolated container in seconds not touching your $HOME at all and importing all the Python/NPM/Whatever dependencies in the spot.

"Anymore" is right though. This should be a call to change the global mindset regarding dependencies. We have to realize that the "good ol days" are behind us in order to take action.

Otherwise people will naysay and detract from the cause. "It worked before" they will say. "Why don't we do it like before?"

DISA STIG already forbids use of the EPEL for Red Hat Enterprise Linux. Enterprise software install instructions are littered with commands to turn off gpgcheck and install rpm's from sourceforge. The times are changing and we need cryptographically verifiable guarantees of safety!

Would value your opinion on my project to isolate creds from the container:

https://github.com/calebfaruki/tightbeam https://github.com/calebfaruki/airlock

This is literally the thing I'm trying to protect against.

  • I would split the agent loop totally from the main project of tightbeam, no one wants yet another new agent harness we need to focus on the operational problems. Airlock seems interesting in theory but its really hard to believe this could capture every single behaviour of the native local binaries, we need the native tools with native behaviour otherwise might as well use something like MCP. I would bet more on a git protocol proxy and native solutions for each of these.

So... I'm working on an open source technology to make a literal virtual machine shippable i.e. freezing everything inside it, isolated due to vm/hypervisor for sandboxing, with support for containers too since it's a real linux vm.

The problems you mentioned resonated a lot with me and why I'm building it, any interest in working to solve that together?: https://github.com/smol-machines/smolvm

  • Thanks for the pointer! Love the premise project. Just a few notes:

    - a security focused project should NOT default to train people installing by piping to bash. If i try previewing the install script in the browser it forces download instead of showing as plain text. The first thing i see is an argument

    # --prefix DIR Install to DIR (default: ~/.smolvm)

    that later in the script is rm -rf deleting a lib folder. So if i accidentally pick a folder with ANY lib folder this will be deleted.

    - Im not sure what the comparison to colima with krunkit machines is except you don't use vm images but how this works or how it is better is not 100% clear

    - Just a minor thing but people don't have much attention and i just saw aws and fly.io in the description and nearly closed the project. it needs to be simpler to see this is a local sandbox with libkrun NOT a wrapper for a remote sandbox like so many of the projects out there.

    Will try reaching you on some channel, would love to collaborate especially on devX, i would be very interested in something more reliable and bit more lightweight in placce of colima when libkrun can fully replace vz

    • Love this feedback, agree with you completely on all of it - I'll be making those changes.

      1. In comparison with colima with krunkit, I ship smolvm with custom built kernel + rootfs, with a focus on the virtual machine as opposed to running containers (though I enable running containers inside it).

      The customizations are also opensource here: https://github.com/smol-machines/libkrunfw

      2. Good call on that description!

      I've reached out to you on linkedin

    • What is the alternative to bash piping? If you don't trust the project install script, why would you trust the project itself? You can put malware in either.

      8 replies →

  • Probably on the side of your project, but did you try SmolBSD? <https://smolbsd.org> It's a meta-OS for microVMs that boots in 10–15 ms.

    It can be dedicated to a single service (or a full OS), runs a real BSD kernel, and provides strong isolation.

    Overall, it fits into the "VM is the new container" vision.

    Disclaimer: I'm following iMil through his twitch streams (the developer of smolBSD and a contributor to NetBSD) and I truly love what he his doing. I haven't actually used smolBSD in production myself since I don't have a need for it (but I participated in his live streams by installing and running his previews), and my answer might be somewhat off-topic.

    More here <https://hn.algolia.com/?q=smolbsd>

    • First time hearing about it, thanks for sharing!

      At a glance, it's a matter of compatibility, most software has first class support for linux. But very interesting work and I'm going to follow it closely

  • What would the advantage of this be compared to using something like a Firecracker backend for containerd?

    • Run locally on macs, much easier to install/use, and designed to be "portable" meaning you can package a VM to preserve statefulness and run it somewhere else.

      worked in AWS and specifically with firecracker in the container space for 4 years - we had a very long onboarding doc to dev on firecracker for containers... So I made sure to focus on ease of use here.

We need programming languages where every imported module is in its own sandbox by default.

  • Now is probably a pretty good time to start a capabilities-based language if someone is able to do that. I wish I had the time.

  • Java had that from v1.2 in the 1990s. It got pulled out because nobody used it. The problem of how to make this usable by developers is very hard, although maybe LLMs change the equation.

  • We have one where thats possible: workerd (apache 2.0) no new language needed just a new runtime

    • I mean, the sandboxing aspect of a language is just one thing.

      We should have sandboxing in Rust, Python, and every language in between.

  • just sandbox the interpreter (in this case), package manager and binaries.

    u can run in chroot jail and it wouldnt have accessed ssh keys outside of the jail...

    theres many more similar technologies aleady existing, for decades.

    doing it on a per language basis is not ideal. any new language would have to reinvent the wheel.

    better to do it at system level. with the already existing tooling.

    openbsd has plege/unveil, linux chroot, namespaces, cgroups, freebsd capsicum or w/e. theres many of these things.

    (i am not sure how well they play within these scenarios, but just triggering on the sandboxing comment. theres plenty of ways to do it as far as i can tell...)

    • What if I wanted to write a program that uses untrusted libraries, but also does some very security sensitive stuff? You are probably going to suggest splitting the program into microservices. But that has a lot of problems and makes things slow.

      The problem is that programs can be entire systems, so "doing it at the system level" still means that you'd have to build boundaries inside a program.

      2 replies →

  • Or just make side effects explicit in the type system through monads or algebraic effects.

> Dev containers were never good enough, too clumsy and too little isolation.

I haven't kept up with the recent exploits, so a side question: Have any of the recent supply chain attacks or related exploits included any escapes from basic dev containers?

Defense-in-depth on dev machines is useful but doesn't address the actual attack path here. The credential that was stolen lived in CI, not on a dev laptop — Trivy ran with PyPI publisher permissions because that's standard practice for "scanner before publish."

The harder problem is that CI pipelines routinely grant scanner processes more credential access than they need. Trivy needed read access to the repo and container layers; it didn't need PyPI publish tokens. Scoping CI secrets to the minimum necessary operation, and injecting them only for the specific job that needs them rather than the entire pipeline, would have contained the blast radius here.

That's no solution. If you can't trust and/or verify dependencies, and they are malicious, then you have bigger problems than what a sandbox will protect against. Even if it's sandboxed and your host machine is safe, you're presumably still going to use that malicious code in production.

  • I'm supportive of going further - like restricting what a library is able to do. e.g. if you are using some library to compute a hash, it should not make network calls. Without sub-processes, it would require OS support.

    • In type system theory I think what you're looking for is "effect systems".

      You make the type system statically encode categories of side-effects, so you can tell from the type of a function whether it is pure computation, or if not what other things it might do. Exactly what categories of side-effect are visible this way depends on the type system; some are more expressive than others.

      But it means when you use a hash function you can know that it's, eg, only reading memory you gave it access to and doing some pure computation on it.

    • Which exists: pledge in OpenBSD.

      Making this work on a per-library level … seems a lot harder. The cost for being very paranoid is a lot of processes right now.

      1 reply →

  • That's exactly what a sandbox is designed for. I think you're overly constraining your view of what sort of sandboxing can exist. You can, for example, sandbox code such that it can't do anything but read/write to a specific segment of memory.

  • Except that LiteLLM probably got pwned because they used Trivy in CI. If Trivy ran in a proper sandbox, the compromised job could not publish a compromised package.

    (Yes, they should better configure which CI job has which permissions, but this should be the default or it won't always happen)

> In such an environment the container would crash, we see the violations, delete it and dont' have to worry about it.

This is the interesting part. What kind of UI or other mechanisms would help here? There's no silver bullet for detecting and crashing on "something bad". The adversary can test against your sandbox as well.

> We need to start working in full sandboxes with defence in depth that have real guardrails

Happily sandboxing almost all third-party tools since 2025. `npm run dev` does not need access to my full disk.

Sandboxes yes, but who even added the dependency? Half the projects I see have requirements.txt written by Copilot. AI says "add litellm", dev clicks accept, nobody even pins versions.

Then we talk about containment like anyone actually looked at that dep list.

  > We just can't trust dependencies and dev setups.

In one of my vibe coded personal projects (Python and Rust project) I'm actually getting rid of most dependencies and vibe coding replacements that do just what I need. I think that we'll see far fewer dependencies in future projects.

Also, I typically only update dependencies when either an exploit is known in the current version or I need a feature present in a later version - and even then not to the absolute latest version if possible. I do this for all my projects under the many eyes principal. Finding exploits takes time, new updates are riskier than slightly-stale versions.

Though, if I'm filing a bug with a project, I do test and file against the latest version.

  • > In one of my vibe coded personal projects (Python and Rust project) I'm actually getting rid of most dependencies and vibe coding replacements that do just what I need. I think that we'll see far fewer dependencies in future projects.

    No free lunch. LLMs are capable of writing exploitable code and you don’t get notifications (in the eg Dependabot sense, though it has its own problems) without audits.

I agree in general, but how are you ever upgrading any of that? Could be a "sleeper compromise" that only activates sometime in the future. Open problem.

  • A sleeper compromise that cannot execute can still not reach its goal. Generally speaking outdated dependencies without known compromise in a sandbox are still better than the latest deps with or without sandbox.

Containers prevent this kind of info stealing greatly, only explicitly provided creds would be leaked.

  • Containers can mean many things, if you mean plain docker default configured containers then no, they are a packaging mechanism not safe environment by themselves.

The trouble with sandboxing is that eventually everything you want to access ends up inside the sandbox. Otherwise the friction is infuriating.

I see people going in the opposite direction with "dump everything in front of my army of LLMs" setups. Horribly insecure, but gotta go fast, right?

strongly agree. we keep giving away trust to other entities in order to make our jobs easier. trusting maintainers is still better than trusting a clanker but still risky. We need a sandboxed environment where we can build our software without having to worry about these unreliable factors.

On a personal note, I have been developing and talking to a clanker ( runs inside ) to get my day to day work done. I can have multiple instances of my project using worktrees, have them share some common dependencies and monitor all of them in one place. I plan to opensource this framework soon.

This stuff already exists - mobile phone sandboxed applications with intents (allow Pictures access, ...)

But mention that on HN and watch getting downvoted into oblivion: the war against general computation, walled gardens, locked down against device owners...

  • You are not being downvoted because the core premise is wrong but because your framing as a choice between being locked out of general purpose computing vs security is repeating the brainwashing companies like apple and meta do to justify their rent-seeking locking out out of competitors and user agency. We have all the tools to build safe systems that don't require up front manifest declaration and app store review by the lord but give tools for control, dials and visibility to the users themselves in the moment. And yes, many of these UIs might look like intent sheets. The difference is who ultimately controls how these Interfaces look and behave.