Red and orange scratchy brushstrokes over black with olive green strokes along the bottom

Supply Chains

lots of steps


The other day I was at a meetup listening to talks. The opening one hooked me, using modern browser APIs to reduce the amount of packages we vendor in. The following one struck me, the speaker said they are the CTO of a firm because they were the only founder who could write code. And then proceeded to give a talk on the recent supply chain attack with Axios, while stating they didn’t know what the library was or what a supply chain attack is. Now they could have been doing a bit, but I took personal offense as someone who loves this craft and spent their entire 20s in this game refining it. So here’s something less subliminal than the recent disappointing triple drop of the Iceman, Maid of Honor, and Habibti albums from our favorite Degrassi actor. This is America, so being fair-and-balanced, the overly dramatic beat on What Did I Miss hits.

So what is a Supply Chain Attack?

Supply Chain

I’m going to use a non-software example. The plain black t-shirts I wear nearly every day. There are a lot of steps involved to get it into my closet.

Someone in the Global South needs to procure land for agriculture. Then they need to find seeds for the cotton plants, till the fields, cover the future crop with dirt, purchase fertilizer, figure out how to irrigate it, and so on.

Once they are grown, it needs to be harvested and run through a gin. From there weave it into fabric.

Then all that cloth needs to be refined into articles of clothing. After that, put on a hauler to move into one of Bezos-uncle’s warehouses.

Once it’s in storage, it then has to go to either a physical or digital storefront. Drilling into the latter route, spinning up the e-commerce platform is its own step. Followed by actually getting the product delivered to my doorstep.

That entire process is what we call a Supply Chain. All the linked-together steps that are involved in getting a product in the hands of the customer.

Software Supply Chain

For the bulk of my professional career, I’ve written a lot of Java and Python with a fair amount of JavaScript.

None of those have as robust a std lib as my two beloveds, Go and Deno. So we would import packages like Spring, Django, and React to help produce software at industry scale.

Drilling in on Django.

Let’s take this simple model to represent an Order

from django.db import models

class Order(models.Model):
    product = models.CharField(max_length=255)
    quantity = models.IntegerField()
    status = models.CharField(max_length=50)

    def __str__(self):
        return f"{self.product} - {self.status}"

A Serializer to shape the data.

from rest_framework import serializers
from .models import Order

class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = Order
        fields = ['id', 'product', 'quantity', 'status']

We can then build on top of it to expose it via an API.

from rest_framework import viewsets
from .models import Order
from .serializers import OrderSerializer

class OrderViewSet(viewsets.ModelViewSet):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer

Under the hood, it abstracts away work that looks like this.

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Order
from .serializers import OrderSerializer

class OrderListView(APIView):

    def get(self, request):
        orders = Order.objects.all()
        serializer = OrderSerializer(orders, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = OrderSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class OrderDetailView(APIView):

    def get(self, request, pk):
        order = Order.objects.get(pk=pk)
        serializer = OrderSerializer(order)
        return Response(serializer.data)

    def put(self, request, pk):
        order = Order.objects.get(pk=pk)
        serializer = OrderSerializer(order, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        order = Order.objects.get(pk=pk)
        order.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

Starting from the bottom up. Serving the REST API requires djangorestframework. Notice the first word in the compound. We can’t use that package without also pip installing Django. Luckily Django is predominantly built off the Python std lib. But it still pulls in asgiref and sqlparse as transitive dependencies. And if you are deploying to Microslop W!nd0ws, it also vendors in tzdata.

Ignoring the development and deployment environments. Just to make an API available to my customer. I need to bring in djangorestframework, Django, asgiref, sqlparse, the std lib, and the Python runtime. Modifying any of those impacts the experience of the layers above it.

Attack

Going back to the example with my shirts. Compromising any link in that chain impacts the experience I have as the end customer. A bad actor could mess with the seeds, their nutrients, or water supply. They could compromise the lanes of travel or machinery.

The result can be everything from a minor inconvenience, reducing the supply thus driving up prices (assuming demand stays constant), to a serious threat. What if something hypothetically introduced a biological agent in that series of steps and there’s suddenly a potential public health crisis.

Now let’s flip back to software.

It’s all about layers.

Compromising djangorestframework impacts every REST API it is being used to serve.

Compromising Django impacts every application built with it.

Compromising asgiref or sqlparse impacts every application that vendors it in, like Django.

Compromising the Python std lib means we have bigger problems we need to address.

Looping back, Axios. It is an HTTP client library in the JS ecosystem that is an alternative to the native Fetch API with some quality of life features. Some pretty important libraries and frameworks are built on top of it.

Wrap Up

These words aren’t complicated. It’s literally three elementary-level vocab terms.

This isn’t limited to physical products and software. See also: the leaks through Graham v. Lamar.