Security essentials for Flask APIs — CORS, Talisman security headers, rate
99
94%
Does it follow best practices?
Impact
100%
1.17xAverage score across 10 eval scenarios
Passed
No known issues
{
"context": "The agent was asked to add input validation to a Flask POST endpoint that creates book records. The scorer checks bookstore.py to verify correct use of get_json(silent=True), presence/type checks for all four fields, length constraints, and proper 400 error responses.",
"type": "weighted_checklist",
"checklist": [
{
"name": "get_json(silent=True) used",
"description": "The handler calls request.get_json(silent=True) (not request.get_json() without silent=True) to safely parse the body.",
"max_score": 10
},
{
"name": "None body returns 400",
"description": "If get_json returns None (missing or non-JSON body), the handler returns a 400 response with a JSON error message before attempting to access any fields.",
"max_score": 10
},
{
"name": "title presence check",
"description": "title is validated to be a non-empty string after stripping whitespace. Missing or empty title returns 400.",
"max_score": 8
},
{
"name": "title max length check",
"description": "title longer than 200 characters is rejected with a 400 error.",
"max_score": 6
},
{
"name": "title stripped",
"description": "title is stripped of leading/trailing whitespace before the non-empty check (e.g., using .strip()).",
"max_score": 6
},
{
"name": "author presence check",
"description": "author is validated to be a non-empty string after stripping whitespace. Missing or empty author returns 400.",
"max_score": 8
},
{
"name": "author max length check",
"description": "author longer than 100 characters is rejected with a 400 error.",
"max_score": 6
},
{
"name": "year type and range check",
"description": "year is validated to be an integer (not a string or float) and within the range 1000–2100 inclusive. Invalid values return 400.",
"max_score": 10
},
{
"name": "tags list type check",
"description": "tags is validated to be a list. Non-list values return 400.",
"max_score": 8
},
{
"name": "tags element check",
"description": "Each element in tags is validated to be a non-empty string. Invalid elements cause a 400 error.",
"max_score": 8
},
{
"name": "400 JSON error response",
"description": "All validation errors return HTTP 400 with a JSON body containing at least an 'error' key and a descriptive message.",
"max_score": 10
},
{
"name": "Valid request succeeds",
"description": "A request with all valid fields returns HTTP 201 with the book data (the happy path is preserved).",
"max_score": 10
}
]
}evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
skills
flask-security-basics
verifiers