Skip to content

🛡️ Sentinel: [CRITICAL] Fix missing auth on migrate-formats#14

Open
Horus0305 wants to merge 1 commit intomainfrom
sentinel-secure-migrate-formats-2924955117721349805
Open

🛡️ Sentinel: [CRITICAL] Fix missing auth on migrate-formats#14
Horus0305 wants to merge 1 commit intomainfrom
sentinel-secure-migrate-formats-2924955117721349805

Conversation

@Horus0305
Copy link
Copy Markdown
Owner

🚨 Severity: CRITICAL
💡 Vulnerability: The /auth/migrate-formats endpoint was publicly accessible without authentication, allowing any user to trigger database migrations and data modification.
🎯 Impact: Unauthorized users could manipulate data or cause denial of service by repeatedly triggering migrations.
🔧 Fix:

  • Added ADMIN_SECRET validation to CricketGame/backend/core/config.py.
  • Updated /auth/migrate-formats in CricketGame/backend/api/auth.py to require X-Admin-Secret header.
  • Implemented secure secrets.compare_digest check.
    ✅ Verification:
  • Added CricketGame/backend/test_auth.py with tests covering missing, invalid, and valid secret scenarios.
  • Verified tests pass with pytest.

PR created automatically by Jules for task 2924955117721349805 started by @Horus0305

🚨 Severity: CRITICAL
💡 Vulnerability: The `/auth/migrate-formats` endpoint was publicly accessible without authentication.
🔧 Fix: Added `X-Admin-Secret` header validation using `secrets.compare_digest`.
✅ Verification: Added backend tests verifying 403/200 responses.

Co-authored-by: Horus0305 <98160215+Horus0305@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 21, 2026 17:18
@google-labs-jules
Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@vercel
Copy link
Copy Markdown

vercel bot commented Feb 21, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
very-important-study-material Ready Ready Preview, Comment Feb 21, 2026 5:18pm

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to remediate a critical security issue by restricting the /auth/migrate-formats data-migration endpoint to callers who provide an admin secret, preventing unauthenticated users from triggering DB-modifying migrations.

Changes:

  • Added ADMIN_SECRET configuration in backend/core/config.py.
  • Updated /auth/migrate-formats to require X-Admin-Secret and validate it using secrets.compare_digest.
  • Added an auth test module for the new admin-secret requirement (and introduced a committed SQLite DB artifact).

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 4 comments.

File Description
cricket.db Adds a full SQLite database file to the repo (problematic artifact; not required for the auth fix).
CricketGame/backend/test_auth.py Adds tests for the admin-secret behavior, but currently introduces import-time side effects and doesn’t match existing test execution conventions.
CricketGame/backend/core/config.py Introduces ADMIN_SECRET env config, but currently includes a hardcoded fallback secret in non-prod.
CricketGame/backend/api/auth.py Requires X-Admin-Secret on /auth/migrate-formats and rejects invalid secrets with 403.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1 to +22
from fastapi.testclient import TestClient
from backend.main import app
from backend.core.config import ADMIN_SECRET
from backend.data.database import init_db

# Initialize DB for tests
init_db()

client = TestClient(app)

def test_migrate_formats_no_header():
# Expect 422 because the header is required (Header(...))
response = client.get("/auth/migrate-formats")
assert response.status_code == 422

def test_migrate_formats_wrong_header():
# Expect 403 because the secret is invalid
response = client.get("/auth/migrate-formats", headers={"X-Admin-Secret": "wrong-secret"})
assert response.status_code == 403
assert response.json()["detail"] == "Invalid admin secret"

def test_migrate_formats_correct_header():
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

init_db() is executed at import time and TestClient(app) is created as a module-level global. With this app, constructing the TestClient will run the FastAPI lifespan (which starts the background learning processor) and init_db() will write to the real sqlite:///./cricket.db by default. This can create/modify local files during test import and make tests flaky. Prefer creating the client inside each test (or a fixture), and configure an isolated test database (e.g., set DATABASE_URL to an in-memory/temporary SQLite URL before importing the app).

Suggested change
from fastapi.testclient import TestClient
from backend.main import app
from backend.core.config import ADMIN_SECRET
from backend.data.database import init_db
# Initialize DB for tests
init_db()
client = TestClient(app)
def test_migrate_formats_no_header():
# Expect 422 because the header is required (Header(...))
response = client.get("/auth/migrate-formats")
assert response.status_code == 422
def test_migrate_formats_wrong_header():
# Expect 403 because the secret is invalid
response = client.get("/auth/migrate-formats", headers={"X-Admin-Secret": "wrong-secret"})
assert response.status_code == 403
assert response.json()["detail"] == "Invalid admin secret"
def test_migrate_formats_correct_header():
import os
import pytest
from fastapi.testclient import TestClient
# Configure an isolated test database before importing the app
os.environ.setdefault("DATABASE_URL", "sqlite:///:memory:")
from backend.main import app
from backend.core.config import ADMIN_SECRET
from backend.data.database import init_db
@pytest.fixture
def client():
# Initialize DB for each test using the test database
init_db()
with TestClient(app) as test_client:
yield test_client
def test_migrate_formats_no_header(client):
# Expect 422 because the header is required (Header(...))
response = client.get("/auth/migrate-formats")
assert response.status_code == 422
def test_migrate_formats_wrong_header(client):
# Expect 403 because the secret is invalid
response = client.get("/auth/migrate-formats", headers={"X-Admin-Secret": "wrong-secret"})
assert response.status_code == 403
assert response.json()["detail"] == "Invalid admin secret"
def test_migrate_formats_correct_header(client):

Copilot uses AI. Check for mistakes.
data = response.json()
assert "format_stats_2v2_merged" in data
assert "duplicate_rows_removed" in data
assert "match_history_fixed" in data
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

This test module is written in pytest style, but the existing backend tests in this repo are standalone scripts (with run_all_tests() + __main__) and requirements.txt does not include pytest. Unless the project is switching to pytest (and adding it to dependencies/CI), these tests likely won't run in the current test workflow. Either adapt this test to the existing script pattern, or add pytest as a dependency and update the repo’s test instructions accordingly.

Suggested change
assert "match_history_fixed" in data
assert "match_history_fixed" in data
def run_all_tests():
"""
Run all tests in this module.
This mirrors the standalone script pattern used by other backend tests.
"""
test_migrate_formats_no_header()
test_migrate_formats_wrong_header()
test_migrate_formats_correct_header()
if __name__ == "__main__":
run_all_tests()

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +19
ADMIN_SECRET = os.getenv("ADMIN_SECRET")
if not ADMIN_SECRET:
if APP_ENV in ("production", "prod"):
raise ValueError("ADMIN_SECRET is required in production")
ADMIN_SECRET = "super-secret-admin-key"

Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

ADMIN_SECRET falls back to a hardcoded default value when APP_ENV is not production. If a deployment forgets to set APP_ENV=production (or uses another value like staging), the admin protection becomes a known, guessable secret. Prefer failing fast when ADMIN_SECRET is unset (in all environments), or at least generate a random per-run dev secret and log it explicitly to avoid a stable default.

Copilot uses AI. Check for mistakes.
Comment on lines 66 to +70
@router.get("/migrate-formats")
def migrate_formats(db: Session = Depends(get_db)):
def migrate_formats(
x_admin_secret: str = Header(..., alias="X-Admin-Secret"),
db: Session = Depends(get_db),
):
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

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

This endpoint performs a data migration (writes + commit) but is exposed as a GET. GET requests are commonly cached/retried/prefetched and are expected to be side-effect free, which increases the risk of accidental or repeated migrations. Consider switching this route to POST (or another non-GET verb) to better match HTTP semantics and reduce operational risk.

Copilot uses AI. Check for mistakes.
Copilot AI added a commit that referenced this pull request Feb 21, 2026
Co-authored-by: Horus0305 <98160215+Horus0305@users.noreply.github.com>
Horus0305 added a commit that referenced this pull request Feb 21, 2026
Merge PRs #14, #15, #16: auth fix, async CPU moves, lobby a11y
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants