Coverage Report

Created: 2025-03-04 07:22

/src/serenity/Userland/Libraries/LibWeb/Fetch/Fetching/Checks.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2022-2023, Linus Groh <linusg@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include <LibWeb/DOMURL/DOMURL.h>
8
#include <LibWeb/Fetch/Fetching/Checks.h>
9
#include <LibWeb/Fetch/Infrastructure/HTTP/Requests.h>
10
#include <LibWeb/Fetch/Infrastructure/HTTP/Responses.h>
11
12
namespace Web::Fetch::Fetching {
13
14
// https://fetch.spec.whatwg.org/#concept-cors-check
15
bool cors_check(Infrastructure::Request const& request, Infrastructure::Response const& response)
16
0
{
17
    // 1. Let origin be the result of getting `Access-Control-Allow-Origin` from response’s header list.
18
0
    auto origin = response.header_list()->get("Access-Control-Allow-Origin"sv.bytes());
19
20
    // 2. If origin is null, then return failure.
21
    // NOTE: Null is not `null`.
22
0
    if (!origin.has_value())
23
0
        return false;
24
25
    // 3. If request’s credentials mode is not "include" and origin is `*`, then return success.
26
0
    if (request.credentials_mode() != Infrastructure::Request::CredentialsMode::Include && origin->span() == "*"sv.bytes())
27
0
        return true;
28
29
    // 4. If the result of byte-serializing a request origin with request is not origin, then return failure.
30
0
    if (request.byte_serialize_origin() != *origin)
31
0
        return false;
32
33
    // 5. If request’s credentials mode is not "include", then return success.
34
0
    if (request.credentials_mode() != Infrastructure::Request::CredentialsMode::Include)
35
0
        return true;
36
37
    // 6. Let credentials be the result of getting `Access-Control-Allow-Credentials` from response’s header list.
38
0
    auto credentials = response.header_list()->get("Access-Control-Allow-Credentials"sv.bytes());
39
40
    // 7. If credentials is `true`, then return success.
41
0
    if (credentials.has_value() && credentials->span() == "true"sv.bytes())
42
0
        return true;
43
44
    // 8. Return failure.
45
0
    return false;
46
0
}
47
48
// https://fetch.spec.whatwg.org/#concept-tao-check
49
bool tao_check(Infrastructure::Request const& request, Infrastructure::Response const& response)
50
0
{
51
    // 1. If request’s timing allow failed flag is set, then return failure.
52
0
    if (request.timing_allow_failed())
53
0
        return false;
54
55
    // 2. Let values be the result of getting, decoding, and splitting `Timing-Allow-Origin` from response’s header list.
56
0
    auto values = response.header_list()->get_decode_and_split("Timing-Allow-Origin"sv.bytes());
57
58
    // 3. If values contains "*", then return success.
59
0
    if (values.has_value() && values->contains_slow("*"sv))
60
0
        return true;
61
62
    // 4. If values contains the result of serializing a request origin with request, then return success.
63
0
    if (values.has_value() && values->contains_slow(request.serialize_origin()))
64
0
        return true;
65
66
    // 5. If request’s mode is "navigate" and request’s current URL’s origin is not same origin with request’s origin, then return failure.
67
    // NOTE: This is necessary for navigations of a nested browsing context. There, request’s origin would be the
68
    //       container document’s origin and the TAO check would return failure. Since navigation timing never
69
    //       validates the results of the TAO check, the nested document would still have access to the full timing
70
    //       information, but the container document would not.
71
0
    if (request.mode() == Infrastructure::Request::Mode::Navigate
72
0
        && request.origin().has<URL::Origin>()
73
0
        && !request.current_url().origin().is_same_origin(request.origin().get<URL::Origin>())) {
74
0
        return false;
75
0
    }
76
77
    // 6. If request’s response tainting is "basic", then return success.
78
0
    if (request.response_tainting() == Infrastructure::Request::ResponseTainting::Basic)
79
0
        return true;
80
81
    // 7. Return failure.
82
0
    return false;
83
0
}
84
85
}