Summary
The video proxy endpoint GET /v1/videos/:task_id/content is vulnerable to an Insecure Direct Object Reference (IDOR). Any authenticated user who knows another user's task_id can retrieve that user's generated video content because the handler queries tasks by task_id alone and does not verify ownership.
Affected Component
- Endpoint:
GET /v1/videos/:task_id/content
- Route middleware:
TokenOrUserAuth()
- Vulnerable handler:
controller.VideoProxy
Details
VideoProxy fetches the task with:
task, exists, err := model.GetByOnlyTaskId(taskID)
GetByOnlyTaskId performs a database lookup using only task_id:
err = DB.Where("task_id = ?", taskId).First(&task).Error
The authenticated user's ID is available in request context, but VideoProxy does not use it. This allows any authenticated user to request /v1/videos/<foreign_task_id>/content and access another user's video if they know a valid task ID.
Other task-fetch paths already enforce ownership correctly via:
model.GetByTaskId(userId, taskId)
Impact
An authenticated attacker who knows another user's task_id can:
- Download video content belonging to another user
- Bypass tenant isolation for generated media assets
- Cause the server to fetch upstream video content for a task the attacker does not own
For Gemini tasks, the proxy also uses task.PrivateData.Key when contacting the upstream provider. In addition, full upstream response headers are forwarded back to the requester.
Proof of Concept
curl -o stolen_video.mp4 \
"https://<instance>/v1/videos/<victim_task_id>/content" \
-H "Authorization: Bearer sk-<attacker_token>"
Expected result:
- Response returns
200 OK
- Response body contains the victim's video content
Recommended Fix
Replace the task lookup in VideoProxy with an ownership-checked query:
userId := c.GetInt("id")
task, exists, err := model.GetByTaskId(userId, taskID)
References
Summary
The video proxy endpoint
GET /v1/videos/:task_id/contentis vulnerable to an Insecure Direct Object Reference (IDOR). Any authenticated user who knows another user'stask_idcan retrieve that user's generated video content because the handler queries tasks bytask_idalone and does not verify ownership.Affected Component
GET /v1/videos/:task_id/contentTokenOrUserAuth()controller.VideoProxyDetails
VideoProxyfetches the task with:GetByOnlyTaskIdperforms a database lookup using onlytask_id:The authenticated user's ID is available in request context, but
VideoProxydoes not use it. This allows any authenticated user to request/v1/videos/<foreign_task_id>/contentand access another user's video if they know a valid task ID.Other task-fetch paths already enforce ownership correctly via:
Impact
An authenticated attacker who knows another user's
task_idcan:For Gemini tasks, the proxy also uses
task.PrivateData.Keywhen contacting the upstream provider. In addition, full upstream response headers are forwarded back to the requester.Proof of Concept
Expected result:
200 OKRecommended Fix
Replace the task lookup in
VideoProxywith an ownership-checked query:References