Skip to content

fix(redact): a login in a logged URL is masked - #198

Merged
derek-miller merged 3 commits into
mainfrom
fix/redact-url-logins
Nov 10, 2026
Merged

derek-miller merged 3 commits into
mainfrom
fix/redact-url-logins

Conversation

@derek-miller

Copy link
Copy Markdown
Contributor

lib.redact masked JSON members and key=value pairs, but not the login in a URL, so rtsp://viewer:pass@192.0.2.20/live reached a log line whole. Home Connect puts camera stream addresses in its bridge traces and masks them with a helper of its own, which misses a ?token= in the same URL.

What I changed:

  • redact.text, and so redact.value on any string or table leaf, masks a URL's login before it masks the pairs. That trace line now reads rtsp://***REDACTED***@192.0.2.20/live?token=***REDACTED***.
  • The login runs to the last @ before the host ends at /, ? or #, as a browser reads it. A raw @ in a password is masked whole, and an @ in a path, query or fragment, as in https://example.com?email=user@example.com, stays readable.
  • lib.http logs a request's URL through redact.value, so its Trace line masks a login too.

Each driver repo picks this up on its next copier update, and Home Connect then drops its helper.

lib.redact masked JSON members and key=value pairs but not a URL's userinfo, so rtsp://user:pass@host reached a log whole. The text path now masks the login up to the last @ before the host, as a browser reads it, and leaves an @ in a path, query or fragment alone.
svc-finitelabs[bot]
svc-finitelabs Bot previously approved these changes Nov 10, 2026

@svc-finitelabs svc-finitelabs Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. The login pattern takes the last @ before /, ?, #, whitespace or ", so I probed what sits on either side of that: an IPv6 host (http://user:PASS@[2001:db8::1]:554/live), an uppercase scheme and a percent-encoded @ in the password all mask the login and keep the host. Beyond CI, I mutated the class one exclusion at a time (dropping ", %s, and ?#). Each mutation fails a different case in the new "stays readable" section, so every character the class excludes has a test that pins it.

end)
-- A URL's login: rtsp://user:pass@host. As a browser reads it, the login runs to the last "@" before the
-- host ends at "/", "?" or "#", so a raw "@" in a password is masked whole and one in a query is left alone.
text = text:gsub('(://)[^/?#%s"]+@', "%1" .. REDACTED .. "@")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the class stops at " but not at ' or ,, so a single-quoted or comma-separated URL that is followed by an email loses its host: url='http://host',user=a@b.com becomes url='http://***REDACTED***@b.com. That fails closed, so nothing leaks, but the line no longer says which host it was. Adding ' next to " ([^/?#%s"']+@) covers the quoted case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declined, and pinned with a test in b66dede. ' and , are sub-delims, legal raw in a URL login (RFC 3986 section 3.2.1), so a class that stops at either prints a password holding one: with [^/?#%s"'], rtsp://viewer:it's@192.0.2.20/live comes out whole. The current class can hide the host in your quoted case but never a secret, and failing closed is the side lib.redact takes. " is different: it can't stand raw in a URL, and in JSON text it ends the string. The new check "a raw ' or , in the password masked whole" fails if either character is added to the class.

Both may stand raw in a login, so a class that stops at either prints the password.

@svc-finitelabs svc-finitelabs Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new check pins the class against both characters with one string: adding either ' or , alone to the class in redact.lua:152 leaves rtsp://viewer:it's,ok_LEAK@192.0.2.20/live printed whole and fails only this check, and it passes at this head. Nothing else changed since my last review.

@svc-finitelabs svc-finitelabs Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The merge of main leaves this PR's two commits as they were, and it resolves to the same tree git merges on its own.

@derek-miller
derek-miller merged commit 05ebf84 into main Nov 10, 2026
20 checks passed
@derek-miller
derek-miller deleted the fix/redact-url-logins branch November 10, 2026 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant