Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/kernelbot/api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -835,3 +835,35 @@ async def delete_user_submission(
raise
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error deleting submission: {e}") from e


@app.delete("/admin/submissions/{submission_id}")
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ADMIN_API_SECRET should be accessed through the env module following the codebase convention, not directly via os.environ.get(). Add env.ADMIN_API_SECRET = os.getenv("ADMIN_API_SECRET", "") to src/kernelbot/env.py (similar to line 19 for ADMIN_TOKEN), then use env.ADMIN_API_SECRET here instead of ADMIN_API_SECRET. This maintains consistency with how other environment variables like ADMIN_TOKEN are handled throughout the codebase.

Copilot uses AI. Check for mistakes.
async def admin_delete_submission(
submission_id: int,
x_admin_secret: Optional[str] = Header(None, alias="X-Admin-Secret"),
db_context=Depends(get_db),
) -> dict:
"""Admin-only: delete any submission by ID, regardless of ownership.

Protected by a shared secret between kernelboard and kernelbot.
Comment on lines +843 to +848
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This endpoint duplicates the existing DELETE /admin/submissions/{submission_id} endpoint defined at line 578. FastAPI will use the first registered route, making this new endpoint unreachable. The existing endpoint uses the standard require_admin dependency (with Authorization Bearer token), while this one uses a different authentication method (X-Admin-Secret header). Either the existing endpoint should be removed/replaced, or this new endpoint should use a different path (e.g., /admin/submissions/{submission_id}/delete-alt or /kernelboard/admin/submissions/{submission_id}).

Copilot uses AI. Check for mistakes.
Kernelboard verifies admin identity (whitelist) before calling this.
"""
await simple_rate_limit()

if not env.ADMIN_API_SECRET or x_admin_secret != env.ADMIN_API_SECRET:
raise HTTPException(status_code=403, detail="Admin access required")

try:
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The secret comparison on line 856 is vulnerable to timing attacks. An attacker could use timing measurements to determine the correct secret character by character. Use secrets.compare_digest() for constant-time comparison of secrets to prevent timing attacks. This should be: if not ADMIN_API_SECRET or not secrets.compare_digest(x_admin_secret or "", ADMIN_API_SECRET):

Copilot uses AI. Check for mistakes.
with db_context as db:
submission = db.get_submission_by_id(submission_id)
if submission is None:
raise HTTPException(status_code=404, detail="Submission not found")

db.delete_submission(submission_id)
return {"message": f"Submission {submission_id} deleted successfully"}
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The response format is inconsistent with the user delete endpoint. The user delete endpoint at line 833 returns {"status": "ok", "submission_id": submission_id} while this admin endpoint returns {"message": f"Submission {submission_id} deleted successfully"}. For consistency and API design coherence, both endpoints should use the same response format since they perform the same operation.

Suggested change
return {"message": f"Submission {submission_id} deleted successfully"}
return {"status": "ok", "submission_id": submission_id}

Copilot uses AI. Check for mistakes.
except HTTPException:
raise
except Exception as e:
raise HTTPException(
status_code=500, detail=f"Error deleting submission: {e}"
) from e
1 change: 1 addition & 0 deletions src/kernelbot/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
env.DISCORD_DEBUG_CLUSTER_STAGING_ID = os.getenv("DISCORD_DEBUG_CLUSTER_STAGING_ID")

env.ADMIN_TOKEN = os.getenv("ADMIN_TOKEN")
env.ADMIN_API_SECRET = os.getenv("ADMIN_API_SECRET", "")

# Only required to run the CLI against this instance
# setting these is required only to run the CLI against local instance
Expand Down
Loading