Description
Buffered and streamed uploads currently normalize uploaded filenames differently.
The streamed upload parser sanitizes the multipart filename to a basename:
filename = Path(filename.lstrip("/")).name
But the buffered upload path keeps the original path segments:
path=Path(file.filename.lstrip("/")) if file.filename else None
This means a filename such as ../secret.txt becomes:
- streamed upload: secret.txt
- buffered upload: ../secret.txt in UploadFile.path
UploadFile.name still returns the basename, but UploadFile.path is exposed to user handlers, so app code can observe
inconsistent behavior depending on whether the handler uses rx.upload_files or rx.upload_files_chunk.
### Reproduction
import io
from pathlib import Path
from starlette.datastructures import UploadFile as StarletteUploadFile
from reflex_components_core.core._upload import UploadFile
file = StarletteUploadFile(file=io.BytesIO(b"x"), filename="../secret.txt")
upload = UploadFile(
file=file.file,
path=Path(file.filename.lstrip("/")),
size=file.size,
headers=file.headers,
)
print(upload.path)
print(upload.name)
On Windows this prints:
..\secret.txt
secret.txt
The streamed parser path for the same filename emits:
secret.txt
### Expected behavior
Buffered uploads should apply the same filename normalization as streamed uploads, so UploadFile.path does not
preserve directory or traversal segments from the client-provided multipart filename.
### Suggested fix
Use the same basename normalization in the buffered upload path:
path=Path(Path(file.filename.lstrip("/")).name) if file.filename else None
or factor this into a shared helper so both upload modes always normalize filenames identically.
### Why this matters
This avoids inconsistent behavior between rx.upload_files and rx.upload_files_chunk, and prevents user handlers from
accidentally trusting path segments supplied by the client.
I searched existing issues with upload/path/filename traversal terms and did not find an existing report for this
specific buffered-vs-streamed inconsistency.
Description
Buffered and streamed uploads currently normalize uploaded filenames differently.
The streamed upload parser sanitizes the multipart filename to a basename: