Skip to content

fix(security): mask the user name of a URL with no password - #3676

Merged
dan-petty merged 3 commits into
mainfrom
fix/2662-mask-url-user-name-without-password
Nov 5, 2026
Merged

dan-petty merged 3 commits into
mainfrom
fix/2662-mask-url-user-name-without-password

Conversation

@dan-petty

Copy link
Copy Markdown
Owner

redact_text and mask_uri_credentials left the user name of a URL as written when the URL had no password. A service can take a token as the user name, and httpx2 sends such a URL as Basic authentication. So a token showed in masked text, and the same URL with a password was masked.

The user name is now masked in every scheme: in redact_text and *** in mask_uri_credentials. A parser cannot tell a token from a name such as git, so both are masked, as pip does. The sanitizer docstring states the rule. Cost: the user name of a clone URL is masked too, and the host and the path still show.

Closes #2662

Change: openspec/changes/archive/2026-11-05-2662-mask-url-user-name-without-password/

redact_text and mask_uri_credentials masked the userinfo of a URL only when it
held a password. A token used as the user name, with an empty password,
showed in masked text. httpx2 sends such a URL as Basic authentication.

The user name is now masked, whatever the scheme: <masked-user> in
redact_text and *** in mask_uri_credentials. A parser cannot tell a token
from a name such as git, so the rule masks both, as pip does. The module
docstring of the sanitizer states the rule and the tests hold it.

Plans #2662.
The spec, the design and the module docstring said that both masking
functions return a URL with no user name as it was. mask_uri_credentials
returns <masked-url> for a text that has an @ and no userinfo (#1109).
The texts now name each function, and mask_uri_credentials has a test
for both forms.

Plans #2662.
@dan-petty dan-petty added type/bug Defect, regression, or incorrect runtime behavior scope/security Security linters (trivy, bandit, gitleaks, kubeconform) and Vault labels Nov 5, 2026
@dan-petty

Copy link
Copy Markdown
Owner Author

Test record for this pull request. The body keeps no test results.

Fail-to-pass (uv run devops ci fail-to-pass --base origin/main, exit 0): 19 tests fail on the base and pass with the fix. They are in tests/security/test_secret_redaction.py, tests/security/test_redaction_properties.py, tests/ai/client/test_url_credential_masking.py and tests/k8s/test_gitea_doctor.py. The log is .data/agent/fail-to-pass.log in the worktree.

Narrow runs after the rebase onto origin/main: 1602 tests pass in tests/security, tests/ai/client/test_url_credential_masking.py, tests/k8s/test_gitea_doctor.py and tests/invariants/test_architectural_invariants.py. devops openspec check passes.

Review finding fixed. One review finding was right. The spec, the design and the module docstring said that both functions return a URL with an @ and no userinfo as it was. mask_uri_credentials returns <masked-url> for such a text (fail closed, #1109) and this change does not touch that branch. The three texts now name each function, and tests/ai/client/test_url_credential_masking.py holds both forms for mask_uri_credentials.

Full uv run devops ci on the final code, local devcontainer host. All gates pass except test and coverage. The test run has 10 failures and 1 error. None comes from this change:

The 18820 other tests pass.

@dan-petty
dan-petty marked this pull request as ready for review November 5, 2026 18:21
@dan-petty
dan-petty merged commit bc1cd9c into main Nov 5, 2026
23 checks passed
@dan-petty
dan-petty deleted the fix/2662-mask-url-user-name-without-password branch November 5, 2026 18:39
dan-petty pushed a commit that referenced this pull request Nov 5, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.63.0](v0.62.7...v0.63.0)
(2026-11-05)


### Features

* **roadmap:** let a negative search verify check more than one name
([#3678](#3678))
([5a4364c](5a4364c))
* **telemetry:** count the tool calls of the stage planner by outcome
([#3679](#3679))
([45da6dd](45da6dd))


### Bug Fixes

* **ci:** count tests and specs as hardening guardrails
([#3684](#3684))
([1d75506](1d75506))
* **security:** mask the user name of a URL with no password
([#3676](#3676))
([bc1cd9c](bc1cd9c))
* **service:** count each GitHub request with its HTTP status
([#3686](#3686))
([b39dcba](b39dcba))
* **telemetry:** Service counters read true across pods and repos
([#3680](#3680))
([05544ab](05544ab))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: dan-petty-release[bot] <346998822+dan-petty-release[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope/security Security linters (trivy, bandit, gitleaks, kubeconform) and Vault type/bug Defect, regression, or incorrect runtime behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(security): redact_text leaves the user name of a URL with no password, so a token used as the user name shows in text

1 participant