CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/flask-security-basics

Security essentials for Flask APIs — CORS, Talisman security headers, rate

99

1.17x
Quality

94%

Does it follow best practices?

Impact

100%

1.17x

Average score across 10 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

task.mdevals/scenario-6/

Refactoring Flask Extensions for an Application Factory

Problem Description

A developer at a logistics company wrote a Flask API as a simple script during a hackathon. The code works for local testing, but the team now needs to:

  • Run it with Gunicorn
  • Write integration tests that create the app in TESTING mode without starting a real server
  • Eventually split routes across multiple blueprints

The app currently initialises all security extensions at module level (directly in the global scope), which prevents multiple app instances from being created and makes testing impossible.

Your task is to refactor delivery_api.py to use the application factory pattern (create_app() function) and initialise all extensions correctly so they work with the factory. The routes, security configuration values, and behaviour should remain the same — only the structure changes.

Output Specification

Produce a single refactored file:

  • delivery_api.py — the Flask application using the application factory pattern

Input Files

The following file is provided as input. Extract it before beginning.

=============== FILE: delivery_api.py =============== import os from flask import Flask, jsonify, request from flask_cors import CORS from flask_talisman import Talisman from flask_limiter import Limiter from flask_limiter.util import get_remote_address

app = Flask(name) app.config['SECRET_KEY'] = os.getenv('SECRET_KEY') if not app.config['SECRET_KEY']: raise RuntimeError('SECRET_KEY environment variable is required')

Extensions initialised at module level — breaks multiple app instances

CORS(app, origins=os.getenv('ALLOWED_ORIGINS', 'http://localhost:5173').split(','))

talisman = Talisman(app, content_security_policy=None, force_https=False, session_cookie_secure=True, session_cookie_http_only=True, )

limiter = Limiter( key_func=get_remote_address, app=app, default_limits=["200 per hour"], storage_uri=os.getenv('REDIS_URL', 'redis://localhost:6379/0'), )

@app.route('/deliveries', methods=['GET']) def list_deliveries(): return jsonify({'deliveries': []})

@app.route('/deliveries', methods=['POST']) @limiter.limit("20 per minute") def create_delivery(): data = request.get_json(silent=True) if data is None: return jsonify({'error': 'Request body must be JSON'}), 400 destination = data.get('destination', '').strip() if not destination: return jsonify({'error': 'destination is required'}), 400 return jsonify({'id': 1, 'destination': destination}), 201

@app.route('/deliveries/int:delivery_id', methods=['DELETE']) @limiter.limit("10 per minute") def cancel_delivery(delivery_id): return jsonify({'cancelled': delivery_id})

if name == 'main': app.run()

evals

tile.json