Skip to content

fix(httpapi): percent-decode the secret name on DELETE /secrets/{name} - #1775

Merged
Dumbris merged 2 commits into
smart-mcp-proxy:mainfrom
rudycelekli:fix/secret-delete-name-decode-20261024-01
Oct 29, 2026
Merged

Dumbris merged 2 commits into
smart-mcp-proxy:mainfrom
rudycelekli:fix/secret-delete-name-decode-20261024-01

Conversation

@rudycelekli

Copy link
Copy Markdown
Contributor

Problem

Secret names aren't restricted. The reference parser accepts anything but } after the type, so ${keyring:openai:prod} is a valid reference and POST /api/v1/secrets stores it as-is. The Web UI deletes with /api/v1/secrets/${encodeURIComponent(name)}, which sends openai%3Aprod. chi routes on RawPath, so chi.URLParam(r, "name") returns the encoded value and handleDeleteSecret asks the keyring to delete openai%3Aprod, an entry that doesn't exist. The real secret stays in the keyring.

Fix

Decode {name} with the existing decodePathParam, matching the other path-param handlers.

Test

TestDeleteSecret_DecodesNameParam registers a recording keyring provider and sends DELETE /api/v1/secrets/openai%3Aprod. On main the provider receives openai%3Aprod; with this change it receives openai:prod. go test -count=1 ./internal/httpapi/ passes.

Made with Cursor

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Secret names may contain any character but '}', so ${keyring:openai:prod}
is a valid reference. The Web UI builds the delete URL with
encodeURIComponent and chi routes on RawPath, so {name} arrived as
openai%3Aprod and the keyring delete targeted an entry that does not
exist, leaving the real secret in place. Decode it with decodePathParam
like the other path-param handlers.
@rudycelekli
rudycelekli force-pushed the fix/secret-delete-name-decode-20261024-01 branch from f01ff35 to 62fb6f4 Compare October 24, 2026 22:18
Review finding (P2): decodePathParam ran unconditionally, so a name whose
only escape is a literal %XX (e.g. "a%41", sent as "a%2541") left RawPath
empty, chi matched the already-decoded Path, and the second decode deleted
a different keyring entry ("aA"). Decode only when RawPath is set, and add
a regression test covering literal-percent names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Dumbris

Dumbris commented Oct 26, 2026

Copy link
Copy Markdown
Member

Verified the bug on main and the fix; thank you! The review found one gap, so I pushed a small maintainer commit on top of your branch: decoding unconditionally decodes twice when Go leaves RawPath empty, i.e. a name whose only escape is a literal %XX: deleting a%41 removed aA. On a delete path that hits another real secret, so the commit decodes only when r.URL.RawPath is set and adds literal-percent cases.

I will merge once CI is green.

@Dumbris Dumbris left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Verified: the bug reproduces on main and the PR fixes it. The review found one gap, closed by the maintainer commit on top (regression test included). Race tests and CI lint for the touched packages are clean on this branch merged with main, and the result was cross-reviewed clean.

@Dumbris
Dumbris merged commit dfa2b83 into smart-mcp-proxy:main Oct 29, 2026
48 checks passed
@Dumbris

Dumbris commented Oct 29, 2026

Copy link
Copy Markdown
Member

Merged. Thank you, @rudycelekli! Deleting a secret whose name the Web UI percent-encodes (like openai%3Aprod) now removes the real openai:prod entry instead of a name that does not exist, and a literal % in a name is not double-decoded. I confirmed the decoded name on a live instance.

Contributions like this are what keep MCPProxy moving, and they matter a lot to the project.

One small ask, only if you feel like it: a short public note about your change (a tweet, a LinkedIn post, a line in a community you are part of) helps more people discover MCPProxy. No pressure at all, and I would be glad to repost it.

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.

3 participants