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

tests(smoke): verify CSP violations caused by lighthouse #12391

Merged
merged 9 commits into from
Apr 28, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
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
11 changes: 11 additions & 0 deletions lighthouse-cli/test/fixtures/csp.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<html>
adamraine marked this conversation as resolved.
Show resolved Hide resolved
<head>
<script>
// Use a source map so we can test the injected iframe fetcher.
//# sourceMappingURL=http://localhost:10200/source-map/script.js.map
</script>
</head>
<body>
<h1>Test this page with a CSP</h1>
</body>
</html>
2 changes: 1 addition & 1 deletion lighthouse-cli/test/fixtures/static-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const mime = require('mime-types');
const parseQueryString = require('querystring').parse;
const parseURL = require('url').parse;
const URLSearchParams = require('url').URLSearchParams;
const HEADER_SAFELIST = new Set(['x-robots-tag', 'link']);
const HEADER_SAFELIST = new Set(['x-robots-tag', 'link', 'content-security-policy']);

const lhRootDirPath = path.join(__dirname, '../../../');

Expand Down
4 changes: 4 additions & 0 deletions lighthouse-cli/test/smokehouse/test-definitions/core-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ const smokeTests = [{
id: 'screenshot',
expectations: require('./screenshot/expectations.js'),
config: require('./screenshot/screenshot-config.js'),
}, {
id: 'csp',
expectations: require('./csp/csp-expectations.js'),
config: require('./csp/csp-config.js'),
}];

module.exports = smokeTests;
11 changes: 11 additions & 0 deletions lighthouse-cli/test/smokehouse/test-definitions/csp/csp-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @license Copyright 2021 The Lighthouse Authors. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/
'use strict';

/** @type {LH.Config.Json} */
module.exports = {
extends: 'lighthouse:default',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* @license Copyright 2021 The Lighthouse Authors. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/
'use strict';

/**
* @param {[string, string][]} headers
* @return {string}
*/
function headersParam(headers) {
const headerString = new URLSearchParams(headers).toString();
return new URLSearchParams([['extra_header', headerString]]).toString();
}

const blockAllExceptInlineScriptCsp = headersParam([[
'Content-Security-Policy',
'default-src \'none\'; script-src \'unsafe-inline\'',
adamraine marked this conversation as resolved.
Show resolved Hide resolved
]]);

/**
* @type {Array<Smokehouse.ExpectedRunnerResult>}
*/
module.exports = [
{
artifacts: {
RobotsTxt: {
status: 404,
content: null,
},
InspectorIssues: {contentSecurityPolicy: []},
SourceMaps: [{
sourceMapUrl: 'http://localhost:10200/source-map/script.js.map',
map: {},
errorMessage: undefined,
}],
},
lhr: {
requestedUrl: 'http://localhost:10200/csp.html',
finalUrl: 'http://localhost:10200/csp.html',
audits: {},
},
},
{
artifacts: {
RobotsTxt: {
status: null,
content: null,
},
InspectorIssues: {
contentSecurityPolicy: [
{
// TODO: Fix connect-src violation when fetching robots.txt.
// https://github.com/GoogleChrome/lighthouse/issues/10225
blockedURL: 'http://localhost:10200/robots.txt',
violatedDirective: 'connect-src',
isReportOnly: false,
contentSecurityPolicyViolationType: 'kURLViolation',
},
{
// TODO: Fix style-src-elem violation when checking tap targets.
// https://github.com/GoogleChrome/lighthouse/issues/11862
violatedDirective: 'style-src-elem',
isReportOnly: false,
contentSecurityPolicyViolationType: 'kInlineViolation',
},
],
},
SourceMaps: [{
// TODO: Fix frame-src violation when using iframe fetcher.
// Doesn't trigger a CSP violation because iframe is injected after InspectorIssues gatherer finishes.
Copy link
Member Author

Choose a reason for hiding this comment

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

Could we move InspectorIssues earlier in the config so CSP violations caused by Lighthouse aren't in the report.

Conversely, we could move InspectorIssues to the end so it catches issues caused by SourceMaps.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Would that even work since InspectorIssues stops listening in afterPass, and some (all?) of these issues come from snapshot?

... so it catches issues caused by SourceMaps.

nbd if this is just the iframe fetcher, which will be removed soon.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Would that even work since InspectorIssues stops listening in afterPass, and some (all?) of these issues come from snapshot?

In current LH flow, snapshot isn't a special phase it's just immediately called by the afterPass. You have an astute observation though that in FR this isn't actually a problem because snapshot is always called after afterTimespan ;)

// https://github.com/GoogleChrome/lighthouse/pull/12044#issuecomment-788274938
sourceMapUrl: 'http://localhost:10200/source-map/script.js.map',
errorMessage: 'Error: Timed out fetching resource.',
map: undefined,
}],
},
lhr: {
requestedUrl: 'http://localhost:10200/csp.html?' + blockAllExceptInlineScriptCsp,
finalUrl: 'http://localhost:10200/csp.html?' + blockAllExceptInlineScriptCsp,
audits: {},
},
},
];
5 changes: 4 additions & 1 deletion lighthouse-core/gather/gatherers/seo/tap-targets.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ class TapTargets extends FRGatherer {
* @return {Promise<LH.Artifacts.TapTarget[]>} All visible tap targets with their positions and sizes
*/
snapshot(passContext) {
return passContext.driver.executionContext.evaluate(gatherTapTargets, {
const a = passContext.driver.executionContext.evaluate(gatherTapTargets, {
adamraine marked this conversation as resolved.
Show resolved Hide resolved
args: [tapTargetsSelector],
useIsolation: true,
deps: [
Expand All @@ -312,6 +312,9 @@ class TapTargets extends FRGatherer {
pageFunctions.getNodeLabel,
],
});
return a.then(e => {
return e;
});
}
}

Expand Down