Skip to content

Show only the last four characters of a licence key in logs and errors - #78

Merged
jwrosewell merged 6 commits into
rcfrom
fix/mask-licence-key
Nov 10, 2026
Merged

jwrosewell merged 6 commits into
rcfrom
fix/mask-licence-key

Conversation

@jwrosewell

@jwrosewell jwrosewell commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Problem

For the rule on licence keys in logs and errors, logging.md, License keys (lines 20 to 39 on specifications rc). It says "A license key MUST NOT appear in full in a log entry or in an error message, at any log level. Where a message names a license key it MUST show only the key's last 4 characters, with each character before them replaced by one *" and "A key of 4 characters or fewer MUST be replaced entirely, by one * for each character. Every package masks the same way, so ABCDEFGH is written ****EFGH in every language." It also says a message that names a URL carrying a key, or the message of an error raised by an HTTP library, MUST hold only the masked key, and that there MUST be a test of a failed request.

The update URL carries licenseKeys=..., and datafile_update_service.py logged it in full for 429, 304, 403, other failures and a failed MD5 check (lines 124 to 153 on rc). A failed request raises an error whose message names the URL as well, and the Cloud Request Engine's no-data message names the response URL.

What changed

  • New fiftyone_pipeline_core/keymask.py with mask_licence_key and mask_licence_keys_in_text. The second finds licence parameters in text (licenseKeys, licenceKey, license_keys and the like, in any case) and masks each key of a list separated by | or %7C.

  • The update service logs a masked URL, and re-raises a failed request with a masked message.

  • The Cloud Request Engine masks the URL in its no-data message.

  • The Cloud Request Engine also masks the licence key by value in every exception validate_response raises, through the new CloudRequestEngine.masked. The cloud's accessible properties answer to a licence key that grants no cloud product names the key in its errors text ("License key(s): '...'"), and validate_response put that text into the exception in full (cloudrequestengine.py lines 339 to 343 and 367 to 376 on rc at f55f0d9). A non-JSON answer's content is masked the same way.

A review on 10 November found that cloud errors case. Nothing else in the src folders logs or raises a key or a URL that carries one (searched log, raise and Exception).

Overlap

The data update draft #69 rewrites the same log lines, and the two conflict in datafile_update_service.py. #69 holds this draft's commits as they were at b919b6b, merged in, and masks its own new messages, so this draft merges first and #69 after it. In #69 a failed request is logged rather than raised, so #69 also changes this draft's test_an_error_raised_by_the_request_does_not_hold_the_key to check the logged message.

How it was verified

New tests in pipeline/fiftyone_pipeline_engines/tests/test_licence_key_masking.py.

The last release into main merged on 2026-11-04.

#69 now holds this draft's later commits too, merged in at 2a90195.

Each hidden character is an asterisk, and a key of four or fewer characters is
hidden entirely. The update service masks the URL it logs and the message of a
failed request, and the Cloud Request Engine masks the URL in its no-data
message.
@jwrosewell
jwrosewell marked this pull request as ready for review November 10, 2026 23:53
@jwrosewell
jwrosewell merged commit 703a61b into rc Nov 10, 2026
2 checks passed
@jwrosewell
jwrosewell deleted the fix/mask-licence-key branch November 10, 2026 23:53
This was referenced Nov 12, 2026
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