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-5/

Fixing Information Leakage in Error Responses

Problem Description

A fintech startup's Flask API has been reported by a penetration tester: when the application encounters unhandled exceptions, the full Python exception message and sometimes a stack trace appear in the HTTP response body. During the pentest, the tester was able to retrieve database connection strings and internal file paths by deliberately triggering errors.

The current app has no custom error handlers — it relies on Flask's defaults. Additionally, there is no custom 404 handler, so missing routes return an HTML page that reveals the Flask version.

Your task is to add proper error handlers to api.py so that:

  • All unhandled server errors return a generic JSON response that reveals nothing about the internals
  • The exception is still recorded somewhere useful for the operations team (without sending it to the client)
  • Missing routes return a JSON response consistent with the rest of the API

Output Specification

Produce a single updated file:

  • api.py — the Flask application with secure error handlers added

Input Files

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

=============== FILE: api.py =============== import os from flask import Flask, jsonify, request

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

# Simulated external service that can fail
def fetch_account(account_id):
    if account_id == 0:
        raise ConnectionError(
            "Cannot connect to database: host=db.internal port=5432 user=api_user"
        )
    return {'id': account_id, 'balance': 1000.00}

@app.route('/accounts/<int:account_id>', methods=['GET'])
def get_account(account_id):
    account = fetch_account(account_id)
    return jsonify(account)

@app.route('/accounts', methods=['POST'])
def create_account():
    data = request.get_json(silent=True)
    if data is None:
        return jsonify({'error': 'Request body must be JSON'}), 400
    name = data.get('name', '').strip()
    if not name:
        return jsonify({'error': 'name is required'}), 400
    return jsonify({'id': 999, 'name': name}), 201

# TODO: add error handlers here

return app

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

evals

tile.json