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

flask-security.jsonverifiers/

{
  "instruction": "Apply Flask security best practices for production deployment",
  "relevant_when": "Agent builds or reviews a Flask API for production",
  "context": "Flask needs ProxyFix behind reverse proxies, Flask-CORS with explicit origins, Flask-Talisman for headers, Flask-Limiter with persistent storage, secure session cookies, strong SECRET_KEY from env, input validation, and generic error handlers.",
  "sources": [
    {
      "type": "file",
      "filename": "skills/flask-security-basics/SKILL.md",
      "tile": "tessl-labs/flask-security-basics@0.2.0"
    }
  ],
  "checklist": [
    {
      "name": "proxy-fix-applied",
      "rule": "Agent applies werkzeug ProxyFix middleware when the app runs behind a reverse proxy (nginx, ALB, etc.), setting x_for=1 and x_proto=1",
      "relevant_when": "Agent deploys Flask behind a reverse proxy or load balancer"
    },
    {
      "name": "limiter-persistent-storage",
      "rule": "Agent configures Flask-Limiter with a persistent storage backend (Redis or memcached) via storage_uri, not the default in-memory storage",
      "relevant_when": "Agent configures Flask-Limiter for production"
    },
    {
      "name": "per-route-rate-limits",
      "rule": "Agent adds @limiter.limit() decorators on POST, PATCH, and DELETE endpoints with limits stricter than the global default",
      "relevant_when": "Agent configures rate limiting on Flask mutation endpoints"
    },
    {
      "name": "talisman-force-https-false-behind-proxy",
      "rule": "Agent sets force_https=False on Talisman when the app runs behind a TLS-terminating reverse proxy, to avoid redirect loops",
      "relevant_when": "Agent configures Flask-Talisman behind a reverse proxy"
    },
    {
      "name": "session-cookie-secure",
      "rule": "Agent sets SESSION_COOKIE_SECURE=True in production configuration",
      "relevant_when": "Agent configures Flask session cookies for production"
    },
    {
      "name": "session-cookie-httponly",
      "rule": "Agent sets SESSION_COOKIE_HTTPONLY=True (or leaves Flask default which is True)",
      "relevant_when": "Agent configures Flask session cookies"
    },
    {
      "name": "no-sensitive-session-data",
      "rule": "Agent does not store sensitive data (tokens, passwords, roles) in Flask's default session, understanding it is signed but not encrypted",
      "relevant_when": "Agent uses Flask session to store data"
    },
    {
      "name": "cors-explicit-origins",
      "rule": "Agent installs and configures Flask-CORS with explicit origins from an environment variable, not wildcard '*'",
      "relevant_when": "Agent configures Flask CORS"
    },
    {
      "name": "secret-key-from-env",
      "rule": "Agent loads SECRET_KEY from an environment variable with a startup guard that raises an error if missing (outside testing mode)",
      "relevant_when": "Agent configures Flask SECRET_KEY"
    },
    {
      "name": "secret-key-strong-generation",
      "rule": "Agent recommends or uses secrets.token_hex(32) or os.urandom(32) for SECRET_KEY generation, not a short human-readable string",
      "relevant_when": "Agent generates or documents how to create a Flask SECRET_KEY"
    },
    {
      "name": "input-validation-silent-json",
      "rule": "Agent uses request.get_json(silent=True) and checks for None before accessing fields, returning a JSON 400 error",
      "relevant_when": "Agent writes a Flask endpoint that accepts JSON input"
    },
    {
      "name": "generic-error-handlers",
      "rule": "Agent registers error handlers that return generic JSON error responses without leaking stack traces or exception details",
      "relevant_when": "Agent sets up Flask error handling"
    },
    {
      "name": "debug-mode-disabled",
      "rule": "Agent ensures debug=False in production (no app.debug=True, no debug=True in app.run())",
      "relevant_when": "Agent configures Flask for production"
    },
    {
      "name": "security-headers-configured",
      "rule": "Agent installs Flask-Talisman or manually adds security headers (X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security)",
      "relevant_when": "Agent configures Flask security headers"
    }
  ]
}

tile.json