src/visionset/server/models.py bounds none of the strings a video import declares:
display_name (line 885) - becomes the source's name
batch_name (line 891) - becomes the committed batch's name
materializer (line 895) - stored inside the source's video JSON blob
codec (line 859) - min_length=1 only
normalize_name rejects blank and nothing else, so a multi-megabyte display_name is accepted and stored. No path traversal or filename injection is reachable - the locator is video-import:<uuid4>, Asset.uri derives from it, and nothing on this path builds a filesystem path from a client string - so this is size only.
It matches what register_image_source already does with its name, so the fix is probably one length bound applied consistently at the boundary rather than something specific to video.
Related, same boundary: the 32-part cap on POST /video-imports/{id}/frames is enforced in the handler, after the multipart parser has accepted and spooled the parts. The parser's own default allows far more, so an oversized request is written to temp files before it earns its 422. The files are cleaned up, so this is transient disk rather than a leak.
src/visionset/server/models.pybounds none of the strings a video import declares:display_name(line 885) - becomes the source's namebatch_name(line 891) - becomes the committed batch's namematerializer(line 895) - stored inside the source'svideoJSON blobcodec(line 859) -min_length=1onlynormalize_namerejects blank and nothing else, so a multi-megabytedisplay_nameis accepted and stored. No path traversal or filename injection is reachable - the locator isvideo-import:<uuid4>,Asset.uriderives from it, and nothing on this path builds a filesystem path from a client string - so this is size only.It matches what
register_image_sourcealready does with itsname, so the fix is probably one length bound applied consistently at the boundary rather than something specific to video.Related, same boundary: the 32-part cap on
POST /video-imports/{id}/framesis enforced in the handler, after the multipart parser has accepted and spooled the parts. The parser's own default allows far more, so an oversized request is written to temp files before it earns its 422. The files are cleaned up, so this is transient disk rather than a leak.