{"record":{"id":"ce745171559a8e2c","repo":"googleapis/mcp-toolbox","slug":"parameter-q-is-secure-and-must-not-be-passed-in-s","errorCode":null,"errorMessage":"parameter %q is secure and must not be passed in standard arguments","messagePattern":"parameter %q is secure and must not be passed in standard arguments","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/server/mcp/v20260728/method.go","lineNumber":891,"sourceCode":"\t\tResult:  result,\n\t}, nil\n}\n\n// validateAndMergeSecureParams validates and merges standard and secure arguments.\nfunc validateAndMergeSecureParams(ctx context.Context, req *CallToolRequest, paramDefs parameters.Parameters) (map[string]any, error, error) {\n\tsecureParamMap := make(map[string]bool)\n\turlParams, _ := util.UrlParamsFromContext(ctx)\n\n\tfor _, p := range paramDefs {\n\t\tif p != nil && p.GetSecure() {\n\t\t\tsecureParamMap[p.GetName()] = true\n\t\t}\n\t}\n\n\t// Validate that secure parameters are not passed in standard arguments (Agent error)\n\tfor argName := range req.Params.Arguments {\n\t\tif secureParamMap[argName] {\n\t\t\treturn nil, fmt.Errorf(\"parameter %q is secure and must not be passed in standard arguments\", argName), nil\n\t\t}\n\t}\n\n\t// Validate that non-secure parameters are not passed in secureArguments (Protocol error)\n\tfor argName := range req.Params.SecureArguments {\n\t\tif !secureParamMap[argName] {\n\t\t\treturn nil, nil, fmt.Errorf(\"parameter %q is not secure and must not be passed in secureArguments\", argName)\n\t\t}\n\t}\n\n\t// Validate that required secure parameters are present in secureArguments (Protocol error)\n\tfor _, p := range paramDefs {\n\t\tif p != nil && p.GetSecure() {\n\t\t\tname := p.GetName()\n\t\t\tif p.GetValueFromParam() == \"\" {\n\t\t\t\tif _, bound := urlParams[name]; !bound {\n\t\t\t\t\tif parameters.CheckParamRequired(p.GetRequired(), p.GetDefault()) {\n\t\t\t\t\t\tif req.Params.SecureArguments == nil {","sourceCodeStart":873,"sourceCodeEnd":909,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/server/mcp/v20260728/method.go#L873-L909","documentation":"During tools/call, validateAndMergeSecureParams enforces that parameters marked secure (secure=true in the tool's parameter definition) are supplied only via the SecureArguments extension field, never in the standard Arguments map. Passing a secure parameter in standard arguments is treated as an agent-side error (first return = agent error) because the value would be exposed in the non-secure payload.","triggerScenarios":"A tools/call request includes a key in params.arguments whose name matches a parameter defined with secure: true, e.g. putting a password/api-key parameter in arguments instead of secureArguments.","commonSituations":"Clients not updated for the com.google.cloud/toolbox.v1 secure-arguments extension still sending all params in arguments; hand-written MCP clients; LLM agent copying all parameter values into the plain arguments object.","solutions":["Move the secure parameter value into params.secureArguments and remove it from params.arguments","Declare the client capability extension \"com.google.cloud/toolbox.v1\" in initialize capabilities and use secureArguments for secure params","Change the parameter's secure: true flag in tools.yaml to false if the value is not actually sensitive (not recommended for secrets)"],"exampleFix":"// before\n{\"method\": \"tools/call\", \"params\": {\"name\": \"run_query\", \"arguments\": {\"password\": \"hunter2\"}}}\n// after\n{\"method\": \"tools/call\", \"params\": {\"name\": \"run_query\", \"arguments\": {}, \"secureArguments\": {\"password\": \"hunter2\"}}}","handlingStrategy":"validation","validationCode":"const secureNames = new Set(toolParams.filter(p => p.secure).map(p => p.name));\nfor (const key of Object.keys(args)) {\n  if (secureNames.has(key)) throw new Error(`\"${key}\" is secure; send it in secureArguments, not arguments`);\n}","typeGuard":"function hasNoSecureInStandard(args, secureNames) {\n  return Object.keys(args).every(k => !secureNames.has(k));\n}","tryCatchPattern":"try {\n  await mcp.toolsCall({ name: tool, arguments: args, secureArguments: secureArgs });\n} catch (e) {\n  if (/is secure and must not be passed in standard arguments/.test(e.message)) {\n    const key = e.message.match(/parameter \"([^\"]+)\"/)?.[1];\n    secureArgs[key] = args[key]; delete args[key]; // retry with split payloads\n  } else { throw e; }\n}","preventionTips":["Inspect the tool's parameter manifest and split params by the secure flag before every call","Advertise the com.google.cloud/toolbox.v1 client capability and route secure params to secureArguments","Never copy full argument maps wholesale; build arguments from typed schemas","Review tools.yaml secure flags after upgrades and regenerate client call templates"],"tags":["mcp","security","secure-parameters","jsonrpc"],"backgroundTag":"secure-param-in-plain-arguments","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}