Skip to content

Commit 36944df

Browse files
Matt Menkechromium-wpt-export-bot
authored andcommitted
[Protected Audiences] Make WPT tests reject unexpected CORS preflights.
Bug: None Change-Id: I0d529fc16856476b4a40c1745f521ab05cf81330 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6404777 Reviewed-by: Maks Orlovich <[email protected]> Commit-Queue: mmenke <[email protected]> Cr-Commit-Position: refs/heads/main@{#1439642}
1 parent 648c9e3 commit 36944df

File tree

6 files changed

+72
-38
lines changed

6 files changed

+72
-38
lines changed

fledge/tentative/resources/additional-bids.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class BadRequestError(Exception):
2323

2424
def main(request, response):
2525
try:
26-
if fledge_http_server_util.handle_cors_headers_and_preflight(request, response):
26+
if fledge_http_server_util.handle_cors_headers_fail_if_preflight(request, response):
2727
return
2828

2929
# Verify that Sec-Ad-Auction-Fetch is present

fledge/tentative/resources/bidding-logic.sub.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
# injected in them. generateBid() will by default return a bid of 9 for the
99
# first ad.
1010
def main(request, response):
11-
if fledge_http_server_util.handle_cors_headers_and_preflight(request, response):
11+
if fledge_http_server_util.handle_cors_headers_fail_if_preflight(request, response):
1212
return
1313

1414
error = request.GET.first(b"error", None)

fledge/tentative/resources/fledge_http_server_util.py

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,17 @@
22
from collections import namedtuple
33
from urllib.parse import unquote_plus, urlparse
44

5+
def fail(response, body):
6+
"""Sets up response to fail with the provided response body.
7+
8+
Args:
9+
response: the wptserve Response that was passed to main
10+
body: the HTTP response body to use
11+
"""
12+
response.status = (400, "Bad Request")
13+
response.headers.set(b"Content-Type", b"text/plain")
14+
response.content = body
15+
516
def headers_to_ascii(headers):
617
"""Converts a header map with binary values to one with ASCII values.
718
@@ -22,18 +33,15 @@ def headers_to_ascii(headers):
2233
header_map[pair[0].decode("ASCII")] = values
2334
return header_map
2435

25-
26-
def handle_cors_headers_and_preflight(request, response):
27-
"""Applies CORS logic common to many entrypoints.
36+
def attach_origin_and_credentials_headers(request, response):
37+
"""Attaches Access-Control-Allow-Origin and Access-Control-Allow-Credentials
38+
response headers to a response, if the request indicates they're needed.
39+
Only intended for internal use.
2840
2941
Args:
3042
request: the wptserve Request that was passed to main
3143
response: the wptserve Response that was passed to main
32-
33-
Returns True if the request is a CORS preflight, which is entirely handled by
34-
this function, so that the calling function should immediately return.
3544
"""
36-
# Append CORS headers if needed
3745
if b"origin" in request.headers:
3846
response.headers.set(b"Access-Control-Allow-Origin",
3947
request.headers.get(b"origin"))
@@ -42,20 +50,50 @@ def handle_cors_headers_and_preflight(request, response):
4250
response.headers.set(b"Access-Control-Allow-Credentials",
4351
request.headers.get(b"credentials"))
4452

53+
def handle_cors_headers_fail_if_preflight(request, response):
54+
"""Adds CORS headers if necessary. In the case of CORS preflights, generates
55+
a failure response. To be used when CORS preflights are not expected.
56+
57+
Args:
58+
request: the wptserve Request that was passed to main
59+
response: the wptserve Response that was passed to main
60+
61+
Returns True if the request is a CORS preflight, in which case the calling
62+
function should immediately return.
63+
"""
64+
# Handle CORS preflight requests.
65+
if request.method == u"OPTIONS":
66+
fail(response, "CORS preflight unexpectedly received.")
67+
return True
68+
69+
# Append CORS headers if needed
70+
attach_origin_and_credentials_headers(request, response)
71+
return False
72+
73+
def handle_cors_headers_and_preflight(request, response):
74+
"""Applies CORS logic, either adding CORS headers to response or generating
75+
an entire response to preflights.
76+
77+
Args:
78+
request: the wptserve Request that was passed to main
79+
response: the wptserve Response that was passed to main
80+
81+
Returns True if the request is a CORS preflight, in which case the calling
82+
function should immediately return.
83+
"""
84+
# Append CORS headers if needed
85+
attach_origin_and_credentials_headers(request, response)
86+
4587
# Handle CORS preflight requests.
4688
if not request.method == u"OPTIONS":
4789
return False
4890

4991
if not b"Access-Control-Request-Method" in request.headers:
50-
response.status = (400, b"Bad Request")
51-
response.headers.set(b"Content-Type", b"text/plain")
52-
response.content = "Failed to get access-control-request-method in preflight!"
92+
fail(response, "Failed to get access-control-request-method in preflight!")
5393
return True
5494

5595
if not b"Access-Control-Request-Headers" in request.headers:
56-
response.status = (400, b"Bad Request")
57-
response.headers.set(b"Content-Type", b"text/plain")
58-
response.content = "Failed to get access-control-request-headers in preflight!"
96+
fail(response, "Failed to get access-control-request-headers in preflight!")
5997
return True
6098

6199
response.headers.set(b"Access-Control-Allow-Methods",

fledge/tentative/resources/permissions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def get_permissions(request, response):
3535
- 天気の良い日 / élève: allow both join and leave
3636
- anything else (including no subdomain): returns a 404
3737
"""
38-
if fledge_http_server_util.handle_cors_headers_and_preflight(request, response):
38+
if fledge_http_server_util.handle_cors_headers_fail_if_preflight(request, response):
3939
return
4040

4141
first_domain_label = re.search(r"[^.]*", request.url_parts.netloc).group(0)

fledge/tentative/resources/trusted-bidding-signals.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ def main(request, response):
2020
for param in request.url_parts.query.split("&"):
2121
pair = param.split("=", 1)
2222
if len(pair) != 2:
23-
return fail(response, "Bad query parameter: " + param)
23+
fail(response, "Bad query parameter: " + param)
24+
return
2425
# Browsers should escape query params consistently.
2526
if "%20" in pair[1]:
26-
return fail(response, "Query parameter should escape using '+': " + param)
27+
fail(response, "Query parameter should escape using '+': " + param)
28+
return
2729

2830
# Hostname can't be empty. The empty string can be a key or interest group name, though.
2931
if pair[0] == "hostname" and hostname == None and len(pair[1]) > 0:
@@ -37,20 +39,22 @@ def main(request, response):
3739
continue
3840
if pair[0] == "slotSize" or pair[0] == "allSlotsRequestedSizes":
3941
continue
40-
return fail(response, "Unexpected query parameter: " + param)
42+
fail(response, "Unexpected query parameter: " + param)
43+
return
4144

4245
# If trusted signal keys are passed in, and one of them is "cors",
43-
# add appropriate Access-Control-* headers to normal requests, and handle
44-
# CORS preflights.
45-
if keys and "cors" in keys and fledge_http_server_util.handle_cors_headers_and_preflight(
46+
# add appropriate Access-Control-* headers to normal requests.
47+
if keys and "cors" in keys and fledge_http_server_util.handle_cors_headers_fail_if_preflight(
4648
request, response):
4749
return
4850

4951
# "interestGroupNames" and "hostname" are mandatory.
5052
if not hostname:
51-
return fail(response, "hostname missing")
53+
fail(response, "hostname missing")
54+
return
5255
if not interestGroupNames:
53-
return fail(response, "interestGroupNames missing")
56+
fail(response, "interestGroupNames missing")
57+
return
5458

5559
response.status = (200, b"OK")
5660

@@ -153,8 +157,3 @@ def main(request, response):
153157
if body != None:
154158
return body
155159
return json.dumps(responseBody)
156-
157-
def fail(response, body):
158-
response.status = (400, "Bad Request")
159-
response.headers.set(b"Content-Type", b"text/plain")
160-
return body

fledge/tentative/resources/trusted-scoring-signals.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ def main(request, response):
1313
try:
1414
params = fledge_http_server_util.decode_trusted_scoring_signals_params(request)
1515
except ValueError as ve:
16-
return fail(response, str(ve))
16+
fail(response, str(ve))
17+
return
1718

1819
response.status = (200, b"OK")
1920

@@ -36,7 +37,8 @@ def main(request, response):
3637
try:
3738
signalsParams = fledge_http_server_util.decode_render_url_signals_params(renderUrl)
3839
except ValueError as ve:
39-
return fail(response, str(ve))
40+
fail(response, str(ve))
41+
return
4042

4143
for signalsParam in signalsParams:
4244
if signalsParam == "close-connection":
@@ -92,8 +94,8 @@ def main(request, response):
9294
responseBody[urlList["type"]][renderUrl] = value
9395

9496
# If the signalsParam embedded inside a render URL calls for CORS, add
95-
# appropriate response headers, and fully handle preflights.
96-
if cors and fledge_http_server_util.handle_cors_headers_and_preflight(
97+
# appropriate response headers.
98+
if cors and fledge_http_server_util.handle_cors_headers_fail_if_preflight(
9799
request, response):
98100
return
99101

@@ -107,8 +109,3 @@ def main(request, response):
107109
if body != None:
108110
return body
109111
return json.dumps(responseBody)
110-
111-
def fail(response, body):
112-
response.status = (400, "Bad Request")
113-
response.headers.set(b"Content-Type", b"text/plain")
114-
return body

0 commit comments

Comments
 (0)