fix(02-03): scrub PKCE and OAuth form fields by name

Value-based replace can miss a code_verifier when an authorization code is a substring of it, which 502'd MCP token capture.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jakub Zych
2026-09-17 13:43:27 +02:00
parent 2eb9b4b0c9
commit 7a6c669e3a
2 changed files with 56 additions and 0 deletions

View File

@@ -448,6 +448,15 @@ func ScrubStep(store *Store, step *Step) error {
step.Request.Query = replaceAll(step.Request.Query, pairs)
step.Request.Headers = scrubMap(step.Request.Headers, pairs)
step.Request.Body = Body(replaceAll(string(step.Request.Body), pairs))
for _, rule := range step.Capture {
if strings.TrimSpace(rule.From) != "request.form" {
continue
}
if rule.Name == "" || rule.As == "" {
continue
}
step.Request.Body = Body(scrubFormField(string(step.Request.Body), rule.Name, rule.As))
}
step.Response.Headers = scrubMap(step.Response.Headers, pairs)
step.Response.Body = Body(replaceAll(string(step.Response.Body), pairs))
return rejectUnclassifiedCredentials(*step)
@@ -510,6 +519,14 @@ func phpJSONEscape(s string) string {
return strings.ReplaceAll(s, "/", `\/`)
}
func scrubFormField(body, name, as string) string {
if name == "" || as == "" || body == "" {
return body
}
re := regexp.MustCompile(`(?i)(^|&)(` + regexp.QuoteMeta(name) + `=)[^&]*`)
return re.ReplaceAllString(body, `${1}${2}{{`+as+`}}`)
}
func replaceIsolated(s, old, neu string) string {
if old == "" || s == "" {
return s