Prevent secret values from leaking into the DOM when concealed#17024
Conversation
The conceal mechanism used a custom dot font to visually mask secret values, but the actual plaintext remained in the DOM. Selecting text (Ctrl+A or mouse selection) and copying would expose the real secret values. Replace the dot-font approach with a static placeholder that never renders real values in the DOM when concealed. Add unit tests for both KeyValue and DetailText components to verify secret values are not present in rendered HTML when concealment is active.
3538ff8 to
038473c
Compare
rak-phillip
left a comment
There was a problem hiding this comment.
@adifsgaid thanks for raising this PR and the associated issue. We might also be able to remove the dots font with this change now that we no longer render every character as a dot by swapping the font family. I think we can do the following now:
- remove
shell/assets/styles/fonts/_dots.scss - delete the dots import in
shell/assets/styles/app.scss
Move bullet placeholder characters from template content to CSS ::before pseudo-elements so they never render in the DOM tree, making them purely presentational and unselectable by default.
|
@rak-phillip applied both nits, bullets are now in CSS ::before and the templates are empty. Also went ahead and removed the dots font. LabeledInput in rancher-components was the only other consumer of the .conceal class for multiline-password masking (used in googleoauth.vue). Replaced it with -webkit-text-security: disc which does the same thing natively without the custom font, if anything else needs to be done feel free to add further comments ! |
Delete the dots font entirely since concealed values no longer rely on font swapping. Migrate LabeledInput multiline-password masking to -webkit-text-security: disc which is natively supported.
rak-phillip
left a comment
There was a problem hiding this comment.
@adifsgaid excellent, thanks for the follow up and for contributing to Rancher!
Summary
Fixes #17023
Occurred changes and/or fixed issues
dotsfontCSS approach were still present as plaintext in the DOM, allowing text selection + copy to expose actual secret valuesKeyValue.vue: replaced theTextAreaAutoGrowwith.concealclass with a static placeholder<div>that renders bullet characters and usesuser-select: nonewhenvalueConcealedis trueDetailText.vue: whenconcealed, renders a static bullet placeholder instead of the real value. JSON values skipCodeMirrorentirely when concealedTechnical notes summary
dotsfontvisual masking is replaced with a static placeholder that contains only bullet charactersCopyToClipboardbutton still copies the real value (this is intentional — it requires an explicit user click)input type="password"fallback path is unchanged as it already uses native browser maskingAreas or cases that should be tested
Areas which could experience regressions
KeyValuecomponent used elsewhere withvalueConcealedpropDetailTextcomponent used for displaying concealed valuesScreenshot/Video
Checklist
Admin,Standard UserandUser Base