Skip to content

owasp-no-credentials-in-url flags any parameter whose name merely contains "secret" or "token" (e.g. secretPath), with no per-parameter escape #251

Description

@david-long1

Summary

owasp-no-credentials-in-url tests parameter names with

regexp.MustCompile(`(?i)^.*(client_?secret|token|access_?token|refresh_?token|id_?token|password|secret|api-?key).*$`)

(openapi/linter/rules/owasp_no_credentials_in_url.go). That is a case-insensitive, unanchored substring match, carried over from Spectral's owasp:api2:2023-no-credentials-in-url, applied to every path and query parameter name. So a path parameter called secretPath (the storage path of a secret in a secrets-manager API, not a credential) is reported as an error, and so are tokenId and mySecretPath. Any domain whose nouns include "secret" or "token" trips it on names that carry no credential at all.

There is no per-parameter escape. The only ways to make the finding go away are --disable owasp-no-credentials-in-url (or disabled: true / a lower severity for the rule in lint.yaml), all of which switch the check off for the whole document, including the parameters it should catch.

Reproduction

openapi: 3.1.0
info: { title: t, version: "1" }
paths:
  /files/{secretPath}:
    get:
      parameters: [{ name: secretPath, in: path, required: true, schema: { type: string } }]
      responses: { "200": { description: ok } }
$ openapi spec lint owasp.yaml | grep credentials
 6:28 error   owasp-no-credentials-in-url      URL parameter `secretPath` appears to contain credentials - avoid passing sensitive data in URLs
$ openapi spec lint --disable owasp-no-credentials-in-url owasp.yaml | grep -c credentials
0

Same result with the name changed to secret_path, tokenId or mySecretPath. openapi built with go install github.com/speakeasy-api/openapi/cmd/openapi@latest (v0.0.0-20260826005500-83ebf39fa45e).

Suggested fix

Either would help; both would be better:

  1. Token-aware matching. Split the name on _, - and camelCase boundaries and flag it when the credential word is the head (last) token: clientSecret, access_token, api-key, password are credentials, while secretPath, tokenId, secretName name a path, an id, a name. A cheaper variant keeps the regex and skips names ending in a non-credential suffix such as Path, Name, Id, Url, Type.
  2. A per-parameter suppression, so a reviewed false positive can be silenced in place instead of turning the rule off document-wide. An x- extension on the parameter listing rule IDs to ignore, or a per-rule exclude list of JSON paths in lint.yaml, would both do.

I can put a PR together for (1) if you'd take it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions