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.
GET /v1/videos/:task_id/contentTokenOrUserAuth()controller.VideoProxyVideoProxy 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)
An authenticated attacker who knows another user's task_id can:
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.
curl -o stolen_video.mp4 \
"https://<instance>/v1/videos/<victim_task_id>/content" \
-H "Authorization: Bearer sk-<attacker_token>"
Expected result:
200 OKReplace the task lookup in VideoProxy with an ownership-checked query:
userId := c.GetInt("id")
task, exists, err := model.GetByTaskId(userId, taskID)
{
"cwe_ids": [
"CWE-639"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-23T20:30:57Z",
"nvd_published_at": "2026-03-23T20:16:25Z",
"severity": "MODERATE"
}