Skip to content

fix: redact client credentials from OAuth error output#2

Merged
Gribbs merged 1 commit into
mainfrom
fix/oauth-error-redacts-credentials
Jun 1, 2026
Merged

fix: redact client credentials from OAuth error output#2
Gribbs merged 1 commit into
mainfrom
fix/oauth-error-redacts-credentials

Conversation

@Gribbs
Copy link
Copy Markdown
Owner

@Gribbs Gribbs commented Jun 1, 2026

Summary

procure login printed the OAuth client_id and client_secret in plaintext to stderr on a failed token request. Procurify echoes the request body back inside its 401 error response, and fetchToken embedded that raw body into the OAuthError message/.body, which handleError then prints.

Changes

  • Add sanitizeResponseText() in lib/oauth.js that redacts client_id, client_secret, and token/password/assertion fields before any response body is surfaced in an error. JSON bodies are parsed and masked structurally; non-JSON falls back to regex redaction.
  • Masking preserves the last 4 chars (e.g. ***ibAN) so output stays diagnosable and still lines up with Procurify's own "client_id ending in ibAN" hint.
  • Applied to both the non-2xx and unparseable-body error paths.
  • Add a regression test asserting the full client id and secret never appear in err.message or err.body.

Before vs after (same failing login):

```
before: "client_id":"nIeayneGllGyilEeFkKhBzvgFZIwibAN","client_secret":"<plaintext>"
after: "client_id":"***ibAN","client_secret":"***Yldv"
```

Note: the --debug log line was already masked; this closes the remaining leak in the error body.

Test plan

  • npx jest — 136 tests pass (incl. new redaction test)
  • npx eslint lib/oauth.js test/oauth.test.js — clean
  • Manual: procure login --profile sandbox no longer prints plaintext credentials

Procurify echoes the token request (including client_id and
client_secret) back in 401 error bodies. fetchToken embedded that raw
body into the OAuthError message and body, so a failed `procure login`
printed both credentials in plaintext to stderr.

Add sanitizeResponseText() to mask client_id, client_secret, and
token/password fields before any response body is surfaced in an error,
preserving the last 4 chars for diagnosability. Covered by a regression
test asserting the secret and full client id never appear in the error.
@Gribbs Gribbs merged commit 12bd022 into main Jun 1, 2026
1 check passed
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

🎉 This PR is included in version 0.1.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant