Changeset 292266 in webkit


Ignore:
Timestamp:
Apr 2, 2022 9:22:20 AM (4 months ago)
Author:
Patrick Griffis
Message:

CSP: Improve compatibility of source matching
https://bugs.webkit.org/show_bug.cgi?id=235873

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

Update expectation as passing.

  • web-platform-tests/content-security-policy/connect-src/connect-src-websocket-self.sub-expected.txt:

Source/WebCore:

  • Improved handling of protocol changes:
    • For host and self sources direct upgrades are allowed (ws->wss) (http->https already worked).
    • For self sources side grades are now allowed (http->ws).
    • For self sources upgrades are always allowed (*->https, *->wss).

This is documented here: https://www.w3.org/TR/CSP3/#match-url-to-source-expression

I also included some minor cleanups and adding of comments.

  • page/csp/ContentSecurityPolicy.cpp:

(WebCore::ContentSecurityPolicy::updateSourceSelf):
(WebCore::ContentSecurityPolicy::protocolMatchesSelf const): Deleted.

  • page/csp/ContentSecurityPolicy.h:

(WebCore::ContentSecurityPolicy::selfProtocol const):

  • page/csp/ContentSecurityPolicySource.cpp:

(WebCore::ContentSecurityPolicySource::ContentSecurityPolicySource):
(WebCore::ContentSecurityPolicySource::matches const):
(WebCore::ContentSecurityPolicySource::schemeMatches const):
(WebCore::ContentSecurityPolicySource::portMatches const):

  • page/csp/ContentSecurityPolicySource.h:
  • page/csp/ContentSecurityPolicySourceList.cpp:

(WebCore::ContentSecurityPolicySourceList::isProtocolAllowedByStar const):
(WebCore::ContentSecurityPolicySourceList::parse):

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r292222 r292266  
     12022-04-02  Patrick Griffis  <pgriffis@igalia.com>
     2
     3        CSP: Improve compatibility of source matching
     4        https://bugs.webkit.org/show_bug.cgi?id=235873
     5
     6        Reviewed by Darin Adler.
     7
     8        Update expectation as passing.
     9
     10        * web-platform-tests/content-security-policy/connect-src/connect-src-websocket-self.sub-expected.txt:
     11
    1122022-04-01  Tim Nguyen  <ntim@apple.com>
    213
  • trunk/LayoutTests/imported/w3c/web-platform-tests/content-security-policy/connect-src/connect-src-websocket-self.sub-expected.txt

    r246330 r292266  
    11
    2 FAIL Expecting logs: ["allowed", "allowed"] assert_unreached: unexpected log: blocked Reached unreachable code
     2PASS Expecting logs: ["allowed", "allowed"]
    33
  • trunk/Source/WebCore/ChangeLog

    r292264 r292266  
     12022-04-02  Patrick Griffis  <pgriffis@igalia.com>
     2
     3        CSP: Improve compatibility of source matching
     4        https://bugs.webkit.org/show_bug.cgi?id=235873
     5
     6        Reviewed by Darin Adler.
     7
     8        - Improved handling of protocol changes:
     9          - For host and self sources direct upgrades are allowed (ws->wss) (http->https already worked).
     10          - For self sources side grades are now allowed (http->ws).
     11          - For self sources upgrades are always allowed (*->https, *->wss).         
     12        This is documented here: https://www.w3.org/TR/CSP3/#match-url-to-source-expression
     13
     14        I also included some minor cleanups and adding of comments.
     15
     16        * page/csp/ContentSecurityPolicy.cpp:
     17        (WebCore::ContentSecurityPolicy::updateSourceSelf):
     18        (WebCore::ContentSecurityPolicy::protocolMatchesSelf const): Deleted.
     19        * page/csp/ContentSecurityPolicy.h:
     20        (WebCore::ContentSecurityPolicy::selfProtocol const):
     21        * page/csp/ContentSecurityPolicySource.cpp:
     22        (WebCore::ContentSecurityPolicySource::ContentSecurityPolicySource):
     23        (WebCore::ContentSecurityPolicySource::matches const):
     24        (WebCore::ContentSecurityPolicySource::schemeMatches const):
     25        (WebCore::ContentSecurityPolicySource::portMatches const):
     26        * page/csp/ContentSecurityPolicySource.h:
     27        * page/csp/ContentSecurityPolicySourceList.cpp:
     28        (WebCore::ContentSecurityPolicySourceList::isProtocolAllowedByStar const):
     29        (WebCore::ContentSecurityPolicySourceList::parse):
     30
    1312022-04-02  Andres Gonzalez  <andresg_22@apple.com>
    232
  • trunk/Source/WebCore/page/csp/ContentSecurityPolicy.cpp

    r292134 r292266  
    240240void ContentSecurityPolicy::updateSourceSelf(const SecurityOrigin& securityOrigin)
    241241{
    242     m_selfSourceProtocol = securityOrigin.protocol();
    243     m_selfSource = makeUnique<ContentSecurityPolicySource>(*this, m_selfSourceProtocol, securityOrigin.host(), securityOrigin.port(), emptyString(), false, false);
     242    m_selfSourceProtocol = securityOrigin.protocol().convertToASCIILowercase();
     243    m_selfSource = makeUnique<ContentSecurityPolicySource>(*this, m_selfSourceProtocol, securityOrigin.host(), securityOrigin.port(), emptyString(), false, false, IsSelfSource::Yes);
    244244}
    245245
     
    294294        return downcast<Document>(*m_scriptExecutionContext).settings().allowContentSecurityPolicySourceStarToMatchAnyProtocol();
    295295    return false;
    296 }
    297 
    298 bool ContentSecurityPolicy::protocolMatchesSelf(const URL& url) const
    299 {
    300     if (equalLettersIgnoringASCIICase(m_selfSourceProtocol, "http"))
    301         return url.protocolIsInHTTPFamily();
    302     return equalIgnoringASCIICase(url.protocol(), m_selfSourceProtocol);
    303296}
    304297
  • trunk/Source/WebCore/page/csp/ContentSecurityPolicy.h

    r292229 r292266  
    177177
    178178    // Used by ContentSecurityPolicySource
    179     bool protocolMatchesSelf(const URL&) const;
     179    const String& selfProtocol() const { return m_selfSourceProtocol; };
    180180
    181181    void setUpgradeInsecureRequests(bool);
  • trunk/Source/WebCore/page/csp/ContentSecurityPolicySource.cpp

    r291837 r292266  
    3535namespace WebCore {
    3636
    37 ContentSecurityPolicySource::ContentSecurityPolicySource(const ContentSecurityPolicy& policy, const String& scheme, const String& host, std::optional<uint16_t> port, const String& path, bool hostHasWildcard, bool portHasWildcard)
     37ContentSecurityPolicySource::ContentSecurityPolicySource(const ContentSecurityPolicy& policy, const String& scheme, const String& host, std::optional<uint16_t> port, const String& path, bool hostHasWildcard, bool portHasWildcard, IsSelfSource isSelfSource)
    3838    : m_policy(policy)
    3939    , m_scheme(scheme)
     
    4343    , m_hostHasWildcard(hostHasWildcard)
    4444    , m_portHasWildcard(portHasWildcard)
     45    , m_isSelfSource(isSelfSource == IsSelfSource::Yes)
    4546{
    4647}
     
    4849bool ContentSecurityPolicySource::matches(const URL& url, bool didReceiveRedirectResponse) const
    4950{
     51    // https://www.w3.org/TR/CSP3/#match-url-to-source-expression.
    5052    if (!schemeMatches(url))
    5153        return false;
     
    5759bool ContentSecurityPolicySource::schemeMatches(const URL& url) const
    5860{
    59     if (m_scheme.isEmpty())
    60         return m_policy.protocolMatchesSelf(url);
    61     if (equalLettersIgnoringASCIICase(m_scheme, "http"))
    62         return url.protocolIsInHTTPFamily();
    63     return equalIgnoringASCIICase(url.protocol(), m_scheme);
     61    // https://www.w3.org/TR/CSP3/#match-schemes.
     62    const auto& scheme = m_scheme.isEmpty() ? m_policy.selfProtocol() : m_scheme;
     63    auto urlScheme = url.protocol().convertToASCIILowercase();
     64
     65    if (scheme == urlScheme)
     66        return true;
     67
     68    // host-sources can do direct-upgrades.
     69    if (scheme == "http" && urlScheme == "https")
     70        return true;
     71    if (scheme == "ws" && (urlScheme == "wss" || urlScheme == "https" || urlScheme == "http"))
     72        return true;
     73    if (scheme == "wss" && urlScheme == "https")
     74        return true;
     75
     76    // self-sources can always upgrade to secure protocols and side-grade insecure protocols.
     77    if ((m_isSelfSource
     78        && ((urlScheme == "https" || urlScheme == "wss") || (scheme == "http" && urlScheme == "ws"))))
     79        return true;
     80
     81    return false;
    6482}
    6583
     
    104122        return true;
    105123
    106     if ((m_port && WTF::isDefaultPortForProtocol(m_port.value(), "http")) && ((!port && url.protocolIs("https")) || (port && WTF::isDefaultPortForProtocol(port.value(), "https"))))
     124    // host-source and self-source allows upgrading to a more secure scheme which allows for different ports.
     125    auto defaultSecurePort = WTF::defaultPortForProtocol("https").value_or(443);
     126    auto defaultInsecurePort = WTF::defaultPortForProtocol("http").value_or(80);
     127    bool isUpgradeSecure = (port == defaultSecurePort) || (!port && (url.protocol() == "https" || url.protocol() == "wss"));
     128    bool isCurrentUpgradable = (m_port == defaultInsecurePort) || (m_scheme == "http" && (!m_port || m_port == defaultSecurePort));
     129    if (isUpgradeSecure && isCurrentUpgradable)
    107130        return true;
    108131
  • trunk/Source/WebCore/page/csp/ContentSecurityPolicySource.h

    r278253 r292266  
    3434struct SecurityOriginData;
    3535
     36enum class IsSelfSource : bool { No, Yes };
     37
    3638class ContentSecurityPolicySource {
    3739    WTF_MAKE_FAST_ALLOCATED;
    3840public:
    39     ContentSecurityPolicySource(const ContentSecurityPolicy&, const String& scheme, const String& host, std::optional<uint16_t> port, const String& path, bool hostHasWildcard, bool portHasWildcard);
     41    ContentSecurityPolicySource(const ContentSecurityPolicy&, const String& scheme, const String& host, std::optional<uint16_t> port, const String& path, bool hostHasWildcard, bool portHasWildcard, IsSelfSource);
    4042
    4143    bool matches(const URL&, bool didReceiveRedirectResponse = false) const;
     
    5860    bool m_hostHasWildcard;
    5961    bool m_portHasWildcard;
     62    bool m_isSelfSource;
    6063};
    6164
  • trunk/Source/WebCore/page/csp/ContentSecurityPolicySourceList.cpp

    r292151 r292266  
    121121        return true;
    122122
    123     // Although not allowed by the Content Security Policy Level 3 spec., we allow a data URL to match
     123    // This is counter to the CSP3 spec which only allows HTTPS but Chromium also allows it.
     124    bool isAllowed = url.protocolIsInHTTPFamily() || url.protocolIs("ws") || url.protocolIs("wss") || url.protocolIs(m_policy.selfProtocol());
     125    // Also not allowed by the Content Security Policy Level 3 spec., we allow a data URL to match
    124126    // "img-src *" and either a data URL or blob URL to match "media-src *" for web compatibility.
    125     bool isAllowed = url.protocolIsInHTTPFamily() || url.protocolIs("ws") || url.protocolIs("wss") || m_policy.protocolMatchesSelf(url);
    126127    if (equalIgnoringASCIICase(m_directiveName, ContentSecurityPolicyDirectiveNames::imgSrc))
    127128        isAllowed |= url.protocolIsData();
     
    270271                m_policy.reportDirectiveAsSourceExpression(m_directiveName, source->host.value);
    271272            if (isValidSourceForExtensionMode(source.value()))
    272                 m_list.append(ContentSecurityPolicySource(m_policy, source->scheme.toString(), source->host.value.toString(), source->port.value, source->path, source->host.hasWildcard, source->port.hasWildcard));
     273                m_list.append(ContentSecurityPolicySource(m_policy, source->scheme.convertToASCIILowercase(), source->host.value.toString(), source->port.value, source->path, source->host.hasWildcard, source->port.hasWildcard, IsSelfSource::No));
    273274        } else
    274275            m_policy.reportInvalidSourceExpression(m_directiveName, String(beginSource, buffer.position() - beginSource));
Note: See TracChangeset for help on using the changeset viewer.