I just want to straighten the perspective on things a bit.
Technically there's no web site that doesn't "run code". There's always code involved. It's code all the way down, from the web server to the file system drivers, the operating system and so on.
While it's true that static files reduce attack surface, we need to think deeply why is that, and design intelligent dynamic systems that have the security of static ones.
And ultimately it's about input, and how input is treated. It doesn't matter how complex code you run, if you accept no input, you can't attack that system. Of course with no input you can't even figure out which page to show. So there's always input, even for static sites. But I'm trying to point our attention to what's the major distinction here.
I think they were merely implying that the website codebase doesn't have anything executable. I can't imagine anyone reading HN thinks that serving websites, generally, doesn't require a giant pile of code at many levels. Sure it doesn't eliminate the server-side security concerns of the entire deployment, but probably would from the entire website codebase; many people run static websites in read-only caches. At that point, the security concerns are more in the system/ops/network realm than the site itself.
Sure. Heartbleed for example was a data exposure vulnerability that leaked data from the HTTPS stack, which exposed private keys and plaintext from other inflight requests. Any real world system that handles HTTP requests, at minimum, has to do some reading of config data, some reading of data to serve up, and some writing to log files.
The point is that a static web server does that and only that. A dynamic web server is one that does that and more.
Just to build on this, there are RCEs that involve overflowing headers; Go just had one not that long ago. There's plenty of inputs on a GET request. You still need to do proper security on a static site.
That's because the nginx inputs have a much more homogeneous type than your random django-based system.
I'm not sure there's anything you can learn from that. Some use-cases just lead to more secure software than others, and this is a completely non-actionable piece of information.
As they said, it's attack surface. The static site does one thing; the Django site does more things. This is the use-case difference you're talking about: the more your code does, the more likely it is to have vulnerabilities. And it's actionable: make your code do as few things as possible.
Perhaps we could describe a dynamic website as being a static website + extra (i.e. the dynamic stuff).
As mentioned in the article, every dynamic website will also need some static assets (the .js files, images, etc.)
So, it seems like a dynamic website will always have greater attack surface area than a static one, by definition. It will have all of the static site surface area, plus some more.
----
I wonder if there is room for a language that is not as general as JS, but can still be used to add dynamism to a website. So, you don't have to be stuck in the "it's Turing complete, so we can't be sure it's well-behaved before running it" situation.
Perhaps CSS is kinda turning into that, these days.
Though maybe CSS will become Turing complete too, at this rate (:
Technically there's no web site that doesn't "run code". There's always code involved. It's code all the way down, from the web server to the file system drivers, the operating system and so on.
While it's true that static files reduce attack surface, we need to think deeply why is that, and design intelligent dynamic systems that have the security of static ones.
And ultimately it's about input, and how input is treated. It doesn't matter how complex code you run, if you accept no input, you can't attack that system. Of course with no input you can't even figure out which page to show. So there's always input, even for static sites. But I'm trying to point our attention to what's the major distinction here.