GuardAPI Logo
GuardAPI

Fix Lack of Resources & Rate Limiting in Tornado

Tornado's non-blocking nature is a double-edged sword. While it handles concurrency well, a lack of explicit resource limits allows an attacker to saturate the I/O loop or exhaust memory through 'slowloris' style attacks or massive payload injections. If you aren't enforcing rate limits and body size constraints, your service is a sitting duck for DoS.

The Vulnerable Pattern

import tornado.ioloop
import tornado.web

class VulnerableHandler(tornado.web.RequestHandler): async def post(self): # VULNERABILITY: No limit on request body size and no rate limiting. # An attacker can send gigabytes of data or spam this endpoint to exhaust RAM. data = self.request.body self.write({‘status’: ‘received’, ‘size’: len(data)})

def make_app(): return tornado.web.Application([ (r’/upload’, VulnerableHandler), ]) # No global resource limits configured

The Secure Implementation

The secure implementation mitigates resource exhaustion via two primary vectors. First, 'max_body_size' is explicitly set in the Application settings to prevent memory-based DoS from oversized payloads. Second, a custom 'limit_requests' decorator implements a sliding-window rate limiter on sensitive endpoints, ensuring that a single IP cannot monopolize the event loop. For production-grade security, always offload rate-limiting state to a fast K/V store like Redis and use a reverse proxy like Nginx for initial connection throttling.

import time
from functools import wraps
from tornado.web import HTTPError, RequestHandler, Application

Simple in-memory bucket (Use Redis for production/distributed environments)

ratelimit_store = {}

def limit_requests(max_reqs, window): def decorator(method): @wraps(method) async def wrapper(self, *args, **kwargs): ip = self.request.remote_ip now = time.time() calls = [t for t in ratelimit_store.get(ip, []) if t > now - window] if len(calls) >= max_reqs: raise HTTPError(429, ‘Rate limit exceeded’) ratelimit_store[ip] = calls + [now] return await method(self, *args, **kwargs) return wrapper return decorator

class SecureHandler(RequestHandler): @limit_requests(max_reqs=5, window=60) async def post(self): self.write({‘status’: ‘secure’})

def make_app(): return Application([ (r’/upload’, SecureHandler), ], max_body_size=1024 * 1024 * 2, # SECURE: Limit body size to 2MB max_buffer_size=1024 * 1024 * 4 # SECURE: Limit internal buffer size )

System Alert • ID: 4617
Target: Tornado API
Potential Vulnerability

Your Tornado API might be exposed to Lack of Resources & Rate Limiting

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.