test(): preserve raw option values with secure text - #482
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes an encoding bug when enableSecureText is enabled by preserving raw option values for selection/API/form submission while escaping values only at HTML attribute interpolation time (preventing attribute-breakout injection).
Changes:
- Store option
valuein its original (raw) form during option preparation and when creating/updating “new” options. - Escape
data-valueonly when generating option HTML, keeping attribute-injection protection while avoiding double-encoding in state/dataset updates. - Add Cypress regression coverage for existing unsafe-character values and dynamically added (new) values; update dist/docs bundles accordingly.
Reviewed changes
Copilot reviewed 3 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/virtual-select.js | Keeps raw values in option data, escapes only when interpolating data-value into HTML. |
| dist/virtual-select.js | Built bundle update reflecting the raw-value + attribute-escape behavior. |
| dist/virtual-select.min.js | Minified bundle update reflecting the same behavior. |
| docs/assets/virtual-select.js | Docs bundle update reflecting the raw-value + attribute-escape behavior. |
| docs/assets/virtual-select.min.js | Minified docs bundle update reflecting the same behavior. |
| cypress/e2e/secure-option-values.cy.ts | Cypress regression tests for raw hidden-input values and XSS-safe rendering. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -0,0 +1,58 @@ | |||
| describe('Secure option values', () => { | |||
PR Test Results — ✅ all checks passed
Tested commit: |
Both sides had independently fixed sa-si-dev#455 (option values reaching the form HTML-encoded), so all four conflicts in src/virtual-select.js asked the same question: is the option value escaped? Every one is resolved to master's side, which is a superset of this branch's fix. - data-value uses Utils.escapeAttributeValue() rather than this.secureText(). secureText() deliberately does not escape quotes and is a no-op when enableSecureText is off, so this branch's version still let a value such as `x" data-pwned="1` break out of the attribute in both modes. - setOptions() and getOptionObj() keep master's rawValue/rawLabel/ rawDescription locals; the already-merged code below both hunks refers to them, so this branch's naming would not have compiled. - addNewOption() differed only by an explanatory comment. src/virtual-select.js is now identical to master's. This branch's regression test (cypress/e2e/secure-option-values.cy.ts) is untouched, and the issue's own repro now yields ["<"] in the hidden input instead of ["<"]. Build files are left out per the pull request rule in .github/README.md.
.github/README.md asks that build files not be committed in a PR - they are generated before a release only. fcaaa8a shipped the rebuilt bundle along with its source fix, and the earlier merge already resolved the minified artifacts back to master's copies, leaving dist/virtual-select.js and docs/assets/virtual-select.js as the last two carrying branch-local output. Both are restored to master's version, so this branch now changes no build files at all. The bundle is regenerated at release time from the source change that is still here.
|
Thanks for this, @oiahoon — your diagnosis on #455 was spot on, and the shape of the fix you proposed is the one that shipped. Heads up on what happened while this was open: the same root cause was fixed independently on Two notes on the merge, so nothing looks like it quietly went missing:
One housekeeping note, no action needed from you: Since the source fix arrived by another route, this is now effectively a test-only PR — you may want to retitle it to match. You are credited for #455 in the 1.4.0 release notes alongside #485. |
Issue number: resolves #455
What is the current behavior?
When
enableSecureTextis enabled, option values are converted to HTML entities while options are prepared. A laterdatasetupdate preserves that entity string, so selecting a value such as<writes["<"]to the hidden form input.What is the new behavior?
Does this introduce a breaking change?
Other information
npm run buildnpm run validatenpm pack --dry-run["<"], label renders as text, no injected image, no horizontal overflow, and no console errors