3/9/2026 ~ 6 min read

The Frontend Is a Boundary


I was reading a message board the other day — one of those internal engineering forums where people ask questions and other people answer with varying degrees of confidence. Someone asked about security considerations for frontend frameworks. Standard enough question.

One of the answers stopped me cold:

“Regarding security, we don’t usually have to worry about it in the frontend. React doesn’t let you accidentally inject HTML, and most other issues are solved in the backend.”

There’s a version of this that’s almost true. And that’s what makes it dangerous.


The narrow claim isn’t wrong. Most modern frontend frameworks — React, Angular, Vue, Lit, Svelte — escape output by default. If you render user input through their standard templating, you’re protected from a whole class of cross-site scripting attacks without thinking about it. That’s a genuine engineering accomplishment, and it matters. A decade ago, that wasn’t a given.

But “the framework handles XSS by default” and “we don’t have to worry about security in the frontend” are two very different statements. The first is a fact about a tool. The second is a posture about responsibility. And posture is where incidents live.


Here’s what sits underneath that confident shrug — the things that framework defaults don’t cover, regardless of which framework you’re using.

Every major framework has an escape hatch for raw HTML injection. React calls it dangerouslySetInnerHTML. Angular has bypassSecurityTrustHtml. Vue has v-html. Svelte has {@html}. The names range from explicitly cautionary to casually permissive, but they all do the same thing — they turn off the safety that the original answer was leaning on entirely. And they get used. They get used in rich text editors, in markdown renderers, in CMS integrations, in any feature where someone needs to render content that isn’t plain text. The moment you reach for one of these, you’re back to hand-rolling your own XSS protection. If you believed you didn’t have to worry about it, you won’t.

URL injection is another one that slips past the mental model. Framework escaping doesn’t help you when a user-supplied string ends up in an href or src attribute. A javascript: URI will execute regardless of how carefully the framework escapes angle brackets, because it’s not an escaping problem — it’s a trust boundary problem. The string is syntactically valid. It’s just semantically hostile.

Then there’s the supply chain. The average frontend project pulls in hundreds — sometimes thousands — of transitive dependencies through npm or whatever package manager the ecosystem favors. Every one of those is a trust decision. The event-stream incident. The ua-parser-js compromise. The colors and faker sabotage. These weren’t backend vulnerabilities. They were frontend supply chain attacks that executed in the browser, in CI pipelines, in build processes. “The backend handles security” doesn’t mean anything when the attack surface is your node_modules directory.

Auth token storage is an architectural decision that the frontend team makes — or more often, a decision that gets made by default because nobody on the team thought it was their responsibility to think about it. Storing JWTs in localStorage makes them accessible to any script running on the page, including scripts injected through those supply chain dependencies I just mentioned. httpOnly cookies exist specifically because the browser can enforce a boundary that JavaScript cannot. But choosing the right storage mechanism requires someone on the frontend to understand why it matters. If they’ve been told they don’t have to worry about security, they won’t ask the question.

Content Security Policy headers. CORS configuration. eval() and dynamic code generation in plugin architectures. postMessage handlers that accept messages from any origin. Open redirects in client-side routing. Sensitive data rendered in the DOM and then cached by the browser. Every one of these is a frontend concern. Every one of them lives outside the scope of “the framework escapes output by default.”


What bothers me about the original answer isn’t the technical gap — that’s fixable. Anybody can learn about dangerouslySetInnerHTML or javascript: URIs. What bothers me is the confidence. The word “usually.” The framing that positions security as something that belongs to another team, another layer, another part of the system.

Security doesn’t work that way. It’s not a feature that lives in one place. It’s a property of the whole system — the way structural integrity isn’t a property of the foundation or the walls or the roof but of how they all connect and bear load together. The frontend is a boundary — probably the most exposed boundary in the entire system, the surface that faces the open internet, that accepts user input, that renders content from sources you don’t control. Treating it as the one place where security isn’t your problem is like saying the front door doesn’t need a lock because the safe in the basement is sturdy.

I think about this through a biological lens sometimes. In living systems, the cell membrane isn’t a passive barrier — it’s the most active site of defense in the entire organism. It’s where threats are recognized, filtered, and responded to. The immune system doesn’t start at the nucleus. It starts at the boundary. The skin, the mucous membranes, the gut lining — these are where the environment meets the organism, and they are dense with defensive mechanisms precisely because that’s where exposure happens.

The frontend is the membrane. And membranes that don’t defend themselves rely on the organism’s deeper defenses to catch everything — which works until it doesn’t.


If I were interviewing the person who wrote that answer, I wouldn’t write them off immediately. What they said reveals junior-to-mid-level knowledge — they understand that frameworks provide default protections, which is real knowledge. But the framing tells me they haven’t been through a security incident, or if they have, they drew the wrong lessons from it. For a senior or staff-level role, where part of the job is shaping how a team thinks about risk, that posture would be a serious concern. At that level, I’d expect someone to be raising security culture on the team, not minimizing the attack surface in conversation.

The tell is really the word “usually.” Security is the exact domain where “usually fine” is where incidents live. Usually no one crafts a malicious URL. Usually no one compromises a popular npm package. Usually no one finds the XSS hole in your markdown renderer. Until someone does, and “usually” stops being a comfort and starts being the first line of the post-mortem.

I don’t know what the right level of paranoia is — I think that’s something you calibrate over a career, and I’m still calibrating. But I do know that the answer can’t be “it’s not my layer.” In a system, every layer is your layer. The boundaries most of all.


Headshot of Matthew Hippely

Hi, I’m Matthew. I live in Ventura County, and spend my time thinking about systems, software, and how things evolve over time.

You can find me on GitHub, LinkedIn, or read more about me here.