Developers, It's a good time to evaluate your threat model
Standard disclaimer applies. These are my personal views, not those of any employer.
Your threat model is stale
The world is changing. We know this. As developers we live this. New tools, new patterns, new problems. We build solutions for problems. And we use our experience with our tools to achieve that. But one area that we often forget is our own threat model. Now this is not limited to just developers, but anyone who often runs new software on their hardware, whether it's a phone, server, or workstation. If you install software (and that includes new versions of libraries for development) or run agentic solutions that do that for you, your threat model is likely in desperate need of review. If you don't have a threat model, it's time to think about it.
The bugpocalypse
AI started off as a slow burn in terms of value, but in recent months, it's hit an inflection point. Bugs. AI, especially the frontier models, are brilliant at picking up bugs. This is not a bad thing, but it has uncovered some critical vulnerabilities in core software we use. It's invalidated assumptions that many had around security. The assumption that open source is secure because the code is public and reviewed, along with the assumption that premium closed-source hardware and software providers rapidly capture vulnerabilities. Privilege escalation is the current flavour with not just Linux hit with a series of vulnerabilities (Copy Fail, Dirty Frag, Fragnesia), but also Apple with an M5 kernel memory corruption exploit. The tools we use every day are vulnerable, and we are in a liminal space while all projects and solutions find means to handle the increasing rate of bug and vulnerability resolution.
Now some have the assumption that these are coming from Mythos, and therefore should be handled internally by the organisations that provide the software. There is some truth to that. But the capability gap between restricted and public models is not as wide as it might seem. With the right harness, public models, whether frontier or open source, can action the same research. (HTTP Terminator) If not now, then very soon. Who knows what has been found yet not disclosed, or by whom, and to what end?
Accelerated cascading compromise
There is a common belief in tech enthusiast circles. One does not need anti-virus software. Careful internet usage is all you need to remain safe on the internet. This is while zero days keep popping up with little to no user interaction required to infect a system. Now this suggestion completely ignores the developer angle. Developers pull new software onto their machines every day. New feature needs a new library? Pull from npm/PyPI/Cargo/etc. New version? Pull again. Need a provider for Terraform? Pull some more code. Developers are always pulling unfamiliar code onto their machines. Restricting to only known packages does not work as there are too many transient packages to consider, and there is a wave of worms hitting popular libraries on a regular basis. (Mini Shai-Hulud hits TanStack) It's not much of a stretch for an organised group to prepare worms that leverage privilege escalation bugs like Dirty Frag. Pair that with a previously compromised CI/CD pipeline and you get a very damaging attack against organisations. One that could be incredibly persistent at a global scale. Agentic engineering will accelerate this, where patches on popular open source solutions will be pulled, evaluated, and exploited by agents before the maintainers have had a chance to respond.
The PC Security Channel on YouTube demonstrates real execution of prevalent malware in the wild. It's a practical resource for understanding how these attacks actually work beyond the theoretical.
As developers, we can't just stop using libraries. Even if AI was good enough to replace libraries with bespoke solutions, it still introduces its own security risks and would be a maintenance nightmare. On top of that, the development process is changing. The world is moving towards an agentic approach to engineering. And with that, autonomous agents download libraries, consume websites (which could contain prompt injections), and make decisions without any user interaction. It's clear that the current agentic tools we use don't have the best protections in place, often relying on system prompts to limit the functionality of an agent. Agentic engineering broadens the attack surface of security vulnerabilities on top of the general increased risk due to the environment we work in today.
Things to consider
This is not a framework. The environment we work in is changing rapidly. At best, these are suggestions that can be applied to help limit one's exposure risk. It will not eliminate all risk, and one should evaluate the environment on a regular basis. These are the thoughts of a developer with an interest in cyber security. I'm not a security professional, and nothing here constitutes professional security advice. Many of these suggestions may simply not be applicable to you, whether it's too hard, too expensive, or not applicable for your use cases. The main thing is to be intentional about your threat model. It's also important to note, I'm only talking about the development threat model. Mobile is another vector you should consider among others. Many of the problems translate, but principles may differ.
My attack surface
The first step in evaluating your threat model is to understand the attack surface. Mine is unique to my use cases but hopefully it is a good example that can translate. I develop on NixOS using Rust and TypeScript. I use OpenTofu and Docker Compose for infrastructure. I use OpenCode for agentic engineering. My code goes through merge requests with checks running on GitLab pipelines, using runners I host on a Kubernetes cluster in my homelab. The GitLab instance is the public offering. I host my own repositories in Docker on my Unraid box. My applications deploy to AWS for cloud focused solutions, and Docker on my homelab for internal workloads.
With this, I have various risks in my development flow.
My workstation. Agents run on it with my credentials. I pull libraries that execute code daily. It's bare metal. No easy reset.
GitLab Runners. Merge requests run checks on my self-hosted K8s runners. Anyone with repo access can submit code that executes on my network. The GitLab instance is public. My runners are not.
My agents. OpenCode pulls dependencies and consumes websites without my interaction. A poisoned prompt or a bad dependency is an entry point. It runs with my access.
Third party applications. Self-hosted apps on my Unraid box. Each one is an exposed service with its own attack surface. Web interfaces, APIs, authentication endpoints. Some may run unpatched versions.
IoT devices. Run unpatched firmware or vulnerable Linux versions. Exposed on the network. Notorious for poor security.
My network. If it's flat, every device can reach every other device. K8s runners, credentials, family devices. All reachable from any single compromised point.
Impact of a compromise
Understanding the attack surface is one thing. Understanding what's at stake if a vector is exploited is another. Here's what a compromise would mean for each.
My workstation. Private documents, AWS access tokens, the full scope of what I work on. Bare metal means I can't just blow it away and rebuild. And how do I verify it's clean?
GitLab Runners. Shipped code is poisoned. Supply chain trust is broken. Deployment credentials exposed.
My agents. Whatever the agent can reach is exposed. My workstation, my network, my credentials. All without my interaction.
Third party applications. A compromised app gives a foothold on my network. My internal Docker repos are on that Unraid box.
IoT devices. I don't want to think what I would need to do if my heatpump was compromised. I doubt I would be able to reflash that firmware. A permanently compromised device is a persistent foothold on the network.
My network. The blast radius of a flat network would take weeks to recover from. And that's assuming you can recover without tearing down and starting from scratch.
Sandbox where you can
Agents run on your machine. Your machine has your credentials, access tokens, keys to ssh into servers, etc. Agents pull dependencies, and consume websites without your interaction. If you're going to run them on bare metal, you need something to keep it contained away from everything on your machine. Containerise. Pick your poison. Whether Podman or docker. By containerising your agents, you prevent them from accessing anything you don't want them to on your machine.
This is not a silver bullet. Your kernel is still shared. With Copy Fail like bugs, you are still exposed, but you have reduced your exposure substantially.
If you really want to elevate your security, but still constrained to your one development machine, Vagrant. Vagrant is an under appreciated tool for spinning up VMs with code, much like terraform for infrastructure. Is it perfect? Nope. There is some overhead that comes from running a VM but as we are finding, there is always compromise. And if you don't want to compromise security, performance might be a lever you can pull.
Now it's important to note that this is containment, not prevention. It's not going to stop a compromise, but it will reduce the blast radius to just the compute that the agent, or your tools have access to.
Make your workstation disposable
So you sandboxed your agents but you still ended up compromised. Or maybe your system has been in use for 3 years, who's to say that your system is still secure? What now?
If you can't verify it's clean, make verification irrelevant. Dispose, and rebuild. This is more targeted at developers using Linux. Use a declarative distro like NixOS. If your Linux box is compromised, just delete it, refresh from config. Done. Just ensure your backup process is in order and tested. If the thought of rebuilding your OS is daunting, one thing I have done is virtualise my OS. Proxmox as my hypervisor, giving me the ability to take regular snapshots of my system. That way if I'm compromised, (or I just did something stupid with my Nix config), load from snapshot. This works for Windows systems too.
Move code off your workstation
This one is an extension of the previous two and focuses on the one thing neither sandboxing nor disposable can solve. Use a different device for your development flow. Ideally one with little to no network access beyond the internet. You could have an ideal way to protect, and recover your main machine. But can you protect the rest of your network? Phones, laptops, tablets, routers, switches, printers, iot devices. With AI, you cannot assume that infections will apply the same recipe to infecting other devices. AI can be used to investigate and apply bespoke solutions to compromising devices on the fly.
If there was just one thing you did to protect yourself, it would be this. Find a budget VM provider running in a cloud somewhere with decent connectivity. If that's not an option, you can pick up a second hand computer, and an old router, and build a really simple subnet on your network that locks that device down, away from your network.
Subnet, subnet, subnet
Speaking of subnets, when it comes to running services and gitlab runners, the cost to host in the cloud compared to locally is not an option for me. So instead I do have to make use of the hardware I have on hand. Free runners on gitlab just don't have the resources available to build Rust applications, and even if the memory was not an issue, the time to build is. Along with that like any homelaber, I have a few resources I host for my own use, Immich, ntfy, etc. To support this I break everything down into subnets. Every group of resources gets its own subnet. Kubernetes? Subnet. Immich? Internal subnet via Docker + reverse proxy. It does not need internet. Everything gets its own subnet with only the network access it needs. If a service I host is compromised but it never had network access? No harm done. And even if it did, the risk is only to the scope of the application itself.
With subnets, VLANs are your friend. I initially shied away from them. But don't be like me and try running 7 different physical networks, it just does not scale. Use VLANs.
Make yourself the smallest target possible
Don't expose what you don't need to. Both internally and externally. Every port forward, every general use subnet, every service you run that has internet access is a threat. Now this really comes down to your threat model, but have a think. Do you really need to expose that service externally? Does it need to be accessible by other people or could a VPN/Tailscale be used?
It's important to note that no one will have a perfectly secure network. Everyone has to expose something to the world. We have to be pragmatic (A talk for a later date). But we should really ask not can I do this? rather do I need this? and is there a better way? The principle however remains the same. Keep yourself small. Smaller targets are harder to hit.
Be careful with SBCs and firmware-dependent devices
Getting firmware and patches into mainline Linux can be challenging. x86 is consistent. An OS built for x86 generally will work on most if not all x86 devices. ARM and RISC-V are not. Every SBC manufacturer has their own firmware and patches. The ecosystem is not nearly as mature as x86. And that's OK. They do what they can. While some SBC manufacturers are very good at maintaining their own distros with patched firmware, not all manufacturers can. Maintaining software is not a cheap endeavor. And even if there are updates out there, how often do you log into that Raspberry Pi and update it? I know I have a fair few SBCs whose kernel is stuck in a fork from 2021.
Now it's not all doom and gloom. Raspberry Pis are a golden standard in software support here. If in doubt, a Raspberry Pi won't let you down. But even if you do decide to use that SBC with an unsupported image, take a look at Armbian. Armbian is not perfect but they generally try to provide images for many (not all) SBCs and fill in that gap in software support.
Closing
The world is changing. Faster than we can keep up. What we got away with before isn't good enough now. We can't predict tomorrow. But we can prepare.
Take a few hours to think about your threat model. What matters to you. What you can't afford to lose. And what you can do about it.