GuardAPI Logo
GuardAPI

Fix Shadow API Exposure in Nitro

Nitro's file-system routing is a double-edged sword: ease of development often leads to 'Shadow APIs'—undocumented, unauthenticated endpoints lurking in the `server/api` directory. In a Nitro environment, if a file exists in the api path, it is public. Attackers crawl these for 'debug', 'test', or 'internal' scripts left behind by developers. To secure Nitro, you must enforce strict routing patterns, move internal logic to non-routed directories, and implement global middleware guards.

The Vulnerable Pattern

// server/api/internal/test-db-connection.ts
// VULNERABILITY: This file is automatically exposed as /api/internal/test-db-connection
// No authentication, no method restriction, leaks system config.
export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig();
  const data = await someInternalDbLogic();
  return {
    status: 'connected',
    config: config.private, // Sensitive leak
    preview: data
  };
});

The Secure Implementation

To kill Shadow APIs in Nitro: First, audit the `server/api` directory and move any non-endpoint logic into `server/utils` or `server/lib`, which Nitro's router ignores. Second, adopt 'Method-Specific Routing' by naming files with suffixes like `.get.ts` or `.post.ts` to prevent unintended verb execution. Finally, implement a global middleware in `server/middleware/` that acts as a default-deny gatekeeper, requiring valid credentials for any path under `/api/` unless explicitly whitelisted. This ensures that even if a developer accidentally drops a 'test.ts' file into the API folder, it remains inaccessible to unauthorized scanners.

// 1. Move internal logic to server/utils/db.ts (Nitro does not route server/utils)
// 2. Use explicit method suffixes (.get.ts) and authentication

// server/api/admin/system-check.get.ts export default defineEventHandler(async (event) => { // Ensure user is authenticated via middleware-injected context if (!event.context.user?.isAdmin) { throw createError({ statusCode: 403, statusMessage: ‘Forbidden’ }); }

const data = await someInternalDbLogic(); return { status: ‘healthy’ }; // Return minimal necessary data });

// 3. server/middleware/auth.ts - Global Guard export default defineEventHandler((event) => { const isPublicRoute = [‘/api/login’, ‘/api/health’].includes(event.path); if (event.path.startsWith(‘/api/’) && !isPublicRoute) { const token = getHeader(event, ‘Authorization’); if (!isValid(token)) { throw createError({ statusCode: 401, message: ‘Shadow API Access Blocked’ }); } } });

System Alert • ID: 9807
Target: Nitro API
Potential Vulnerability

Your Nitro API might be exposed to Shadow API Exposure

74% of Nitro apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.