Medium chrome Logic Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactMissing authorization in FileSystem
DescriptionMissing authorization in FileSystem
ComponentFileSystem
Bug ClassLogic Error
Tracker495876543
Fix commit74bd85102d78 (chromium/src) +184/-2
CISA KEVNot listed
CreditedGoogle
Disclosed2026-09-08

Changed Functions

FunctionChangeNotes
if
content/browser/file_system_access/file_system_access_directory_handle_impl.cc
modified
if
content/browser/file_system_access/file_system_access_file_handle_impl.cc
modified

Files Changed

  • content/browser/file_system_access/file_system_access_directory_handle_impl.cc
  • content/browser/file_system_access/file_system_access_file_handle_impl.cc
  • content/browser/file_system_access/file_system_access_observer_browsertest.cc
From 74bd85102d783a72b0fdbac99adfc1cc134b372d Mon Sep 17 00:00:00 2001
From: Mike Taylor <[email protected]>
Date: Thu, 06 Aug 2026 11:06:37 -0700
Subject: [PATCH] FSA: Check token origin in Resolve() and IsSameEntry()

FileSystemAccessDirectoryHandleImpl::ResolveImpl and
FileSystemAccessFileHandleImpl::IsSameEntryImpl resolve the
FileSystemAccessTransferToken passed to resolve() /
isSameEntry() but do not verify that the resolved token's
origin matches the calling context's origin. Sibling callbacks
that resolve transfer tokens (DidResolveTokenToMove,
DidResolveTransferTokenToObserve,
DidResolveTransferTokenForFileHandle and
DidResolveTransferTokenForDirectoryHandle) already enforce this
check; ResolveImpl and IsSameEntryImpl were missed.

Add an origin check mirroring those sibling callbacks: reject
the call with kOperationFailed when the resolved token is null
or its origin differs from context().storage_key.origin().

Also add content_browsertests
(FileSystemAccessObserverCrossOriginTokenBypassTest.
ResolveRefusesCrossOriginChildToken and
IsSameEntryRefusesCrossOriginToken) that drive the browser-side
interfaces directly with a foreign-origin transfer token and
verify the calls are rejected.

TAG=agy
CONV=680ba172-7c3e-488d-bcc5-7e67aaff5c41

Bug: 495876543
Change-Id: I36968b94f857e1a5119f56930d6db8c8a373a266
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8202508
Reviewed-by: Rahul Singh <[email protected]>
Commit-Queue: Mike Taylor <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1675118}
---

diff --git a/content/browser/file_system_access/file_system_access_directory_handle_impl.cc b/content/browser/file_system_access/file_system_access_directory_handle_impl.cc
index 74be365e..9ca98fc 100644
--- a/content/browser/file_system_access/file_system_access_directory_handle_impl.cc
+++ b/content/browser/file_system_access/file_system_access_directory_handle_impl.cc
@@ -557,7 +557,8 @@
     FileSystemAccessTransferTokenImpl* possible_child) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  if (!possible_child) {
+  if (!possible_child ||
+      possible_child->origin() != context().storage_key.origin()) {
     std::move(callback).Run(
         file_system_access_error::FromStatus(
             blink::mojom::FileSystemAccessStatus::kOperationFailed),
diff --git a/content/browser/file_system_access/file_system_access_file_handle_impl.cc b/content/browser/file_system_access/file_system_access_file_handle_impl.cc
index 8a987f8..984b099 100644
--- a/content/browser/file_system_access/file_system_access_file_handle_impl.cc
+++ b/content/browser/file_system_access/file_system_access_file_handle_impl.cc
@@ -474,7 +474,7 @@
     IsSameEntryCallback callback,
     FileSystemAccessTransferTokenImpl* other) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (!other) {
+  if (!other || other->origin() != context().storage_key.origin()) {
     std::move(callback).Run(
         file_system_access_error::FromStatus(
             blink::mojom::FileSystemAccessStatus::kOperationFailed),
diff --git a/content/browser/file_system_access/file_system_access_observer_browsertest.cc b/content/browser/file_system_access/file_system_access_observer_browsertest.cc
index 3c294fa0..b0c36f1 100644
--- a/content/browser/file_system_access/file_system_access_observer_browsertest.cc
+++ b/content/browser/file_system_access/file_system_access_observer_browsertest.cc
@@ -1691,4 +1691,185 @@
             blink::mojom::FileSystemAccessStatus::kInvalidArgument);
 }
 
+// Checks that a possible-child transfer token from a different origin cannot
+// be resolved against a directory handle from the calling origin.
+IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverCrossOriginTokenBypassTest,
+                       ResolveRefusesCrossOriginChildToken) {
+  base::FilePath parent_dir_path;
+  base::FilePath child_file_path;
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    ASSERT_TRUE(base::CreateTemporaryDirInDir(
+        temp_dir_.GetPath(), FILE_PATH_LITERAL("parent"), &parent_dir_path));
+    ASSERT_TRUE(
+        base::CreateTemporaryFileInDir(parent_dir_path, &child_file_path));
+  }
+
+  // First origin site.
+  GURL url_first = GetURL("a.com", "/title1.html");
+  const url::Origin origin_first = url::Origin::Create(url_first);
+  const blink::StorageKey key_first =
+      blink::StorageKey::CreateFirstParty(origin_first);
+  // Second origin site.
+  GURL url_second = GetURL("b.com", "/title1.html");
+  const url::Origin origin_second = url::Origin::Create(url_second);
+  const blink::StorageKey key_second =
+      blink::StorageKey::CreateFirstParty(origin_second);
+  ASSERT_NE(origin_first, origin_second);
+
+  ASSERT_TRUE(NavigateToURL(shell(), url_first));
+  RenderFrameHost* rfh = shell()->web_contents()->GetPrimaryMainFrame();
+  ASSERT_TRUE(rfh);
+
+  auto* manager = GetManager();
+  ASSERT_TRUE(manager);
+
+  // First origin owns a file handle whose path is inside second origin's
+  // directory.
+  const storage::FileSystemURL first_file_url =
+      manager->CreateFileSystemURLFromPath(PathInfo(child_file_path));
+  auto first_read_grant =
+      base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>(
+          FixedFileSystemAccessPermissionGrant::PermissionStatus::GRANTED,
+          PathInfo(child_file_path));
+  auto first_write_grant =
+      base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>(
+          FixedFileSystemAccessPermissionGrant::PermissionStatus::GRANTED,
+          PathInfo(child_file_path));
+  FileSystemAccessManagerImpl::SharedHandleState first_handle_state(
+      first_read_grant, first_write_grant);
+  FileSystemAccessManagerImpl::BindingContext first_context(
+      key_first, url_first, rfh->GetGlobalId());
+  auto first_file_handle = std::make_unique<FileSystemAccessFileHandleImpl>(
+      manager, first_context, first_file_url, /*display_name=*/"",
+      first_handle_state);
+
+  // Transfer token for first origin's file, registered in the manager.
+  mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote;
+  manager->CreateTransferToken(*first_file_handle,
+                               token_remote.InitWithNewPipeAndPassReceiver());
+
+  // Second origin owns the parent directory handle.
+  const storage::FileSystemURL second_dir_url =
+      manager->CreateFileSystemURLFromPath(PathInfo(parent_dir_path));
+  auto second_read_grant =
+      base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>(
+          FixedFileSystemAccessPermissionGrant::PermissionStatus::GRANTED,
+          PathInfo(parent_dir_path));
+  auto second_write_grant =
+      base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>(
+          FixedFileSystemAccessPermissionGrant::PermissionStatus::GRANTED,
+          PathInfo(parent_dir_path));
+  FileSystemAccessManagerImpl::SharedHandleState second_handle_state(
+      second_read_grant, second_write_grant);
+  FileSystemAccessManagerImpl::BindingContext second_context(
+      key_second, url_second, rfh->GetGlobalId());
+  auto second_dir_handle =
+      std::make_unique<FileSystemAccessDirectoryHandleImpl>(
+          manager, second_context, second_dir_url, second_handle_state);
+
+  // Call Resolve() on second origin's directory handle with first origin's
+  // file transfer token as the possible child.
+  base::RunLoop run_loop;
+  blink::mojom::FileSystemAccessStatus resolve_status;
+  std::optional<std::vector<std::string>> resolve_path;
+  static_cast<blink::mojom::FileSystemAccessDirectoryHandle*>(
+      second_dir_handle.get())
+      ->Resolve(std::move(token_remote),
+                base::BindLambdaForTesting(
+                    [&](blink::mojom::FileSystemAccessErrorPtr result,
+                        const std::optional<std::vector<std::string>>& path) {
+                      resolve_status = result->status;
+                      resolve_path = path;
+                      run_loop.Quit();
+                    }));
+  run_loop.Run();
+
+  // ResolveImpl must reject the mismatch when the token origin does not match
+  // the caller's binding context origin.
+  EXPECT_EQ(resolve_status,
+            blink::mojom::FileSystemAccessStatus::kOperationFailed);
+  EXPECT_FALSE(resolve_path.has_value());
+}
+
+// Checks that a transfer token from a different origin cannot be used with
+// FileSystemFileHandle::isSameEntry() to check against another origin's handle.
+IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverCrossOriginTokenBypassTest,
+                       IsSameEntryRefusesCrossOriginToken) {
+  base::FilePath file_path;
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    ASSERT_TRUE(
+        base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
+  }
+
+  // First origin site.
+  GURL url_first = GetURL("a.com", "/title1.html");
+  const url::Origin origin_first = url::Origin::Create(url_first);
+  const blink::StorageKey key_first =
+      blink::StorageKey::CreateFirstParty(origin_first);
+  // Second origin site.
+  GURL url_second = GetURL("b.com", "/title1.html");
+  const url::Origin origin_second = url::Origin::Create(url_second);
+  const blink::StorageKey key_second =
+      blink::StorageKey::CreateFirstParty(origin_second);
+  ASSERT_NE(origin_first, origin_second);
+
+  ASSERT_TRUE(NavigateToURL(shell(), url_first));
+  RenderFrameHost* rfh = shell()->web_contents()->GetPrimaryMainFrame();
+  ASSERT_TRUE(rfh);
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/content/browser/file_system_access/file_system_access_observer_browsertest.cc b/content/browser/file_system_access/file_system_access_observer_browsertest.cc
index 3c294fa0..b0c36f1 100644
--- a/content/browser/file_system_access/file_system_access_observer_browsertest.cc
+++ b/content/browser/file_system_access/file_system_access_observer_browsertest.cc
@@ -1691,4 +1691,185 @@
             blink::mojom::FileSystemAccessStatus::kInvalidArgument);
 }
 
+// Checks that a possible-child transfer token from a different origin cannot
+// be resolved against a directory handle from the calling origin.
+IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverCrossOriginTokenBypassTest,
+                       ResolveRefusesCrossOriginChildToken) {
+  base::FilePath parent_dir_path;
+  base::FilePath child_file_path;
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    ASSERT_TRUE(base::CreateTemporaryDirInDir(
+        temp_dir_.GetPath(), FILE_PATH_LITERAL("parent"), &parent_dir_path));
+    ASSERT_TRUE(
+        base::CreateTemporaryFileInDir(parent_dir_path, &child_file_path));
+  }
+
+  // First origin site.
+  GURL url_first = GetURL("a.com", "/title1.html");
+  const url::Origin origin_first = url::Origin::Create(url_first);
+  const blink::StorageKey key_first =
+      blink::StorageKey::CreateFirstParty(origin_first);
+  // Second origin site.
+  GURL url_second = GetURL("b.com", "/title1.html");
+  const url::Origin origin_second = url::Origin::Create(url_second);
+  const blink::StorageKey key_second =
+      blink::StorageKey::CreateFirstParty(origin_second);
+  ASSERT_NE(origin_first, origin_second);
+
+  ASSERT_TRUE(NavigateToURL(shell(), url_first));
+  RenderFrameHost* rfh = shell()->web_contents()->GetPrimaryMainFrame();
+  ASSERT_TRUE(rfh);
+
+  auto* manager = GetManager();
+  ASSERT_TRUE(manager);
+
+  // First origin owns a file handle whose path is inside second origin's
+  // directory.
+  const storage::FileSystemURL first_file_url =
+      manager->CreateFileSystemURLFromPath(PathInfo(child_file_path));
+  auto first_read_grant =
+      base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>(
+          FixedFileSystemAccessPermissionGrant::PermissionStatus::GRANTED,
+          PathInfo(child_file_path));
+  auto first_write_grant =
+      base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>(
+          FixedFileSystemAccessPermissionGrant::PermissionStatus::GRANTED,
+          PathInfo(child_file_path));
+  FileSystemAccessManagerImpl::SharedHandleState first_handle_state(
+      first_read_grant, first_write_grant);
+  FileSystemAccessManagerImpl::BindingContext first_context(
+      key_first, url_first, rfh->GetGlobalId());
+  auto first_file_handle = std::make_unique<FileSystemAccessFileHandleImpl>(
+      manager, first_context, first_file_url, /*display_name=*/"",
+      first_handle_state);
+
+  // Transfer token for first origin's file, registered in the manager.
+  mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote;
+  manager->CreateTransferToken(*first_file_handle,
+                               token_remote.InitWithNewPipeAndPassReceiver());
+
+  // Second origin owns the parent directory handle.
+  const storage::FileSystemURL second_dir_url =
+      manager->CreateFileSystemURLFromPath(PathInfo(parent_dir_path));
+  auto second_read_grant =
+      base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>(
+          FixedFileSystemAccessPermissionGrant::PermissionStatus::GRANTED,
+          PathInfo(parent_dir_path));
+  auto second_write_grant =
+      base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>(
+          FixedFileSystemAccessPermissionGrant::PermissionStatus::GRANTED,
+          PathInfo(parent_dir_path));
+  FileSystemAccessManagerImpl::SharedHandleState second_handle_state(
+      second_read_grant, second_write_grant);
+  FileSystemAccessManagerImpl::BindingContext second_context(
+      key_second, url_second, rfh->GetGlobalId());
+  auto second_dir_handle =
+      std::make_unique<FileSystemAccessDirectoryHandleImpl>(
+          manager, second_context, second_dir_url, second_handle_state);
+
+  // Call Resolve() on second origin's directory handle with first origin's
+  // file transfer token as the possible child.
+  base::RunLoop run_loop;
+  blink::mojom::FileSystemAccessStatus resolve_status;
+  std::optional<std::vector<std::string>> resolve_path;
+  static_cast<blink::mojom::FileSystemAccessDirectoryHandle*>(
+      second_dir_handle.get())
+      ->Resolve(std::move(token_remote),
+                base::BindLambdaForTesting(
+                    [&](blink::mojom::FileSystemAccessErrorPtr result,
+                        const std::optional<std::vector<std::string>>& path) {
+                      resolve_status = result->status;
+                      resolve_path = path;
+                      run_loop.Quit();
+                    }));
+  run_loop.Run();
+
+  // ResolveImpl must reject the mismatch when the token origin does not match
+  // the caller's binding context origin.
+  EXPECT_EQ(resolve_status,
+            blink::mojom::FileSystemAccessStatus::kOperationFailed);
+  EXPECT_FALSE(resolve_path.has_value());
+}
+
+// Checks that a transfer token from a different origin cannot be used with
+// FileSystemFileHandle::isSameEntry() to check against another origin's handle.
+IN_PROC_BROWSER_TEST_F(FileSystemAccessObserverCrossOriginTokenBypassTest,
+                       IsSameEntryRefusesCrossOriginToken) {
+  base::FilePath file_path;
+  {
+    base::ScopedAllowBlockingForTesting allow_blocking;
+    ASSERT_TRUE(
+        base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &file_path));
+  }
+
+  // First origin site.
+  GURL url_first = GetURL("a.com", "/title1.html");
+  const url::Origin origin_first = url::Origin::Create(url_first);
+  const blink::StorageKey key_first =
+      blink::StorageKey::CreateFirstParty(origin_first);
+  // Second origin site.
+  GURL url_second = GetURL("b.com", "/title1.html");
+  const url::Origin origin_second = url::Origin::Create(url_second);
+  const blink::StorageKey key_second =
+      blink::StorageKey::CreateFirstParty(origin_second);
+  ASSERT_NE(origin_first, origin_second);
+
+  ASSERT_TRUE(NavigateToURL(shell(), url_first));
+  RenderFrameHost* rfh = shell()->web_contents()->GetPrimaryMainFrame();
+  ASSERT_TRUE(rfh);
+
+  auto* manager = GetManager();
+  ASSERT_TRUE(manager);
+
+  const storage::FileSystemURL file_url =
+      manager->CreateFileSystemURLFromPath(PathInfo(file_path));
+  auto read_grant = base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>(
+      FixedFileSystemAccessPermissionGrant::PermissionStatus::GRANTED,
+      PathInfo(file_path));
+  auto write_grant = base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>(
+      FixedFileSystemAccessPermissionGrant::PermissionStatus::GRANTED,
+      PathInfo(file_path));
+  FileSystemAccessManagerImpl::SharedHandleState handle_state(read_grant,
+                                                              write_grant);
+
+  // Both origins independently hold a file handle to the same underlying file.
+  FileSystemAccessManagerImpl::BindingContext first_context(
+      key_first, url_first, rfh->GetGlobalId());
+  auto first_file_handle = std::make_unique<FileSystemAccessFileHandleImpl>(
+      manager, first_context, file_url, /*display_name=*/"", handle_state);
+
+  FileSystemAccessManagerImpl::BindingContext second_context(
+      key_second, url_second, rfh->GetGlobalId());
+  auto second_file_handle = std::make_unique<FileSystemAccessFileHandleImpl>(
+      manager, second_context, file_url, /*display_name=*/"", handle_state);
+
+  // Transfer token for first origin's file, registered in the manager.
+  mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote;
+  manager->CreateTransferToken(*first_file_handle,
+                               token_remote.InitWithNewPipeAndPassReceiver());
+
+  // Call IsSameEntry() on second origin's file handle with first origin's
+  // transfer token.
+  base::RunLoop run_loop;
+  blink::mojom::FileSystemAccessStatus status;
+  bool is_same = false;
+  static_cast<blink::mojom::FileSystemAccessFileHandle*>(
+      second_file_handle.get())
+      ->IsSameEntry(
+          std::move(token_remote),
+          base::BindLambdaForTesting(
+              [&](blink::mojom::FileSystemAccessErrorPtr result, bool same) {
+                status = result->status;
+                is_same = same;
+                run_loop.Quit();
+              }));
+  run_loop.Run();
+
+  // IsSameEntryImpl must reject the mismatch when the token origin does not
+  // match the caller's binding context origin.
+  EXPECT_EQ(status, blink::mojom::FileSystemAccessStatus::kOperationFailed);
+  EXPECT_FALSE(is_same);
+}
+
 }  // namespace content
Loading diff…

Original Bug Report

reported by [email protected]

Potential missing origin check in File System Access API transfer tokens

Project Fortify, an experimental security project, has identified the following potential security issue.

Overview: Several Mojo methods in the File System Access API fail to verify that a provided transfer token belongs to the caller’s origin. A compromised renderer can intercept a token sent via postMessage from another origin and redeem it via methods like Move, Resolve, or Observe. This potentially allows unauthorized cross-origin file operations, such as writing to a victim’s directory.

Affected files:

  • content/browser/file_system_access/file_system_access_directory_handle_impl.cc
  • content/browser/file_system_access/file_system_access_file_handle_impl.cc
  • content/browser/file_system_access/file_system_access_handle_base.cc
  • content/browser/file_system_access/file_system_access_observer_host.cc

Estimated timestamp from git blame: 2025-08-25

Note: The following analysis and steps are suggested by an AI agent. A working proof-of-concept has not been executed, but the logical flow has been traced through the codebase.

Root Cause

In the File System Access API, when handles are passed via postMessage, they are serialized into a FileSystemAccessTransferToken. When these tokens are normally redeemed (e.g., via GetFileHandleFromToken), the browser enforces an origin check via IsValidTransferToken() to ensure the calling renderer’s origin matches the origin embedded in the token.

However, several Mojo API endpoints take a PendingRemote<FileSystemAccessTransferToken> as an argument and resolve it using FileSystemAccessManagerImpl::ResolveTransferToken(). This method retrieves the token via its unguessable ID but fails to perform any origin validation. The resulting FileSystemAccessTransferTokenImpl is then directly acted upon.

The following methods are affected:

  1. FileSystemAccessHandleBase::DoMove: Passes the token to DidResolveTokenToMove. An attacker can use a victim’s directory token as the destination, potentially moving their own files into the victim’s directory, bypassing cross-origin write restrictions.
  2. FileSystemAccessDirectoryHandleImpl::Resolve: Passes the token to ResolveImpl. Can be used to disclose relative paths of a victim’s files.
  3. FileSystemAccessObserverHost::Observe: Passes the token to DidResolveTransferTokenToObserve. Can be used to spy on file changes in a victim’s handle.
  4. FileSystemAccessFileHandleImpl::IsSameEntry: Passes the token to IsSameEntryImpl. Can be used to verify if an attacker’s file handle matches a victim’s.

Potential Exploitation Steps (e.g., Cross-Origin Write via Move)

  1. Victim Grants Access: A victim origin (https://victim.com) requests and is granted access to a local directory (e.g., /home/user/VictimDir/) via showDirectoryPicker().
  2. Token Transfer: The victim web application inadvertently or intentionally shares this directory handle with an attacker origin (https://attacker.com) via window.postMessage(directoryHandle, '*').
  3. Token Interception: The attacker has compromised the renderer process for https://attacker.com. Instead of letting the browser reject standard deserialization, the attacker intercepts the raw Mojo PendingRemote<FileSystemAccessTransferToken> IPC message.
  4. Attacker Context: The compromised attacker renderer obtains a legitimate file handle for one of its own files (e.g., /home/user/AttackerDir/evil.txt).
  5. The Exploit Call: The attacker issues a raw Mojo call to their file handle’s Move method, passing the victim’s intercepted PendingRemote<FileSystemAccessTransferToken> as the destination directory, and "pwned.txt" as the new name.
  6. Browser Processing: In the browser process, FileSystemAccessHandleBase::DoMove calls manager()->ResolveTransferToken(). The token is successfully resolved without an origin check.
  7. Unauthorized Write: DidResolveTokenToMove checks the write permission of the resolved token. Because the GetStatus() check on the token’s grant evaluates the original victim’s granted permissions, it passes. The attacker’s file is moved into the victim’s directory, achieving an unauthorized cross-origin file write.

Suggested Fix

Update FileSystemAccessManagerImpl::ResolveTransferToken() (or its DoResolveTransferToken internal helper) to accept the calling binding_context.storage_key.origin() and enforce IsValidTransferToken() before returning the resolved token. Alternatively, enforce the IsValidTransferToken() origin check individually in all vulnerable callbacks (DidResolveTokenToMove, ResolveImpl, DidResolveTransferTokenToObserve, IsSameEntryImpl).

Evaluated with Chrome root at commit: bb48272cafb7e24c93f55ef40da398cd206ee651


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. Please feel free to reach out to me if you have concerns or feedback.

View on issue tracker