Framework-Level Security: What Next.js, Nuxt, and Astro Developers Miss

General application security advice has never been more available. OWASP Top 10 lists, security scanning tools, and audit checklists abound. What they tend not to cover is the specific failure modes introduced by modern metaframeworks — the places where Next.js, Nuxt, SvelteKit, and Astro create new trust boundaries, new data exposure paths, and new misconfiguration classes that do not map cleanly onto traditional web security thinking.

This is the problem space we focus on at Turma Software, and it underpins both mit10s and our work on a proposed OWASP project: a Top 10 list specifically for metaframework application security risks. Below are the categories of mistakes we see most consistently.

Next.js: the server component boundary

React Server Components (RSCs) in the Next.js App Router run exclusively on the server and never ship their code to the client. This is the correct model for data fetching and server-side logic. The problem arises when developers misunderstand what “never ships to the client” means in practice.

A server component can import and use any module — including one that also gets imported by a client component. If that shared module contains sensitive logic or credentials, a misconfigured import path can cause a client bundle to include code that was only intended to run on the server. Next.js introduced the server-only package to guard against this: importing it at the top of a module throws an error at build time if that module is ever included in a client bundle. It is not used by default and must be added deliberately.

Server Actions — the mechanism for handling form submissions and mutations in the App Router — are another common source of exposure. Server Actions are automatically exposed as HTTP endpoints. Any function marked with 'use server' can be called from the browser. Teams frequently add authorization checks inside the action body, but then forget to apply the same check when the same data operation is called from other server-side contexts. The authorization check should live as close to the data layer as possible, not only at the entry point.

Next.js: route misconfiguration

Next.js middleware allows request-level logic — authentication checks, redirects, header manipulation — to run at the edge before a route renders. A common mistake is using middleware for authorization and assuming that is sufficient. Middleware runs at the edge and does not have access to the same runtime as the application server, which means secrets, database clients, and session stores behave differently there.

A subtler issue is next.config.js rewrites. It is possible to configure rewrites that expose internal API routes or bypass authentication middleware by routing directly to a page that is assumed to be unreachable. Rewrites are checked before middleware in some configurations, creating a gap.

Nuxt: public vs. private runtime config

Nuxt’s runtimeConfig has an explicit two-level structure: keys at the top level are server-only, keys under public are available to both server and client. This is a clean, well-documented model. The failure mode is that teams routinely place secrets under runtimeConfig.public — either because they want to access the value in a component, or because they misread the documentation, or because they are copying a pattern from a colleague who got it wrong.

Nuxt does not warn at build time when a value under public looks like a secret. There is no heuristic check for API keys or connection strings. The value is silently included in the client bundle and exposed in the page source.

Nuxt server routes (server/api/*.ts, server/routes/*.ts) are also public by default. There is no authentication layer applied automatically. Any route defined under server/api/ is accessible to any request unless the handler explicitly checks authentication. In a growing codebase with multiple contributors, this is easy to miss on new routes.

Astro: server endpoints and trust boundaries

Astro’s design is primarily static — most pages have no server-side code. When you add SSR and API endpoints (src/pages/api/*.ts), you are adding a server boundary that Astro does not protect for you. Server endpoints are public by default. Authentication must be applied explicitly in each handler.

Astro’s import.meta.env system also distinguishes between public variables (prefixed with PUBLIC_) and private ones. Variables without the prefix are only available in server-side code. The failure mode is developers using PUBLIC_ on variables that should be private, because they want to access the value in a component — the same structural mistake as the Nuxt runtimeConfig.public problem.

Environment variable leakage across all frameworks

Every major metaframework has a mechanism for distinguishing public from private environment variables:

  • Next.js: NEXT_PUBLIC_ prefix exposes a variable to the client
  • Nuxt: runtimeConfig.public vs. runtimeConfig
  • SvelteKit: $env/static/public vs. $env/static/private
  • Astro: PUBLIC_ prefix exposes a variable to the client

The consistent failure pattern is the same across all of them: a developer needs a value in a client-side context, sees that prefixing works, and applies it to a value that should remain private. Database URLs, internal API keys, and service credentials end up in client bundles and are visible in page source.

This class of mistake is automatable to detect. Scanning for environment variable naming patterns and matching them against how they are used in the codebase — client component imports vs. server-only files — is one of the core static analysis capabilities in mit10s.

Toward a framework-specific security standard

The OWASP Top 10 is a valuable general reference, but it was designed for a world of traditional server-rendered applications. The 2025 update moved software supply chain failures to third position, and security misconfiguration to second — both highly relevant to metaframework deployments — but the specific vulnerability classes described at the framework level are not there.

Our work on the Top 10 Metaframework Security Risks is an attempt to fill that gap: a community-developed reference that names and describes the most critical security risks specific to Next.js, Nuxt, SvelteKit, Astro, and similar frameworks. The goal is to give developers a concrete checklist, and to give tools like mit10s a shared vocabulary for what to look for.

Regulatory context for MENA

For applications deployed in the UAE or Saudi Arabia, these technical failure modes have regulatory implications. The UAE Personal Data Protection Law (Federal Decree-Law No. 45 of 2021) and Saudi Arabia’s Personal Data Protection Law impose obligations on how personal data is collected, processed, and protected. An environment variable leak that exposes a database connection string containing personal data, or a missing authorization check on an API route that returns user records, are not just security incidents — they are potential regulatory violations with associated liability.

Framework-level security is not abstract. It is the layer where data protection obligations either get enforced or get broken.