security: scrub leaked Composio API key from server/opencode.json - #16
Merged
Conversation
The committed `server/opencode.json` contained a live Composio API key (`ak_*`) and tool router id (`trs_*`) that leaked when commit c271660 overwrote the original placeholder values with a developer's actual credentials. The file is generated at runtime by `updateOpencodeConfig()` in `server/server.js` from the live `composio.create()` session, so it should never have been committed. - Restore the original `YOUR_API_KEY` / `YOUR_ROUTER_ID` placeholder contents (matching the version added in aee23f2) so a fresh checkout no longer ships a real key. - Add `server/opencode.json` to `.gitignore` so future runs of the server don't re-commit a regenerated key. The leaked key remains visible in git history at commit c271660 and must be rotated/revoked in the Composio dashboard regardless of this change. Scrubbing it from history requires a separate `git filter-repo` + force-push to `main` (handled outside this PR). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Saransh Rana <saransh@composio.dev>
.gitignore alone doesn't apply to tracked files — the server's updateOpencodeConfig() in server/server.js overwrites the file with live MCP credentials on every startup. With the file still tracked, a developer running `npm start` would see the regenerated file as a modification and could re-commit a real key. `git rm --cached` removes it from version control entirely; the placeholder content remains in the working tree as untracked, and fresh clones get the file generated on first server start. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Saransh Rana <saransh@composio.dev>
Contributor
|
@rohanprabhu can you please review the PR |
Contributor
Author
|
Post-PR status update
Follow-up commit pushed during this loop: Still blocked on (out of scope for this PR):
|
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.
Description
A live Composio API key (
ak_***REDACTED***) and tool router id (trs_***REDACTED***) were committed toserver/opencode.jsonin commitc271660, exposing them publicly on this repo.Root cause:
server/opencode.jsonis auto-generated at runtime byupdateOpencodeConfig()inserver/server.js(it writes the live MCP URL + headers fromcomposio.create()into the file every time the backend starts). The file was added inaee23f2withYOUR_API_KEY/YOUR_ROUTER_IDplaceholders, butc271660then overwrote those placeholders with a developer's actual session credentials and committed them. The file was never in.gitignore.This PR:
server/opencode.jsonto the original placeholder version (commitb581975).git rm --cached server/opencode.jsonso future regenerations by the server don't re-leak (commitd5bfc31)..gitignorealone doesn't apply to already-tracked files.server/opencode.jsonto.gitignoreso a futurenpm startwon't re-commit a regenerated key.Important — this PR alone is not enough
Rotate the leaked key in the Composio dashboard immediately. It has been public on this branch for the entirety of its lifetime and may already have been scraped — consider it compromised regardless of any history rewrite.
Git history still contains the secret at commit
c271660and in the diff of this PR (commitb581975). To remove it from history you need agit filter-repo(or BFG) pass followed by a force-push tomaster. Verified working pass — values to substitute are NOT in this PR; copy them from thec271660commit page (or fetch them locally) into yourscrub.txt:This rewrites every commit SHA on
master. Side effects:The diff of this PR itself shows the secret (commit
b581975has- "x-api-key": "<leaked key>"). Editing PR text won't fix that — the only way to make the diff safe is to force-push thegit filter-reporewrite first, then rebase this PR onto the new master. After the rewrite, the parent commit will already containYOUR_API_KEY, so the rebased PR will only show the structural change (untracking +.gitignoreentry) with no secret in the diff.Suggested order of operations:
git filter-reporewrite + force-push master (above).How did I test this PR
cat server/opencode.jsonafter the change matches the original placeholder version added inaee23f2(verified viagit show aee23f2:server/opencode.json).grep -rn "<leaked-key-substring>" .(with the actual literal locally) returns nothing in the post-PR working tree.git check-ignore -v server/opencode.jsonconfirms the file is ignored, so futurenpm startruns that regenerate it won't re-leak the key.git filter-repopass above on a fresh clone:git log --all -p -S "<leaked-key>"returns 0 hits andgit log --all -p -S "<leaked-router-id>"returns 0 hits after the rewrite.Triggered by: saransh@composio.dev | Source: slack
Session: https://zen-api-production-4c98.up.railway.app/dashboard/#/chat/zen-07ecd6f2e120