{"record":{"id":"883a41e51fad9845","repo":"harry0703/MoneyPrinterTurbo","slug":"file-does-not-exist","errorCode":null,"errorMessage":"file does not exist","messagePattern":"file does not exist","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"app/utils/file_security.py","lineNumber":33,"sourceCode":"        raise ValueError(\"empty path is not allowed\")\n\n    base_dir_real = os.path.realpath(base_dir)\n    candidate_path = unsafe_path\n    if not os.path.isabs(candidate_path):\n        candidate_path = os.path.join(base_dir_real, candidate_path)\n\n    resolved_path = os.path.realpath(candidate_path)\n    try:\n        common_path = os.path.commonpath([base_dir_real, resolved_path])\n    except ValueError as exc:\n        # Windows 下不同盘符会触发 ValueError，这类路径一定不属于允许目录。\n        raise ValueError(\"path is outside the allowed directory\") from exc\n\n    if common_path != base_dir_real:\n        raise ValueError(\"path is outside the allowed directory\")\n\n    if require_file and not os.path.isfile(resolved_path):\n        raise ValueError(\"file does not exist\")\n\n    return resolved_path\n","sourceCodeStart":15,"sourceCodeEnd":36,"githubUrl":"https://github.com/harry0703/MoneyPrinterTurbo/blob/1f9f19c2021a68d04df228f33e9099a0c947f6f8/app/utils/file_security.py#L15-L36","documentation":"Final check of resolve_path_within_directory: the path is inside the allowed directory and require_file is True (the default), but os.path.isfile reports the resolved path is not an existing regular file — it may be missing, a directory, or a special file.","triggerScenarios":"Requesting a task artifact that has not been generated yet or was deleted; passing a directory path; referencing a file whose generation step failed earlier; typo in the filename portion.","commonSituations":"Client polls for a video/audio file before the task finished generating it; task artifacts cleaned up by retention jobs; downloading a still-running task's output.","solutions":["Confirm the task reached the stage that produces this file before requesting it (check task status first).","Verify the filename against the task record — copy the exact name the server returned, don't construct it.","If files were pruned, re-run the task or restore the artifacts.","Pass require_file=False only when you intentionally resolve a not-yet-created output path."],"exampleFix":"# before\nresolve_path_within_directory(task_dir, \"final_video.mp4\")  # not generated yet\n\n# after\n# resolve an output path that will be created later\nresolve_path_within_directory(task_dir, \"final_video.mp4\", require_file=False)","handlingStrategy":"validation","validationCode":"import os\nexpected = os.path.join(base_dir, unsafe_path)\nif require_file and not os.path.isfile(expected):\n    # file not generated yet — wait or check task status first\n    poll_task_status_before_download()","typeGuard":null,"tryCatchPattern":"try:\n    resolved = resolve_path_within_directory(task_dir, filename)\nexcept ValueError as exc:\n    if \"file does not exist\" in str(exc):\n        return HTTP 404 with a retry-after hint\n    if \"outside the allowed directory\" in str(exc):\n        return HTTP 403 and log\n    raise","preventionTips":["Gate downloads on task completion status.","Use require_file=False deliberately for output paths that are written later."],"tags":["path-traversal","security","file-existence"],"backgroundTag":null,"analyzedSha":"1f9f19c2021a68d04df228f33e9099a0c947f6f8","analyzedAt":"2026-08-14T19:41:05.568Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}