{"record":{"id":"d749362d95fa1324","repo":"Zie619/n8n-workflows","slug":"invalid-filename-format","errorCode":null,"errorMessage":"Invalid filename format","messagePattern":"Invalid filename format","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"api_server.py","lineNumber":315,"sourceCode":"                \"trigger\": trigger,\n                \"complexity\": complexity,\n                \"active_only\": active_only,\n            },\n        )\n    except Exception as e:\n        raise HTTPException(\n            status_code=500, detail=f\"Error searching workflows: {str(e)}\"\n        )\n\n\n@app.get(\"/api/workflows/{filename}\")\nasync def get_workflow_detail(filename: str, request: Request):\n    \"\"\"Get detailed workflow information including raw JSON.\"\"\"\n    try:\n        # Security: Validate filename to prevent path traversal\n        if not validate_filename(filename):\n            print(f\"Security: Blocked path traversal attempt for filename: {filename}\")\n            raise HTTPException(status_code=400, detail=\"Invalid filename format\")\n\n        # Security: Rate limiting\n        client_ip = request.client.host if request.client else \"unknown\"\n        if not check_rate_limit(client_ip):\n            raise HTTPException(\n                status_code=429, detail=\"Rate limit exceeded. Please try again later.\"\n            )\n\n        # Get workflow metadata from database\n        workflows, _ = db.search_workflows(f'filename:\"{filename}\"', limit=1)\n        if not workflows:\n            raise HTTPException(\n                status_code=404, detail=\"Workflow not found in database\"\n            )\n\n        workflow_meta = workflows[0]\n\n        # Load raw JSON from file with security checks","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/Zie619/n8n-workflows/blob/94007c1445d9258a7da116646b79473e7c7c3282/api_server.py#L297-L333","documentation":"A 400 from GET /api/workflows/{filename} raised when validate_filename(filename) rejects the value. This is a deliberate security guard: filenames containing path segments, traversal sequences (../), or characters outside the allowed pattern are refused before any filesystem access. The same check is logged server-side as 'Security: Blocked path traversal attempt'.","triggerScenarios":"Requesting /api/workflows/../../etc/passwd, a filename with a slash ('subdir/file.json'), a leading dot, an empty or URL-encoded traversal payload (%2e%2e%2f), or any extension/pattern the validate_filename allowlist does not accept.","commonSituations":"Passing a full relative path from the UI instead of the bare filename; copy-pasting a URL-encoded filename whose decoded form contains forbidden characters; automated scanners probing the endpoint.","solutions":["Send only the bare filename (e.g. 'my-workflow.json') exactly as returned by the /api/workflows listing's filename field.","Strip any directory component and URL-decode before issuing the request.","If a legitimately named file is rejected, inspect validate_filename() in api_server.py and either rename the file to match the allowed pattern or extend the regex deliberately.","Do not attempt to bypass the check; it exists to prevent path traversal."],"exampleFix":"// before\nconst res = await fetch(`/api/workflows/${encodeURIComponent(fullPath)}`);\n\n// after (bare filename only)\nconst res = await fetch(`/api/workflows/${encodeURIComponent(fileName)}`); // fileName = 'my-workflow.json'","handlingStrategy":"validation","validationCode":"const SAFE_FILENAME = /^[A-Za-z0-9][A-Za-z0-9._ -]*\\.json$/;\nfunction isValidFilename(name) {\n  return typeof name === 'string' && SAFE_FILENAME.test(name) && !name.includes('..');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always take filenames from the API's own listing response.","Never send directory components or URL-encoded traversal sequences.","Mirror the server's validate_filename() pattern client-side for fast feedback."],"tags":["fastapi","security","path-traversal","validation","http-400"],"backgroundTag":null,"analyzedSha":"94007c1445d9258a7da116646b79473e7c7c3282","analyzedAt":"2026-08-15T04:10:37.591Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}