Commit 8c0e546e authored by Hiroshige Hayashizaki's avatar Hiroshige Hayashizaki Committed by Commit Bot

[WPT/upgrade-insecure-requests] Migrate to common/security-features generator

This CL migrates most of the wpt/upgrade-insecure-requests tests
from upgrade-insecure-requests/support/generate.py
into the /common/security-features generator framework.

Actual file regeneration is done in
https://chromium-review.googlesource.com/c/chromium/src/+/1788553
and the coverage will become larger than the current generator.
Particularly, this (and the regeneration CL) adds the following cases:

- `upgrade-insecure-requests` is delivered by HTTP response headers.
  Previously, only the delivery via <meta> was tested.
- `upgrade-insecure-requests` isn't delivered and thus requests
  are blocked (as mixed-content or simply failing to connect the server).
  Previously, only successfully upgraded cases were tested.

Bug: 1001422
Change-Id: I351f4dcc75c1008cf743b63dfb585ca82e199f39
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1788551
Commit-Queue: Hiroshige Hayashizaki <hiroshige@chromium.org>
Reviewed-by: default avatarMike West <mkwst@chromium.org>
Reviewed-by: default avatarHiroki Nakagawa <nhiroki@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701027}
parent fc82a523
...@@ -6,7 +6,9 @@ import os ...@@ -6,7 +6,9 @@ import os
def main(): def main():
'''Formats spec.src.json.''' '''Formats spec.src.json.'''
script_directory = os.path.dirname(os.path.abspath(__file__)) script_directory = os.path.dirname(os.path.abspath(__file__))
for dir in ['mixed-content', 'referrer-policy']: for dir in [
'mixed-content', 'referrer-policy', 'upgrade-insecure-requests'
]:
filename = os.path.join(script_directory, '..', '..', '..', dir, filename = os.path.join(script_directory, '..', '..', '..', dir,
'spec.src.json') 'spec.src.json')
spec = json.load( spec = json.load(
......
...@@ -110,6 +110,18 @@ def handle_deliveries(policy_deliveries): ...@@ -110,6 +110,18 @@ def handle_deliveries(policy_deliveries):
else: else:
raise Exception( raise Exception(
'Invalid delivery_type: %s' % delivery.delivery_type) 'Invalid delivery_type: %s' % delivery.delivery_type)
elif delivery.key == 'upgradeInsecureRequests':
# https://w3c.github.io/webappsec-upgrade-insecure-requests/#delivery
assert (delivery.value == 'upgrade')
if delivery.delivery_type == 'meta':
meta += '<meta http-equiv="Content-Security-Policy" ' + \
'content="upgrade-insecure-requests">'
elif delivery.delivery_type == 'http-rp':
headers[
'Content-Security-Policy'] = 'upgrade-insecure-requests'
else:
raise Exception(
'Invalid delivery_type: %s' % delivery.delivery_type)
else: else:
raise Exception('Invalid delivery_key: %s' % delivery.key) raise Exception('Invalid delivery_key: %s' % delivery.key)
return {"meta": meta, "headers": headers} return {"meta": meta, "headers": headers}
......
// TODO(hiroshige): Document the type of `scenario`.
function TestCase(scenario, description) {
const urls = getRequestURLs(scenario.subresource,
scenario.origin,
scenario.redirection);
const checkResult = _ => {
// Send request to check if the key has been torn down.
return xhrRequest(urls.assertUrl)
.then(assertResult => {
// Now check if the value has been torn down. If it's still there,
// we have blocked the request to mixed-content.
assert_equals(assertResult.status, scenario.expectation,
"The resource request should be '" + scenario.expectation + "'.");
});
};
function runTest() {
/** @type {Subresource} */
const subresource = {
subresourceType: scenario.subresource,
url: urls.testUrl,
policyDeliveries: scenario.subresource_policy_deliveries,
};
promise_test(() => {
return xhrRequest(urls.announceUrl)
// Send out the real resource request.
// This should tear down the key if it's not blocked.
.then(_ => invokeRequest(subresource, scenario.source_context_list))
// We check the key state, regardless of whether the main request
// succeeded or failed.
.then(checkResult, checkResult);
}, description);
} // runTest
return {start: runTest};
}
#!/usr/bin/env python
import os
import sys
sys.path.insert(
0,
os.path.join(
os.path.dirname(os.path.abspath(__file__)), '..', '..', '..', 'common',
'security-features', 'tools'))
import generate
class UpgradeInsecureRequestsConfig(object):
def __init__(self):
self.selection_pattern = \
'%(source_context_list)s.%(delivery_type)s/' + \
'%(delivery_value)s/' + \
'%(subresource)s/' + \
'%(origin)s.%(redirection)s.%(source_scheme)s'
self.test_file_path_pattern = 'gen/' + self.selection_pattern + '.html'
self.test_description_template = 'Upgrade-Insecure-Requests: Expects %(expectation)s for %(subresource)s to %(origin)s origin and %(redirection)s redirection from %(source_scheme)s context.'
self.test_page_title_template = 'Upgrade-Insecure-Requests: %s'
self.helper_js = '/upgrade-insecure-requests/generic/test-case.sub.js'
# For debug target only.
self.sanity_checker_js = '/upgrade-insecure-requests/generic/sanity-checker.js'
self.spec_json_js = '/upgrade-insecure-requests/spec_json.js'
self.test_case_name = 'TestCase'
script_directory = os.path.dirname(os.path.abspath(__file__))
self.spec_directory = os.path.abspath(
os.path.join(script_directory, '..', '..'))
if __name__ == '__main__':
generate.main(UpgradeInsecureRequestsConfig())
{
"specification": [
{
"name": "No upgrade-insecure-request",
"title": "No upgrade-insecure-request",
"description": "No upgrade-insecure-request",
"specification_url": "https://w3c.github.io/webappsec-upgrade-insecure-requests/",
"test_expansion": [
{
"name": "Without upgrade-insecure-request, all requests are blocked ...",
"expansion": "default",
"source_scheme": "https",
"source_context_list": "*",
"delivery_type": "meta",
"delivery_value": null,
"redirection": "*",
"subresource": "*",
"origin": "*",
"expectation": "blocked"
},
{
"name": "... except for the secure requests listed here",
"expansion": "override",
"source_scheme": "https",
"source_context_list": "*",
"delivery_type": "meta",
"delivery_value": null,
"redirection": "no-redirect",
"subresource": "*",
"origin": [
"same-https",
"cross-https",
"same-wss",
"cross-wss"
],
"expectation": "allowed"
}
]
},
{
"name": "With upgrade-insecure-request",
"title": "With upgrade-insecure-request",
"description": "With upgrade-insecure-request",
"specification_url": "https://w3c.github.io/webappsec-upgrade-insecure-requests/",
"test_expansion": [
{
"name": "With upgrade-insecure-request, all insecure requests are upgraded and allowed.",
"expansion": "default",
"source_scheme": "https",
"source_context_list": "*",
"delivery_type": "*",
"delivery_value": "upgrade",
"redirection": "*",
"subresource": "*",
"origin": "*",
"expectation": "allowed"
}
]
}
],
"delivery_key": "upgradeInsecureRequests",
"excluded_tests": [
{
"name": "Omit secure requests",
"expansion": "*",
"source_scheme": "*",
"source_context_list": "*",
"delivery_type": "*",
"delivery_value": "*",
"redirection": "no-redirect",
"subresource": "*",
"origin": [
"same-https",
"cross-https",
"same-wss",
"cross-wss"
],
"expectation": "allowed"
},
{
"name": "For inheriting tests skip http-rp because we already have <meta> tests",
"expansion": "*",
"source_scheme": "*",
"source_context_list": [
"srcdoc-inherit",
"iframe-blank-inherit",
"worker-classic-data"
],
"delivery_type": "http-rp",
"delivery_value": "*",
"redirection": "*",
"subresource": "*",
"origin": "*",
"expectation": "*"
},
{
"name": "Workers are same-origin only",
"expansion": "*",
"source_scheme": "*",
"source_context_list": "*",
"delivery_type": "*",
"delivery_value": "*",
"redirection": "*",
"subresource": [
"worker-classic",
"worker-module",
"sharedworker-classic"
],
"origin": [
"cross-https",
"cross-http-downgrade",
"cross-wss",
"cross-ws-downgrade"
],
"expectation": "*"
},
{
"name": "Websockets are ws/wss-only",
"expansion": "*",
"source_scheme": "*",
"source_context_list": "*",
"delivery_type": "*",
"delivery_value": "*",
"redirection": "*",
"subresource": "websocket",
"origin": [
"same-https",
"same-http-downgrade",
"cross-https",
"cross-http-downgrade"
],
"expectation": "*"
},
{
"name": "Websockets is no-redirect only",
"expansion": "*",
"source_scheme": "*",
"source_context_list": "*",
"delivery_type": "*",
"delivery_value": "*",
"redirection": [
"downgrade"
],
"subresource": "websocket",
"origin": "*",
"expectation": "*"
},
{
"name": "ws/wss are websocket-only",
"expansion": "*",
"source_scheme": "*",
"source_context_list": "*",
"delivery_type": "*",
"delivery_value": "*",
"redirection": "*",
"subresource": [
"iframe-tag",
"img-tag",
"xhr",
"fetch",
"worker-classic",
"worker-module",
"worker-import-data",
"sharedworker-classic",
"worklet-animation",
"worklet-audio",
"worklet-layout",
"worklet-paint",
"worklet-animation-import-data",
"worklet-audio-import-data",
"worklet-layout-import-data",
"worklet-paint-import-data"
],
"origin": [
"same-wss",
"same-ws-downgrade",
"cross-wss",
"cross-ws-downgrade"
],
"expectation": "*"
}
],
"source_context_schema": {
"supported_delivery_type": {
"top": [
"http-rp",
"meta"
],
"iframe": [
"http-rp",
"meta"
],
"iframe-blank": [
"meta"
],
"srcdoc": [
"meta"
],
"worker-classic": [
"http-rp"
],
"worker-module": [
"http-rp"
],
"worker-classic-data": [],
"worker-module-data": []
},
"supported_subresource": {
"top": "*",
"iframe": "*",
"iframe-blank": "*",
"srcdoc": "*",
"worker-classic": [
"xhr",
"fetch",
"websocket"
],
"worker-module": [
"xhr",
"fetch",
"websocket"
],
"worker-classic-data": [
"xhr",
"fetch",
"websocket"
],
"worker-module-data": [
"xhr",
"fetch",
"websocket"
]
}
},
"subresource_schema": {
"supported_delivery_type": {
"xhr": [],
"worker-classic": [],
"worker-module": [],
"worker-import-data": [],
"sharedworker-classic": [],
"worklet-animation": [],
"worklet-audio": [],
"worklet-layout": [],
"worklet-paint": [],
"worklet-animation-import-data": [],
"worklet-audio-import-data": [],
"worklet-layout-import-data": [],
"worklet-paint-import-data": [],
"fetch": [],
"websocket": [],
"img-tag": [],
"iframe-tag": []
}
},
"source_context_list_schema": {
"top": {
"description": "CSP set by the top-level Document",
"sourceContextList": [
{
"sourceContextType": "top",
"policyDeliveries": [
"policy"
]
}
],
"subresourcePolicyDeliveries": []
},
"srcdoc-inherit": {
"description": "srcdoc iframe should inherit parent Document's policy",
"sourceContextList": [
{
"sourceContextType": "top",
"policyDeliveries": [
"policy"
]
},
{
"sourceContextType": "srcdoc"
}
],
"subresourcePolicyDeliveries": []
},
"iframe-blank-inherit": {
"description": "blank iframe should inherit parent Document's policy",
"sourceContextList": [
{
"sourceContextType": "top",
"policyDeliveries": [
"policy"
]
},
{
"sourceContextType": "iframe-blank"
}
],
"subresourcePolicyDeliveries": []
},
"worker-classic-data": {
"description": "CSP set by the top-level Document is inherited to dedicated workers",
"sourceContextList": [
{
"sourceContextType": "top",
"policyDeliveries": [
"policy"
]
},
{
"sourceContextType": "worker-classic-data",
"policyDeliveries": []
}
],
"subresourcePolicyDeliveries": []
}
},
"test_expansion_schema": {
"expansion": [
"default",
"override"
],
"source_scheme": [
"https"
],
"delivery_type": [
"http-rp",
"meta"
],
"delivery_value": [
null,
"upgrade"
],
"source_context_list": [
"top",
"srcdoc-inherit",
"iframe-blank-inherit",
"worker-classic-data"
],
"redirection": [
"no-redirect",
"downgrade"
],
"origin": [
"same-https",
"same-http-downgrade",
"cross-https",
"cross-http-downgrade",
"same-wss",
"same-ws-downgrade",
"cross-wss",
"cross-ws-downgrade"
],
"subresource": [
"iframe-tag",
"img-tag",
"xhr",
"fetch",
"websocket",
"worker-classic",
"worker-module",
"worker-import-data",
"sharedworker-classic",
"worklet-animation",
"worklet-audio",
"worklet-layout",
"worklet-paint",
"worklet-animation-import-data",
"worklet-audio-import-data",
"worklet-layout-import-data",
"worklet-paint-import-data"
],
"expectation": [
"allowed",
"blocked"
]
}
}
var SPEC_JSON = {"subresource_schema": {"supported_delivery_type": {"worklet-layout": [], "worklet-paint": [], "worker-module": [], "sharedworker-classic": [], "worklet-paint-import-data": [], "worklet-animation-import-data": [], "fetch": [], "xhr": [], "worker-classic": [], "worklet-layout-import-data": [], "worklet-audio-import-data": [], "worklet-animation": [], "worker-import-data": [], "websocket": [], "worklet-audio": [], "iframe-tag": [], "img-tag": []}}, "excluded_tests": [{"delivery_value": "*", "origin": ["same-https", "cross-https", "same-wss", "cross-wss"], "delivery_type": "*", "name": "Omit secure requests", "expectation": "allowed", "expansion": "*", "redirection": "no-redirect", "source_context_list": "*", "source_scheme": "*", "subresource": "*"}, {"delivery_value": "*", "origin": "*", "delivery_type": "http-rp", "name": "For inheriting tests skip http-rp because we already have <meta> tests", "expectation": "*", "expansion": "*", "redirection": "*", "source_context_list": ["srcdoc-inherit", "iframe-blank-inherit", "worker-classic-data"], "source_scheme": "*", "subresource": "*"}, {"delivery_value": "*", "origin": ["cross-https", "cross-http-downgrade", "cross-wss", "cross-ws-downgrade"], "delivery_type": "*", "name": "Workers are same-origin only", "expectation": "*", "expansion": "*", "redirection": "*", "source_context_list": "*", "source_scheme": "*", "subresource": ["worker-classic", "worker-module", "sharedworker-classic"]}, {"delivery_value": "*", "origin": ["same-https", "same-http-downgrade", "cross-https", "cross-http-downgrade"], "delivery_type": "*", "name": "Websockets are ws/wss-only", "expectation": "*", "expansion": "*", "redirection": "*", "source_context_list": "*", "source_scheme": "*", "subresource": "websocket"}, {"delivery_value": "*", "origin": "*", "delivery_type": "*", "name": "Websockets is no-redirect only", "expectation": "*", "expansion": "*", "redirection": ["downgrade"], "source_context_list": "*", "source_scheme": "*", "subresource": "websocket"}, {"delivery_value": "*", "origin": ["same-wss", "same-ws-downgrade", "cross-wss", "cross-ws-downgrade"], "delivery_type": "*", "name": "ws/wss are websocket-only", "expectation": "*", "expansion": "*", "redirection": "*", "source_context_list": "*", "source_scheme": "*", "subresource": ["iframe-tag", "img-tag", "xhr", "fetch", "worker-classic", "worker-module", "worker-import-data", "sharedworker-classic", "worklet-animation", "worklet-audio", "worklet-layout", "worklet-paint", "worklet-animation-import-data", "worklet-audio-import-data", "worklet-layout-import-data", "worklet-paint-import-data"]}], "specification": [{"test_expansion": [{"delivery_value": null, "origin": "*", "delivery_type": "meta", "name": "Without upgrade-insecure-request, all requests are blocked ...", "expectation": "blocked", "expansion": "default", "redirection": "*", "source_context_list": "*", "source_scheme": "https", "subresource": "*"}, {"delivery_value": null, "origin": ["same-https", "cross-https", "same-wss", "cross-wss"], "delivery_type": "meta", "name": "... except for the secure requests listed here", "expectation": "allowed", "expansion": "override", "redirection": "no-redirect", "source_context_list": "*", "source_scheme": "https", "subresource": "*"}], "description": "No upgrade-insecure-request", "specification_url": "https://w3c.github.io/webappsec-upgrade-insecure-requests/", "name": "No upgrade-insecure-request", "title": "No upgrade-insecure-request"}, {"test_expansion": [{"delivery_value": "upgrade", "origin": "*", "delivery_type": "*", "name": "With upgrade-insecure-request, all insecure requests are upgraded and allowed.", "expectation": "allowed", "expansion": "default", "redirection": "*", "source_context_list": "*", "source_scheme": "https", "subresource": "*"}], "description": "With upgrade-insecure-request", "specification_url": "https://w3c.github.io/webappsec-upgrade-insecure-requests/", "name": "With upgrade-insecure-request", "title": "With upgrade-insecure-request"}], "test_expansion_schema": {"delivery_value": [null, "upgrade"], "origin": ["same-https", "same-http-downgrade", "cross-https", "cross-http-downgrade", "same-wss", "same-ws-downgrade", "cross-wss", "cross-ws-downgrade"], "delivery_type": ["http-rp", "meta"], "subresource": ["iframe-tag", "img-tag", "xhr", "fetch", "websocket", "worker-classic", "worker-module", "worker-import-data", "sharedworker-classic", "worklet-animation", "worklet-audio", "worklet-layout", "worklet-paint", "worklet-animation-import-data", "worklet-audio-import-data", "worklet-layout-import-data", "worklet-paint-import-data"], "expectation": ["allowed", "blocked"], "expansion": ["default", "override"], "redirection": ["no-redirect", "downgrade"], "source_context_list": ["top", "srcdoc-inherit", "iframe-blank-inherit", "worker-classic-data"], "source_scheme": ["https"]}, "source_context_list_schema": {"worker-classic-data": {"subresourcePolicyDeliveries": [], "description": "CSP set by the top-level Document is inherited to dedicated workers", "sourceContextList": [{"sourceContextType": "top", "policyDeliveries": ["policy"]}, {"sourceContextType": "worker-classic-data", "policyDeliveries": []}]}, "top": {"subresourcePolicyDeliveries": [], "description": "CSP set by the top-level Document", "sourceContextList": [{"sourceContextType": "top", "policyDeliveries": ["policy"]}]}, "srcdoc-inherit": {"subresourcePolicyDeliveries": [], "description": "srcdoc iframe should inherit parent Document's policy", "sourceContextList": [{"sourceContextType": "top", "policyDeliveries": ["policy"]}, {"sourceContextType": "srcdoc"}]}, "iframe-blank-inherit": {"subresourcePolicyDeliveries": [], "description": "blank iframe should inherit parent Document's policy", "sourceContextList": [{"sourceContextType": "top", "policyDeliveries": ["policy"]}, {"sourceContextType": "iframe-blank"}]}}, "delivery_key": "upgradeInsecureRequests", "source_context_schema": {"supported_delivery_type": {"iframe": ["http-rp", "meta"], "worker-module-data": [], "worker-classic-data": [], "top": ["http-rp", "meta"], "worker-classic": ["http-rp"], "iframe-blank": ["meta"], "worker-module": ["http-rp"], "srcdoc": ["meta"]}, "supported_subresource": {"iframe": "*", "worker-module-data": ["xhr", "fetch", "websocket"], "worker-classic-data": ["xhr", "fetch", "websocket"], "top": "*", "worker-classic": ["xhr", "fetch", "websocket"], "iframe-blank": "*", "worker-module": ["xhr", "fetch", "websocket"], "srcdoc": "*"}}};
# Usage: execute
# $ python support/generate.py
# at wpt/upgrade-insecure-requests/.
#
# Note: Some tests (link-upgrade.sub.https.html and
# websocket-upgrade.https.html) are not covered by this generator script.
template = '''<!DOCTYPE html>
<html>
<head>
<!-- Generated by wpt/upgrade-insecure-requests/support/generate.py -->%(additionalMeta)s
<title>Upgrade Insecure Requests: %(name)s.</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="./support/testharness-helper.sub.js"></script>
<script src="/common/security-features/resources/common.sub.js"></script>
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
</head>
<body>
<script>
const tests = %(generatorName)s(ResourceType.%(resourceType)s, %(sameOriginOnly)s);
tests.forEach(test => testMap['%(name)s'](test));
</script>
</body>
</html>
'''
def getLong(file):
testsThatNeedMoreTime = [ "worker-subresource-fetch-redirect-upgrade.https.html" ]
if any(file in item for item in testsThatNeedMoreTime ):
return '\n<meta name="timeout" content="long">'
return ""
# resourceType is |ResourceType| in testharness-helper.sub.js.
for name, resourceType in [
('image', 'IMAGE'), ('iframe', 'FRAME'),
('animation-worklet', 'WORKLET'), ('audio-worklet', 'WORKLET'),
('layout-worklet', 'WORKLET'), ('paint-worklet', 'WORKLET'),
('worker', 'WORKER'),
('module-worker', 'WORKER'),
('worker-subresource-xhr', 'FETCH'),
('worker-subresource-fetch', 'FETCH'),
('shared-worker', 'SHARED_WORKER')]:
# TODO(https://crbug.com/989399): Add tests for subresource requests on shared
# workers, and main/subresource requests on service workers.
sameOriginOnly = 'false'
if resourceType == 'WORKER' or resourceType == 'SHARED_WORKER':
sameOriginOnly = 'true'
types = [('', 'generateTests'), ('-redirect', 'generateRedirectTests')]
if name == 'module-worker' or resourceType == 'WORKLET':
types.append(('-import', 'generateModuleImportTests'))
for typeName, generatorName in types:
filename = '%s%s-upgrade.https.html' % (name, typeName)
with open(filename, 'w') as html_file:
html_file.write(template % {
'name': name,
'additionalMeta': getLong(filename),
'resourceType': resourceType,
'generatorName': generatorName,
'sameOriginOnly': sameOriginOnly})
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment