The user was removed. The proxy kept acting.
Compare the new-session denial, native-tool denial, and provider effects.
See the result →A shared GitHub connection allowed test user B to use an account. We opened a session for B, then removed B from the connection’s access list. Composio denied a new session and the native GitHub tool, yet Proxy Execute in B’s retained session read a private test repository and created a GitHub issue.
After B was denied, the retained proxy returned a 200 private repository read and a 201 GitHub issue creation. The native tool on that same session returned 403. We confirmed the issues independently at GitHub and repeated the path through a controlled application.
Compare the new-session denial, native-tool denial, and provider effects.
See the result →Follow the access-list change, private read, and GitHub issue.
Follow the test →See the narrower key and the B-facing application control.
Inspect the path →Review the project, session, key, and account-state controls.
Read the controls →A SHARED GitHub connection initially allowed B. We created B’s session, then updated the connection’s access list to explicitly deny B and read it back to confirm the change. The connection remained active.
| Action after B was removed | Observed result |
|---|---|
| Create a new B session pinned to the connection | 400 — B was unauthorized |
| Use the native GitHub issue tool in B’s retained session | 403 — B was unauthorized |
| Read the private repository through Proxy Execute in that session | GitHub 200; repository marked private |
| Create a test issue through Proxy Execute in that session | GitHub 201; issue appeared at the provider |
The same access change produced two different answers. Composio denied B at new session creation and native tool execution. Its retained Proxy Execute session continued sending authenticated requests to GitHub. The harmless test issue in our own private repository shows an action at the provider after the access change.
The test used one Composio organization, an owned private GitHub test repository, and composio==0.25.0.
200.#5.The connection owner created the shared connection and allowed B. We pinned it into B’s session and confirmed a private repository read before changing access. At 21:24 UTC on October 9, 2026, we updated the access list to disable access for all users by default, empty the allowed-user list, and put B in the denied-user list. A connection read confirmed those settings.
The retained B session then called session.proxy_execute() for the private repository. GitHub returned 200 and identified the repository as private. A fresh B session could not pin the connection. The native GITHUB_CREATE_AN_ISSUE tool in the retained session returned 403. Proxy Execute in that session created test issue #5 with GitHub 201. A separate signed-in GitHub check found the issue.
The provider read and issue creation were checked at GitHub. The issue was a harmless marker in a repository we owned; its existence establishes a write after the access change.
The follow-up tests narrowed the permissions needed by the caller and showed how an app user could reach the retained proxy without receiving the Composio key.
A second key in the same Composio project had session-management read, session tool-execution write, and Proxy Execute write. It had no connected-account read or write and could not create a session.
The narrow key could not read the connected account directly. The native GitHub tool in B’s retained session still returned 403.
It read the private repository with GitHub 200 and created test issue #6 with GitHub 201. GitHub independently confirmed the issue.
A small local app held the narrow Composio key on its server. B authenticated to the app with an application token, and the server mapped B to the retained session.
B’s client supplied no Composio key, session ID, connection ID, provider URL, or free-form tool arguments. The app exposed fixed test actions. The shared connection’s access list explicitly denied B before and after the run.
The app’s native GitHub action returned 403. Its Proxy Execute action read the private repository with GitHub 200 and created test issue #7 with GitHub 201. An independent GitHub read confirmed the title, body, and creation time.
An app that exposes a proxy action to its user can carry a server-held project key into a retained session after the shared access list removes that user. This was a controlled integration with application authentication supplied by the test harness.
We tested new sessions, another project, reduced key permissions, changed session restrictions, and an inactive connection.
| Control | Observed result |
|---|---|
| Fresh B session or later attempt to attach the connection | Rejected with 400 |
| Separate Composio project and its own key | Could not load the original session or connection |
| Proxy call without an API key | Rejected with 401 |
| Key with session-read permission only | Proxy call rejected with 403 |
| Remove the session’s explicit connection pin | Proxy read rejected with 400 |
| Restrict the session to zero toolkits | GitHub proxy call rejected with 400 |
| Temporarily make the connection inactive | Retained-session proxy calls rejected with 400 |
We restored the connection to active after the inactive-account control; B remained explicitly denied. The retained proxy path still worked roughly 20 minutes after the access-list update. Its maximum lifetime was not measured.
The observed path requires an already-open session and a way to execute through it in the same Composio project. The tested calls did not cross a project boundary or expose an OAuth token. The provider evidence covers GitHub in this fixture; other providers were not tested.
Proxy Execute should check the current shared-connection access list against the session’s user before it injects credentials or forwards each request.
Composio could also invalidate affected connection pins as soon as the access list changes. Either approach needs a regression test that opens B’s session while allowed, removes B, and checks that both proxy reads and writes are denied in the retained session.
This is a proposed correction. The investigation measured hosted behavior and its controls; it did not test a Composio code change.
We submitted this finding through Composio’s private GitHub Security Advisory process as GHSA-hf4g-q94r-9rv3.
The captured advisory page showed a High label and Triage status. That is the recorded status at the time of capture; its current review state belongs to the private advisory.
The evidence package records the access-list change and readback, request statuses, execution-only key permissions, app client and server receipts, and independent GitHub confirmation of the test issues. This public report omits project credentials, OAuth material, session identifiers, and the private repository’s contents.
B was removed from a shared connection, and Composio enforced that removal at new session creation and native tool execution. A retained Proxy Execute session continued to use the connection for a private read and provider-confirmed writes. Access removal needs to reach the action that actually sends the request.
Composio’s documentation describes access lists for shared connections and the session proxy that sends requests with connection credentials. The provider and application receipts were supplied privately with the advisory.
We follow the user, session, connection, and provider effect through the change, then test the controls against the same action.
48-hour Rapid Scan →