← Back to posts

≈ 4 min

From “No Docker” to “Trust Boundaries”: How an AUR Supply-Chain Attack Changed My View of Local Development Environments

A few months ago I wrote an article describing my local PHP and WordPress development setup on Arch Linux.

The idea was simple:

one command → working project

No Docker.
No containers.
No extra abstraction layers.

Just native Linux services:

  • nginx
  • PHP-FPM
  • MariaDB
  • mkcert
  • Fish automation

For a long time it worked exactly as intended.

Fast.
Simple.
Predictable.

I still believe the technical solution itself is solid.

However, recent events forced me to rethink one important aspect of local development environments: trust boundaries.

The AUR supply-chain incident

In June 2026 the Arch Linux community discovered a large-scale AUR supply-chain attack.

What started as a handful of compromised packages quickly expanded into hundreds and eventually more than a thousand affected packages.

The interesting part was not the number.

The interesting part was the attack path.

Many developers assume that reviewing a PKGBUILD file is sufficient.

The reality turned out to be more complicated.

The malicious code was not always hidden directly in the PKGBUILD.

Instead the chain looked roughly like this:

AUR package

build process

npm dependency

preinstall hook

malicious payload

In other words, the trusted package executed code from another package manager, which executed code from yet another source.

This is a classic supply-chain problem.

Why my previous setup suddenly felt different

My original local environment was designed around productivity.

Native services provide several advantages:

  • maximum performance
  • easy debugging
  • minimal complexity
  • no container overhead

Those advantages still exist.

What changed was my threat model.

When I originally built the environment, I mostly thought about:

  • speed
  • simplicity
  • maintainability

After the AUR incident I started thinking about:

  • isolation
  • blast radius
  • trust boundaries
  • compromise containment

These are different optimization goals.

The npm realization

The AUR incident also highlighted something uncomfortable.

As PHP and WordPress developers, we often focus on operating system security while routinely executing enormous amounts of third-party code.

A typical workflow may include:

composer install
npm install

A modern JavaScript project can easily pull thousands of transitive dependencies.

Most developers never review them.

Most developers cannot realistically review them.

The real question becomes:

What happens if one of those dependencies becomes malicious?

Native development vs isolated development

My original setup executes build tools directly on the host system.

That means a compromised dependency potentially has access to:

  • SSH keys
  • browser sessions
  • local configuration files
  • API credentials
  • development secrets

Containers change that equation.

The purpose of Docker or DDEV is not only reproducibility.

It is also isolation.

Instead of:

npm install

running on the host machine,

the process runs inside a disposable environment with a significantly smaller attack surface.

The dependency may still be malicious.

The difference is that the consequences become easier to contain.

Docker is not a silver bullet

Containers do not magically solve supply-chain attacks.

A malicious package can still:

  • steal project secrets
  • access mounted source code
  • compromise the container itself

However, containers establish an important security boundary.

The attacker gains access to the environment.

Not necessarily the entire workstation.

That distinction matters.

What changed in my workflow

I still appreciate simple native environments.

I still believe Linux services are often easier to understand than layers of abstraction.

But today I see local development environments differently.

I no longer view Docker and DDEV purely as convenience tools.

I increasingly view them as containment tools.

The goal is no longer:

maximum performance at all costs.

The goal is:

reasonable performance with reduced blast radius.

Final thoughts

My previous article was written from the perspective of productivity.

This article is written from the perspective of trust.

The original setup was not wrong.

It simply optimized for a different problem.

The AUR incident was a reminder that modern development is built on an enormous chain of trust:

  • Linux distributions
  • package repositories
  • AUR
  • npm
  • Composer
  • PyPI
  • Docker images
  • GitHub Actions

No developer can audit all of it.

The best we can do is establish sensible trust boundaries and limit the damage when something eventually goes wrong.

Sometimes the most valuable feature of a development environment is not speed.

It is containment.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *