GuardAPI Logo
GuardAPI

Fix Shadow API Exposure in Tornado

Shadow APIs are the undocumented, 'dark' endpoints lurking in your Tornado Application manifest. They often stem from legacy debug handlers, forgotten internal tools, or dynamic routing patterns that lack visibility. In production, these are blind spots that bypass WAF rules and monitoring. If it's not in your OpenAPI spec, it's a liability. To fix shadow exposure, you must enforce explicit routing, environment-aware registration, and centralized authentication.

The Vulnerable Pattern

import tornado.web

class DebugConfigHandler(tornado.web.RequestHandler): def get(self): # Shadow API: Left active in production, leaks internal config self.write({“db_conn”: “secret_string”, “debug_mode”: True})

class UserHandler(tornado.web.RequestHandler): def get(self): self.write(“User Data”)

def make_app(): return tornado.web.Application([ (r”/api/v1/user”, UserHandler), (r”/internal/debug/config”, DebugConfigHandler), # Shadow endpoint ])

The Secure Implementation

The fix involves three layers of defense. First, 'Environment-Aware Routing' ensures that sensitive debug handlers are never even registered in the Tornado routing table when running in production. Second, the use of a 'BaseHandler' with a mandatory 'prepare()' method enforces a 'Secure by Default' posture, ensuring even undocumented routes require authentication. Finally, the application manifest should be used to programmatically generate an OpenAPI/Swagger schema, forcing developers to synchronize the code with the security inventory—if it's not in the schema, it shouldn't be in the code.

import tornado.web
import os

class BaseHandler(tornado.web.RequestHandler): def prepare(self): # Centralized Auth: Ensure no endpoint is ‘shadowed’ from security logic if not self.request.headers.get(“Authorization”): raise tornado.web.HTTPError(401)

class UserHandler(BaseHandler): def get(self): self.write(“User Data”)

def make_app(): # 1. Explicit Route Inventory routes = [ (r”/api/v1/user”, UserHandler), ]

# 2. Environment-aware registration
if os.environ.get("APP_ENV") == "development":
    from handlers.debug import DebugConfigHandler
    routes.append((r"/local/debug", DebugConfigHandler))
    
return tornado.web.Application(routes, autoreload=False, compiled_template_cache=True)</code></pre>
System Alert • ID: 2256
Target: Tornado API
Potential Vulnerability

Your Tornado API might be exposed to Shadow API Exposure

74% of Tornado 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.