Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: HTML reporter should not require CSP style-src 'unsafe-inline' #1369

Merged
merged 2 commits into from
Feb 18, 2019
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions reporter/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -350,12 +350,16 @@ export function escapeText( s ) {
}

function toolbarModuleFilter() {
var allCheckbox, commit, reset,
var commit, reset,
moduleFilter = document.createElement( "form" ),
label = document.createElement( "label" ),
moduleSearch = document.createElement( "input" ),
dropDown = document.createElement( "div" ),
actions = document.createElement( "span" ),
applyButton = document.createElement( "button" ),
resetButton = document.createElement( "button" ),
allModulesLabel = document.createElement( "label" ),
allCheckbox = document.createElement( "input" ),
dropDownList = document.createElement( "ul" ),
dirty = false;

Expand All @@ -370,15 +374,27 @@ export function escapeText( s ) {
label.innerHTML = "Module: ";
label.appendChild( moduleSearch );

applyButton.textContent = "Apply";
applyButton.style.display = "none";
Copy link
Member

Choose a reason for hiding this comment

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

I haven't confirmed, so apologies if this isn't true... I would expect the CSP policy for inline styles to disallow all three methods of dynamic style creation: <style> elements, style="" attributes, and CSSOM/style properties (like this one).

To abide the CSP strict style policy, I think we need to declare the styles in the CSS file ahead of time, and toggle them with a class only. For example, the qunit-modulefilter-dropdown element could have a class like has-selection or has-no-selection. And based on that, we could hide the buttons as needed.

However, the apply button isn't the only violation, so to address your use case we'll need numerous other changes as well. Again, that's based on my (potentially) outdated understanding of CSP.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The specification is not quite clear regarding CSSOM and CSP but as far as I'm aware of none of the implementation considers manipulating styles through CSSOM as a CSP violation. So while document.create('<button style="display: none;">') and document.create('button').style = "display: none;" require style-src 'unsafe-inline', document.create('button').style.display = 'none' is not violation style-src: 'none'.


resetButton.textContent = "Reset";
resetButton.type = "reset";
resetButton.style.display = "none";

allCheckbox.type = "checkbox";
allCheckbox.checked = config.moduleId.length === 0;

allModulesLabel.classList.add( "clickable" );
Copy link
Member

Choose a reason for hiding this comment

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

I suspect classList we might still support browsers in QUnit that predate classList. Would need to use className instead, if so.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Didn't expected anyone to still support IE9 and IE10 as even Microsoft has dropped support more that two years ago. But you are right, QUnit webseite says:

QUnit currently supports the same browsers as jQuery 3.x.

And jQuery lists Internet Explorer: 9+.

Pushed the change.

if ( config.moduleId.length ) {
allModulesLabel.classList.add( "checked" );
}
allModulesLabel.appendChild( allCheckbox );
allModulesLabel.appendChild( document.createTextNode( "All modules" ) );

actions.id = "qunit-modulefilter-actions";
actions.innerHTML =
"<button style='display:none'>Apply</button>" +
"<button type='reset' style='display:none'>Reset</button>" +
"<label class='clickable" +
( config.moduleId.length ? "" : " checked" ) +
"'><input type='checkbox'" + ( config.moduleId.length ? "" : " checked='checked'" ) +
" />All modules</label>";
allCheckbox = actions.lastChild.firstChild;
actions.appendChild( applyButton );
actions.appendChild( resetButton );
actions.appendChild( allModulesLabel );
commit = actions.firstChild;
reset = commit.nextSibling;
addEvent( commit, "click", applyUrlParams );
Expand Down