fix(security): Remove Dead Auth Guard in Challenge Check & Hint Endpoints#515
Open
prince-shakyaa wants to merge 1 commit into
Open
Conversation
…ints Fixes GenAI-Security-Project#514 ## Problem POST /api/v1/challenges/{id}/check and POST /api/v1/challenges/{id}/hint both used get_session_context + a manual 'if not session_context: raise 401' guard. Because get_session_context NEVER returns None (it always returns request.state.session_context set by SessionMiddleware), the guard was dead code — always False. Temporary/anonymous sessions passed through freely. Impact: - Any visitor could spam POST /check → inflated attempt counters in DB - Any visitor could spam POST /hint → full hint text revealed without auth ## Fix - Add get_authenticated_session_context to the import in challenges.py - Swap check_challenge and use_hint to Depends(get_authenticated_session_context) - Remove the now-redundant dead 'if not session_context' guards - get_authenticated_session_context raises HTTP 401 automatically when session_context.is_temporary is True (caller hasn't bound an email) GET /api/v1/challenges and GET /api/v1/challenges/{id} are unchanged — they intentionally remain publicly browsable. ## Tests New file: tests/unit/apps/ctf/test_challenge_auth.py (9 tests, all passing) BUG-514-001: temp session rejected on check_challenge PASS BUG-514-002: temp session rejected on use_hint PASS BUG-514-003: auth session not blocked (happy path) PASS BUG-514-004: check_challenge dependency introspection PASS BUG-514-005: use_hint dependency introspection PASS BUG-514-006: dead guard removed from check_challenge source PASS BUG-514-007: dead guard removed from use_hint source PASS BUG-514-008: end-to-end POST /check → HTTP 401 PASS BUG-514-009: end-to-end POST /hint → HTTP 401 PASS
Author
|
Hey @saikishu @e2hln , |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(security): Remove Dead Auth Guard in Challenge Check & Hint Endpoints
Fixes #514
What's the Problem?
Two endpoints in
finbot/apps/ctf/routes/challenges.pycontain an authenticationguard that can never fire:
The guard reads
if not session_context, butsession_contextis injected viaget_session_contextwhich is defined as:The
SessionMiddlewaresetsrequest.state.session_contextfor every request :including anonymous visitors with no email bound (temporary sessions). So the value
is always a truthy
SessionContextobject. Theif not session_contextconditionevaluates to
False100% of the time, and theHTTPException(401)is never raised.Result: Temporary/unauthenticated sessions bypass the guard on both:
POST /api/v1/challenges/{challenge_id}/check- attempt counters get inflated by throwaway sessionsPOST /api/v1/challenges/{challenge_id}/hint- full hint text is leaked to anyone with a browser cookie, no registration requiredThis is the same class of bug as #511 (sidecar endpoint), but with a different root
cause: a dead
if not Xcheck instead of using the wrong dependency directly.What This PR Does
1. Code Fix :
finbot/apps/ctf/routes/challenges.pySwap the weak
get_session_contextdependency toget_authenticated_session_contexton both write endpoints, and remove the now-redundant dead code guards.
get_authenticated_session_contextraisesHTTP 401 Unauthorizedautomatically whensession_context.is_temporaryisTrue- exactly what the dead guard was supposedto do but never could.
check_challengeendpointuse_hintendpoint@router.post("/challenges/{challenge_id}/hint", response_model=HintResponse) def use_hint( challenge_id: str, - session_context: SessionContext = Depends(get_session_context), + session_context: SessionContext = Depends(get_authenticated_session_context), db: Session = Depends(get_db), ): - if not session_context: - raise HTTPException(status_code=401, detail="Authentication required") ...2. New Test File :
tests/unit/apps/ctf/test_challenge_auth.pyA dedicated unit test file following the exact same pattern as
test_sidecar_auth.py(from PR #512).Approach
@pytest.mark.unit_StubSessionstubget_session_contextif not session_contextlines are gonefastapi.testclient.TestClientFiles Changed
finbot/apps/ctf/routes/challenges.pytests/unit/apps/ctf/test_challenge_auth.pyTotal: 2 files, ~206 lines net change.
Before vs After
POST /api/v1/challenges/{id}/checkPOST /api/v1/challenges/{id}/hintPOST /api/v1/challenges/{id}/checkPOST /api/v1/challenges/{id}/hintRoot Cause vs. Issue #511
get_session_contextinstead ofget_authenticated_session_context)if not session_contextwhich is alwaysFalse)How to Test
Checklist
get_session_context→get_authenticated_session_contextinchallenges.pyif not session_context: raise HTTPException(401)deleted from both functionstest_challenge_auth.pycreated with 9 testsGET /api/v1/challengesandGET /api/v1/challenges/{id}are unchanged (still publicly browsable)Closes #514