CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/input-sanitization

Sanitize and validate user input at system boundaries — prevent XSS, SQL

94

1.20x
Quality

89%

Does it follow best practices?

Impact

100%

1.20x

Average score across 6 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

criteria.jsonevals/scenario-4/

{
  "context": "Tests whether the agent correctly prevents SSRF by validating outbound URLs against an allowlist, and prevents mass assignment by explicitly destructuring only expected fields instead of passing req.body directly to the database.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "URL parsed before use",
      "description": "The user-supplied URL is parsed with new URL() (or urllib.parse / url.parse) in a try/catch before making any outbound request",
      "max_score": 10
    },
    {
      "name": "HTTPS-only enforced",
      "description": "The URL protocol/scheme is checked and only 'https:' is accepted; http:, ftp:, file:, etc. are rejected",
      "max_score": 10
    },
    {
      "name": "Hostname allowlist checked",
      "description": "The parsed hostname is checked against an explicit array or set of permitted hostnames, and requests to unlisted hosts are rejected with 400",
      "max_score": 15
    },
    {
      "name": "Invalid URL returns 400",
      "description": "If URL parsing throws (malformed URL) the endpoint returns HTTP 400, not 500",
      "max_score": 8
    },
    {
      "name": "Disallowed host returns 400",
      "description": "If the hostname is not in the allowlist the endpoint returns HTTP 400 or 403 with an error message",
      "max_score": 8
    },
    {
      "name": "No req.body spread to DB",
      "description": "The entire req.body object is NOT passed/spread into a database create or update call (no patterns like prisma.user.create({ data: req.body }) or User(**request.json))",
      "max_score": 15
    },
    {
      "name": "Explicit field destructuring",
      "description": "Only explicitly named fields are destructured from req.body (e.g. const { name, email } = req.body) and those named fields are used in the database operation",
      "max_score": 12
    },
    {
      "name": "Content-Type checked",
      "description": "POST/PUT/PATCH endpoints check Content-Type is application/json and return 415 for other types",
      "max_score": 10
    },
    {
      "name": "String fields trimmed",
      "description": "User-supplied string fields are trimmed before storage",
      "max_score": 6
    },
    {
      "name": "Required fields validated",
      "description": "Missing or empty required fields return 400 before any database or outbound operation is attempted",
      "max_score": 6
    }
  ]
}

evals

tile.json