Fix Insecure API Management in Bottle
Bottle's minimalism is a double-edged sword. Out of the box, it provides zero protection against API abuse. Insecure API management in Bottle usually manifests as missing authentication, lack of rate limiting (DoS/Brute-force), and permissive CORS policies. If you're running production APIs on default routes, you're leaking data and inviting resource exhaustion.
The Vulnerable Pattern
from bottle import route, run, request@route(‘/api/user/info’) def user_info(): # VULNERABILITY: No authentication check # VULNERABILITY: No rate limiting # VULNERABILITY: Default headers (CORS *) user_id = request.query.get(‘id’) return {‘user_id’: user_id, ‘email’: ‘[email protected]’, ‘balance’: 9000}
run(host=‘0.0.0.0’, port=8080)
The Secure Implementation
The hardened implementation addresses three critical vectors. First, it implements a mandatory 'X-API-KEY' header check to prevent unauthorized access. Second, it adds a primitive but effective rate-limiting check based on the source IP to mitigate automated scraping and DoS. Third, it replaces Bottle's default permissive behavior with explicit CORS headers and security headers (nosniff) to prevent cross-origin attacks and MIME-sniffing. Finally, the server binds to 127.0.0.1 instead of 0.0.0.0 to ensure the API isn't exposed to the public internet by default without a reverse proxy like Nginx.
from bottle import route, run, request, response, HTTPError import timeMock store for rate limiting
REQUEST_LOG = {}
def check_auth(): api_key = request.headers.get(‘X-API-KEY’) if api_key != ‘EXPECTED_SECURE_TOKEN’: raise HTTPError(401, ‘Unauthorized’)
def apply_rate_limit(): client_ip = request.remote_addr now = time.time() if client_ip in REQUEST_LOG and now - REQUEST_LOG[client_ip] < 1: # 1 req/sec limit raise HTTPError(429, ‘Too Many Requests’) REQUEST_LOG[client_ip] = now
@route(‘/api/user/info’, method=[‘GET’, ‘OPTIONS’]) def secure_user_info(): # 1. CORS Hardening response.set_header(‘Access-Control-Allow-Origin’, ‘https://trusted-app.com’) response.set_header(‘X-Content-Type-Options’, ‘nosniff’) if request.method == ‘OPTIONS’: return {}
# 2. Rate Limiting apply_rate_limit() # 3. Authentication check_auth() user_id = request.query.get('id') return {'user_id': user_id, 'status': 'authorized'}
run(host=‘127.0.0.1’, port=8080)
Your Bottle API
might be exposed to Insecure API Management
74% of Bottle apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.
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.