fix(agent): add user ownership check to clearContext endpoint#72
Open
sebastiondev wants to merge 1 commit into
Open
Conversation
|
Thanks for the report and detailed analysis.
I reviewed the finding and the reasoning appears sound. The lack of an
ownership check in clearContext is inconsistent with the authorization
pattern already used by other session-mutating endpoints in the controller.
The proposed fix aligns with the existing implementation by reusing
requireActiveSession(userId,
sessionId, res), which ensures both session existence and ownership
validation.
The PoC, root cause analysis, and remediation are clear and reproducible. I
don't see any functional regression risk from adopting the same
authorization helper already used elsewhere in the codebase.
Thanks for the contribution and responsible disclosure.A
…On Wed, Jun 3, 2026 at 4:15 AM Sebastion ***@***.***> wrote:
Vulnerability Summary
The clearContext endpoint in backend/src/controllers/agent.controller.ts
(line 413) has a missing authorization check (CWE-862 — Missing
Authorization). The endpoint accepts a sessionId from the request body
and looks it up using SessionsModel.findOne({ sessionId }) without
verifying that the session belongs to the authenticated user. This allows
any authenticated user to clear another user's session context by providing
their sessionId.
This is an IDOR (Insecure Direct Object Reference) vulnerability. Every
other session-mutating endpoint in the same controller already uses requireActiveSession(userId,
sessionId, res), which filters by both sessionId and uid. The clearContext
endpoint was the only one missing this check.
*Affected route:* POST /clear-context (defined in
backend/src/routes/agent.routes.ts:37)
*Severity:* Medium — requires authentication (the route is gated by
verifySess middleware) and knowledge of a target user's sessionId, but
session IDs are predictable UUIDs that may be leaked through logs, shared
URLs, or other side channels.
Proof of Concept
An authenticated attacker can clear any other user's active session
context:
# Attacker authenticates and obtains their own session token
ATTACKER_TOKEN="<attacker's valid session token>"
# Attacker knows or guesses the victim's sessionId (a UUID)
VICTIM_SESSION_ID="<victim's sessionId>"
# This request succeeds even though the session belongs to a different user
curl -X POST https://<host>/api/agent/clear-context \
-H "Authorization: Bearer $ATTACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"sessionId": "'"$VICTIM_SESSION_ID"'"}'
# Response: {"message": "Context cleared"}# The victim's session messages, subagents, swarms, and agent state are all wiped.
The victim loses their entire session context — all messages, active
subagents, swarm state, and token history — with no indication of who
triggered the reset.
Fix Description
The fix replaces the unscoped SessionsModel.findOne({ sessionId }) call
with requireActiveSession(userId, sessionId, res), which is the same
helper used by all other session-mutating endpoints in this controller (
sendMessage, stopSession, deleteSession, etc.). This helper queries by
both sessionId and uid, ensuring a user can only clear context for
sessions they own.
The change is minimal (3 lines changed in 1 file) and follows the exact
same pattern already established throughout the controller.
What Was Tested
- Verified that requireActiveSession correctly filters by both uid and
sessionId (inspected backend/src/services/session.helpers.ts)
- Confirmed that all other session-mutating endpoints in the same
controller already use this helper
- Verified the route is defined at POST /clear-context with verifySess
middleware in backend/src/routes/agent.routes.ts:37
- Confirmed res.locals.userId is populated by the verifySess
middleware, consistent with its usage in all sibling endpoints
Adversarial Review
Before submitting, we verified this wasn't already mitigated: the
verifySess middleware only authenticates the user (populates
res.locals.userId) but does not perform session ownership checks — that
responsibility falls to each handler. We confirmed that clearContext was
the only endpoint in the controller that skipped the ownership check. The
sessionId parameter comes directly from req.body with no additional
authorization filtering before the database query.
------------------------------
*Submitted by Sebastion — autonomous open-source security research from
Foundation Machines <https://foundationmachines.ai>. Free for public repos
via the Sebastion AI GitHub App <https://github.com/apps/sebastionai>.*
------------------------------
You can view, comment on, or merge this pull request online at:
#72
Commit Summary
- 3b5a0aa
<3b5a0aa>
fix: add user ownership check to clearContext (CWE-862)
File Changes
(1 file <https://github.com/bugbasesecurity/pentest-copilot/pull/72/files>
)
- *M* backend/src/controllers/agent.controller.ts
<https://github.com/bugbasesecurity/pentest-copilot/pull/72/files#diff-d249b0de3608f8aa4c8befa33f0cac0a5167251d3a2f3d3b4b89112fce4843d8>
(5)
Patch Links:
- https://github.com/bugbasesecurity/pentest-copilot/pull/72.patch
- https://github.com/bugbasesecurity/pentest-copilot/pull/72.diff
—
Reply to this email directly, view it on GitHub
<#72?email_source=notifications&email_token=BUHB4E46AQCO2Z4YWPRFH6L456C43A5CNFSNUABEM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UF4ZTOOJSGMYTEMJYGKTHEZLBONXW5KTTOVRHGY3SNFRGKZFFMV3GK3TUVRTG633UMVZF6Y3MNFRWW>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BUHB4E4D3G3MLCDKBCEC4MT456C43AVCNFSM6AAAAACZYARPSGVHI2DSMVQWIX3LMV43ASLTON2WKOZUGU3TMMZUG44DONY>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
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.
Vulnerability Summary
The
clearContextendpoint inbackend/src/controllers/agent.controller.ts(line 413) has a missing authorization check (CWE-862 — Missing Authorization). The endpoint accepts asessionIdfrom the request body and looks it up usingSessionsModel.findOne({ sessionId })without verifying that the session belongs to the authenticated user. This allows any authenticated user to clear another user's session context by providing theirsessionId.This is an IDOR (Insecure Direct Object Reference) vulnerability. Every other session-mutating endpoint in the same controller already uses
requireActiveSession(userId, sessionId, res), which filters by bothsessionIdanduid. TheclearContextendpoint was the only one missing this check.Affected route:
POST /clear-context(defined inbackend/src/routes/agent.routes.ts:37)Severity: Medium — requires authentication (the route is gated by
verifySessmiddleware) and knowledge of a target user'ssessionId, but session IDs are predictable UUIDs that may be leaked through logs, shared URLs, or other side channels.Proof of Concept
An authenticated attacker can clear any other user's active session context:
The victim loses their entire session context — all messages, active subagents, swarm state, and token history — with no indication of who triggered the reset.
Fix Description
The fix replaces the unscoped
SessionsModel.findOne({ sessionId })call withrequireActiveSession(userId, sessionId, res), which is the same helper used by all other session-mutating endpoints in this controller (sendMessage,stopSession,deleteSession, etc.). This helper queries by bothsessionIdanduid, ensuring a user can only clear context for sessions they own.The change is minimal (3 lines changed in 1 file) and follows the exact same pattern already established throughout the controller.
What Was Tested
requireActiveSessioncorrectly filters by bothuidandsessionId(inspectedbackend/src/services/session.helpers.ts)POST /clear-contextwithverifySessmiddleware inbackend/src/routes/agent.routes.ts:37res.locals.userIdis populated by theverifySessmiddleware, consistent with its usage in all sibling endpointsAdversarial Review
Before submitting, we verified this wasn't already mitigated: the
verifySessmiddleware only authenticates the user (populatesres.locals.userId) but does not perform session ownership checks — that responsibility falls to each handler. We confirmed thatclearContextwas the only endpoint in the controller that skipped the ownership check. ThesessionIdparameter comes directly fromreq.bodywith no additional authorization filtering before the database query.Submitted by Sebastion — autonomous open-source security research from Foundation Machines. Free for public repos via the Sebastion AI GitHub App.