Security Lessons from the Modern JavaScript Stack

A reflection on recent security issues across Next.js, React Server Components, npm, and observability tooling

I used to treat security like a separate track: build the feature, then do a security pass near the end if there was time. That worked until it didn't. Over the last year or two, too many of the issues I've worried about were tied to normal implementation choices, not obviously "security" code: how a framework feature actually executes, what a dependency does during install, what gets logged by default, and who can query those logs a month later. Watching the ongoing discussions around Next.js, React Server Components, npm incidents, and observability tools like Axiom made this feel less theoretical and more like the actual day job.

Patterns I've Been Noticing

None of this is shocking in isolation. The shift for me was seeing the same failure shape repeat in different parts of the stack.

Framework convenience can hide security boundaries

Next.js is very good at making complicated things feel simple, which is usually great, but that convenience can blur boundaries that still matter. A server action, edge middleware, and a route handler can look adjacent in the codebase and still represent different trust assumptions, different attack surfaces, and different failure modes.

I still catch myself flattening all of it into "just app code" when a release is moving fast. That shortcut feels harmless in the moment, and then later you realize you treated very different surfaces as if they had the same rules.

React Server Components changed where sensitive data can leak

RSC made this easier to get wrong, at least for me, because you are writing what feels like UI code while touching values that were never meant to leave the server.

The leak is rarely one dramatic moment. It is usually drift over time: a small refactor, a prop flowing one level farther than intended, a debug value left in place, then weeks later you're tracing output and realizing a boundary moved quietly while everyone was focused on shipping.

npm incidents feel less exceptional than they used to

I don't think about npm risk the way I used to. I used to read incident writeups and mentally categorize them as unlucky outliers, but at this point they feel like normal ecosystem behavior at scale: typosquatting, compromised maintainers, questionable install hooks, and transitive trees that are much larger than they look from package.json.

That doesn't mean panic. It mostly changes defaults: I add dependencies more slowly, look harder at install-time behavior, and trust transitive code a lot less than I did a few years ago.

Observability vendors are part of the same threat model

Logging is another place where my instincts changed. Good telemetry is essential, but it can also become a quiet exfiltration path when teams optimize for visibility first and data hygiene later.

Whether it's Axiom or another vendor, I now treat observability as production data handling rather than developer convenience: decide what is allowed to leave the app, redact before egress, and keep access narrow by default. If a field would create a bad incident when leaked, it probably has no business being in raw logs.

Most security work is really systems thinking

The failures that worry me most are combinations of normal decisions: a reasonable framework default, a rushed release window, a dependency update that looked routine, a little extra debug output left on. Patching quickly still matters, but what has reduced stress more than anything is the boring repeatable work I used to skip: naming trust boundaries explicitly, reviewing dependency changes with intent, keeping privileges tighter than feels strictly necessary, and practicing incident response before you need it.

What I changed in my own workflow

I still do a quick pre-ship pass with a few plain questions: where does this run, what sensitive data does it touch, what gets logged, and what new code am I trusting through dependencies.

It usually adds a few minutes and used to feel like overhead; now it feels like buying back sleep.