Medium watch CVSS 5.4 chrome Authorization Error 📄 Reporter bug report 🔧 Commit mapped

Overview

Medium
Severity
5.4
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactIncorrect authorization in Downloads
DescriptionIncorrect authorization in Downloads
ComponentDownloads
Bug ClassAuthorization Error
Action tierwatch — logic/policy bug — security-relevant, no memory-unsafety
Computed by PatchGap's deterministic exploitability ruler from the fixing commit. patch-now = RCE-class & attacker-reachable in a default config, or exploited in the wild; watch = real security signal below that bar; noise = no security relevance.
Tracker499423269
Fix commitbef9afc5c8be (chromium/src) +114/-3
CWECWE-863
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N
CISA KEVNot listed
CreditedGoogle
Reported2026-04-04 (per vendor advisory)
Fix landed2026-07-23 (public git)
Disclosed2026-08-25
Patch gap33 days — fix public in source before the advisory

Background

`DownloadPathReservationTracker`
browser-process code that validates and reserves a download’s target path before writing, rejecting or uniquifying paths that conflict with existing files, in-progress reservations, or the download’s own source.
`PathValidationResult::SAME_AS_SOURCE`
the result that stops a download whose target path is its own source file (possible when the source is a file:// URL pointing into the download directory), so Chrome does not truncate or overwrite the file it is reading.
Case-insensitive filesystems
default Windows (NTFS) and macOS (APFS/HFS+) volumes treat foo.txt and FOO.txt as the same file, so an exact string comparison of paths can miss that two paths are identical on disk.
`base::FilePath::CompareEqualIgnoreCase`
a helper that compares path strings ignoring case. The tracker already used it in its reservation-map check.

Root Cause Analysis

The source-versus-target check in download_path_reservation_tracker.cc used exact equality (*target_path == info.source_path in one function, and target_path == info.source_path in the Android DownloadCollectionBridge::ShouldPublishDownload branch of another; neither enclosing function is named in the hunks). The old comment says the authors chose not to handle paths that differ only by case. On a case-insensitive filesystem, though, a file:// source in the download directory saved as the same path with different case (foo.txt → FOO.txt) passed the equality check while naming the same file on disk, so the “do not download a file onto itself” check was skipped and the target write could clobber the source.

The fix makes the check stricter: both sites now use base::FilePath::CompareEqualIgnoreCase(...), so case-only differences return SAME_AS_SOURCE on every platform. As the commit message notes, this deliberately accepts false positives on case-sensitive filesystems in exchange for no false negatives on case-insensitive ones. The first hunk (adding braces around an existing CompareEqualIgnoreCase reservation check) is a style-only change with no effect on behaviour.

Key insight
A path-identity security check compared strings exactly when the underlying filesystem may compare them case-insensitively, so two strings naming the same file were treated as different. The fix compares them case-insensitively, failing safe.

Attack Path

  1. File-URL download source in the download directory A download is started whose source is a file:// URL pointing into the user’s download directory, as in CaseConflictWithSource. Ordinary web content cannot normally start file:// loads, so this probably needs the user to open a local file, or an extension or other privileged initiator (inferred).
  2. Target path differs only by case The suggested or chosen target is the same full path with different case (for example foo.txt vs FOO.txt).
  3. Self-overwrite check skipped Before the fix, the exact comparison found the paths different, so validation went on to IsPathInUse() and later checks instead of returning SAME_AS_SOURCE.
  4. Source clobbered on a case-insensitive filesystem On default Windows or macOS volumes the download writes to the file it is reading from, which can truncate or corrupt it (inferred from the commit message’s “output file could overwrite the input”).

Impact Assessment

The bug weakens a browser-process safety check in the download system and can let a download overwrite or truncate its own source file in the download directory on case-insensitive filesystems. Preconditions are narrow: a file:// source inside the download directory and a target path that differs from it only by case. Any use beyond local data loss or integrity loss is not shown by the patch (inferred). The advisory gives “Incorrect authorization in Downloads” with no in-the-wild status.

Changed Functions

FunctionChangeNotes
if
components/download/internal/common/download_path_reservation_tracker.cc
modified
TEST_F
components/download/internal/common/download_path_reservation_tracker_unittest.cc
modified
if
components/download/internal/common/download_path_reservation_tracker_unittest.cc
modified

Files Changed

  • components/download/internal/common/download_path_reservation_tracker.cc
  • components/download/internal/common/download_path_reservation_tracker_unittest.cc

Audit Directions

  • Exact path equality used for identity
    Search the download, file-system-access, chrome.downloads and Safe Browsing code for FilePath == comparisons that decide whether two paths name the same file. Consider case folding, Unicode normalisation (NFC/NFD on macOS), 8.3 short names, trailing dots and spaces on Windows, and symlinks or junctions.
  • `file://` sources as download inputs
    Review other places where a local file can be both the source and the destination of a write (Save Page As, chrome.downloads.download with a file: URL, drag-out) to confirm the self-overwrite check is applied consistently.
  • Same check repeated across platform branches
    Where a check is copied into platform branches (Android DownloadCollectionBridge versus desktop), confirm both copies have the same semantics after any fix.
From bef9afc5c8bec12e0055064da8281aa76e20dcd1 Mon Sep 17 00:00:00 2001
From: Joe Mason <[email protected]>
Date: Thu, 23 Jul 2026 10:32:26 -0700
Subject: [PATCH] Treat download files that differ only by case as SAME_AS_SOURCE

An existing comment says: "Assume that downloading a file onto another
file that differs only by case is not enough of a legitimate edge case
to justify determining the case sensitivity of the underlying
filesystem," then treats files that differ only by case as "different"
on all systems. This flips that logic and treats them as "the same" on
all systems. That can lead to false positives where file downloads are
incorrectly denied on case-sensitive systems, but that's safer than a
false negative on case-insensitive systems.

Since the comparison uses the full file path, not just the name, this
only affects the extreme edge case of a download source that's a file://
url pointing into the download directory, that's saved to the same path
with a different case. That's dangerous on case-insensitive file systems
since the output file could overwrite the input. On case-sensitive file
systems it would work, but seems reasonable to block.

Also adds some unit tests for more operations that could be affected by
case conflicts. These are already handled correctly but weren't
explicitly tested.

Fixed: 499423269
Change-Id: I99073a086eefb57fc091aca9a004da75ded2f0b6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8135087
Reviewed-by: Min Qin <[email protected]>
Commit-Queue: Min Qin <[email protected]>
Auto-Submit: Joe Mason <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1667233}
---
diff --git a/components/download/internal/common/download_path_reservation_tracker.cc b/components/download/internal/common/download_path_reservation_tracker.cc
index 2e8490d..9baf8e18 100644
--- a/components/download/internal/common/download_path_reservation_tracker.cc
+++ b/components/download/internal/common/download_path_reservation_tracker.cc
@@ -103,8 +103,9 @@
        iter != g_reservation_map->end(); ++iter) {
     if ((!item || iter->first != item) &&
         base::FilePath::CompareEqualIgnoreCase(iter->second.value(),
-                                               path.value()))
+                                               path.value())) {
       return true;
+    }
   }
   return false;
 }
@@ -324,8 +325,10 @@
   // onto another file that differs only by case is not enough of a legitimate
   // edge case to justify determining the case sensitivity of the underlying
   // filesystem.
-  if (*target_path == info.source_path)
+  if (base::FilePath::CompareEqualIgnoreCase(target_path->value(),
+                                             info.source_path.value())) {
     return PathValidationResult::SAME_AS_SOURCE;
+  }
 
   if (!IsPathInUse(*target_path))
     return PathValidationResult::SUCCESS;
@@ -369,7 +372,11 @@
   if (DownloadCollectionBridge::ShouldPublishDownload(target_path)) {
     PathValidationResult result = PathValidationResult::SUCCESS;
     // Disallow downloading a file onto itself. Assume that downloading a file
-    if (target_path == info.source_path) {
+    // onto another file that differs only by case is not enough of a legitimate
+    // edge case to justify determining the case sensitivity of the underlying
+    // filesystem.
+    if (base::FilePath::CompareEqualIgnoreCase(target_path.value(),
+                                               info.source_path.value())) {
       result = PathValidationResult::SAME_AS_SOURCE;
     } else if (IsPathInUse(target_path)) {
       // If the download is written to a content URI, put file name in the
diff --git a/components/download/internal/common/download_path_reservation_tracker_unittest.cc b/components/download/internal/common/download_path_reservation_tracker_unittest.cc
index 749b51a..b4aa382a 100644
--- a/components/download/internal/common/download_path_reservation_tracker_unittest.cc
+++ b/components/download/internal/common/download_path_reservation_tracker_unittest.cc
@@ -314,6 +314,47 @@
   EXPECT_FALSE(IsPathInUse(path1));
 }
 
+// As above, but checks for existing files that differ only by case.
+TEST_F(DownloadPathReservationTrackerTest, CaseConflictingFiles) {
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
+
+  base::FilePath path(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
+  base::FilePath target_path(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("FOO.txt")));
+  base::FilePath path1(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("FOO (1).txt")));
+  bool use_download_collection = false;
+#if BUILDFLAG(IS_ANDROID)
+  if (DownloadCollectionBridge::ShouldPublishDownload(path)) {
+    use_download_collection = true;
+    DownloadCollectionBridge::AddExistingFileNameForTesting(path.BaseName());
+  }
+#endif  // BUILDFLAG(IS_ANDROID)
+  if (!use_download_collection) {
+    // Create a file at |path|, and a .crdownload file at |path1|.
+    ASSERT_TRUE(base::WriteFile(path, ""));
+    ASSERT_TRUE(base::WriteFile(
+        base::FilePath(path1.value() + FILE_PATH_LITERAL(".crdownload")), ""));
+  }
+
+  ASSERT_TRUE(IsPathInUse(path));
+
+  // Whether this counts as a conflict depends on whether the filesystem is
+  // actually case-sensitive.
+  CreateReservation(
+      item.get(), target_path, DownloadPathReservationTracker::UNIQUIFY,
+      IsPathInUse(target_path) ? PathValidationResult::SUCCESS_RESOLVED_CONFLICT
+                               : PathValidationResult::SUCCESS,
+      IsPathInUse(target_path) ? path1 : target_path);
+
+  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
+  item.reset();
+  RunUntilIdle();
+  EXPECT_TRUE(IsPathInUse(path));
+  EXPECT_FALSE(IsPathInUse(path1));
+}
+
 // If there are conflicting files on the file system, an overwriting reservation
 // should succeed without altering the target path.
 TEST_F(DownloadPathReservationTrackerTest, ConflictingFiles_Overwrite) {
@@ -341,6 +382,38 @@
   RunUntilIdle();
 }
 
+// As above, but checks for existing files that differ only by case. On a
+// case-sensitive filesystem this is redundant, since the files won't actually
+// conflict, but it's easier to run the test everywhere than to check the
+// filesystem type.
+TEST_F(DownloadPathReservationTrackerTest, CaseConflictingFiles_Overwrite) {
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
+  base::FilePath path(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
+  base::FilePath target_path(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("FOO.txt")));
+  bool use_download_collection = false;
+#if BUILDFLAG(IS_ANDROID)
+  if (DownloadCollectionBridge::ShouldPublishDownload(path)) {
+    use_download_collection = true;
+    DownloadCollectionBridge::AddExistingFileNameForTesting(path.BaseName());
+  }
+#endif  // BUILDFLAG(IS_ANDROID)
+  if (!use_download_collection) {
+    // Create a file at |path|.
+    ASSERT_TRUE(base::WriteFile(path, ""));
+  }
+  ASSERT_TRUE(IsPathInUse(path));
+
+  CreateReservation(item.get(), target_path,
+                    DownloadPathReservationTracker::OVERWRITE,
+                    PathValidationResult::SUCCESS, target_path);
+
+  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
+  item.reset();
+  RunUntilIdle();
+}
+
 // If the source is a file:// URL that is in the download directory, then Chrome
 // could download the file onto itself. Test that this is flagged by DPRT.
 TEST_F(DownloadPathReservationTrackerTest, ConflictWithSource) {
@@ -369,6 +442,37 @@
   RunUntilIdle();
 }
 
+// As above, but check for a file:// URL that differs only by case. This should
+// be flagged on all file systems, even case-sensitive ones, for safety.
+TEST_F(DownloadPathReservationTrackerTest, CaseConflictWithSource) {
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
+  base::FilePath path(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
+  base::FilePath target_path(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("FOO.txt")));
+  bool use_download_collection = false;
+#if BUILDFLAG(IS_ANDROID)
+  if (DownloadCollectionBridge::ShouldPublishDownload(path)) {
+    use_download_collection = true;
+    DownloadCollectionBridge::AddExistingFileNameForTesting(path.BaseName());
+  }
+#endif  // BUILDFLAG(IS_ANDROID)
+  if (!use_download_collection) {
+    ASSERT_TRUE(base::WriteFile(path, ""));
+  }
+  ASSERT_TRUE(IsPathInUse(path));
+  EXPECT_CALL(*item, GetURL())
+      .WillRepeatedly(ReturnRefOfCopy(net::FilePathToFileURL(path)));
+
+  CreateReservation(item.get(), target_path,
+                    DownloadPathReservationTracker::UNIQUIFY,
+                    PathValidationResult::SAME_AS_SOURCE, target_path);
+
+  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
+  item.reset();
+  RunUntilIdle();
+}
+
 // Multiple reservations for the same path should uniquify around each other.
 TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) {
   std::unique_ptr<MockDownloadItem> item1 = CreateDownloadItem(1);
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/components/download/internal/common/download_path_reservation_tracker_unittest.cc b/components/download/internal/common/download_path_reservation_tracker_unittest.cc
index 749b51a..b4aa382a 100644
--- a/components/download/internal/common/download_path_reservation_tracker_unittest.cc
+++ b/components/download/internal/common/download_path_reservation_tracker_unittest.cc
@@ -314,6 +314,47 @@
   EXPECT_FALSE(IsPathInUse(path1));
 }
 
+// As above, but checks for existing files that differ only by case.
+TEST_F(DownloadPathReservationTrackerTest, CaseConflictingFiles) {
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
+
+  base::FilePath path(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
+  base::FilePath target_path(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("FOO.txt")));
+  base::FilePath path1(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("FOO (1).txt")));
+  bool use_download_collection = false;
+#if BUILDFLAG(IS_ANDROID)
+  if (DownloadCollectionBridge::ShouldPublishDownload(path)) {
+    use_download_collection = true;
+    DownloadCollectionBridge::AddExistingFileNameForTesting(path.BaseName());
+  }
+#endif  // BUILDFLAG(IS_ANDROID)
+  if (!use_download_collection) {
+    // Create a file at |path|, and a .crdownload file at |path1|.
+    ASSERT_TRUE(base::WriteFile(path, ""));
+    ASSERT_TRUE(base::WriteFile(
+        base::FilePath(path1.value() + FILE_PATH_LITERAL(".crdownload")), ""));
+  }
+
+  ASSERT_TRUE(IsPathInUse(path));
+
+  // Whether this counts as a conflict depends on whether the filesystem is
+  // actually case-sensitive.
+  CreateReservation(
+      item.get(), target_path, DownloadPathReservationTracker::UNIQUIFY,
+      IsPathInUse(target_path) ? PathValidationResult::SUCCESS_RESOLVED_CONFLICT
+                               : PathValidationResult::SUCCESS,
+      IsPathInUse(target_path) ? path1 : target_path);
+
+  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
+  item.reset();
+  RunUntilIdle();
+  EXPECT_TRUE(IsPathInUse(path));
+  EXPECT_FALSE(IsPathInUse(path1));
+}
+
 // If there are conflicting files on the file system, an overwriting reservation
 // should succeed without altering the target path.
 TEST_F(DownloadPathReservationTrackerTest, ConflictingFiles_Overwrite) {
@@ -341,6 +382,38 @@
   RunUntilIdle();
 }
 
+// As above, but checks for existing files that differ only by case. On a
+// case-sensitive filesystem this is redundant, since the files won't actually
+// conflict, but it's easier to run the test everywhere than to check the
+// filesystem type.
+TEST_F(DownloadPathReservationTrackerTest, CaseConflictingFiles_Overwrite) {
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
+  base::FilePath path(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
+  base::FilePath target_path(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("FOO.txt")));
+  bool use_download_collection = false;
+#if BUILDFLAG(IS_ANDROID)
+  if (DownloadCollectionBridge::ShouldPublishDownload(path)) {
+    use_download_collection = true;
+    DownloadCollectionBridge::AddExistingFileNameForTesting(path.BaseName());
+  }
+#endif  // BUILDFLAG(IS_ANDROID)
+  if (!use_download_collection) {
+    // Create a file at |path|.
+    ASSERT_TRUE(base::WriteFile(path, ""));
+  }
+  ASSERT_TRUE(IsPathInUse(path));
+
+  CreateReservation(item.get(), target_path,
+                    DownloadPathReservationTracker::OVERWRITE,
+                    PathValidationResult::SUCCESS, target_path);
+
+  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
+  item.reset();
+  RunUntilIdle();
+}
+
 // If the source is a file:// URL that is in the download directory, then Chrome
 // could download the file onto itself. Test that this is flagged by DPRT.
 TEST_F(DownloadPathReservationTrackerTest, ConflictWithSource) {
@@ -369,6 +442,37 @@
   RunUntilIdle();
 }
 
+// As above, but check for a file:// URL that differs only by case. This should
+// be flagged on all file systems, even case-sensitive ones, for safety.
+TEST_F(DownloadPathReservationTrackerTest, CaseConflictWithSource) {
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
+  base::FilePath path(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
+  base::FilePath target_path(
+      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("FOO.txt")));
+  bool use_download_collection = false;
+#if BUILDFLAG(IS_ANDROID)
+  if (DownloadCollectionBridge::ShouldPublishDownload(path)) {
+    use_download_collection = true;
+    DownloadCollectionBridge::AddExistingFileNameForTesting(path.BaseName());
+  }
+#endif  // BUILDFLAG(IS_ANDROID)
+  if (!use_download_collection) {
+    ASSERT_TRUE(base::WriteFile(path, ""));
+  }
+  ASSERT_TRUE(IsPathInUse(path));
+  EXPECT_CALL(*item, GetURL())
+      .WillRepeatedly(ReturnRefOfCopy(net::FilePathToFileURL(path)));
+
+  CreateReservation(item.get(), target_path,
+                    DownloadPathReservationTracker::UNIQUIFY,
+                    PathValidationResult::SAME_AS_SOURCE, target_path);
+
+  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
+  item.reset();
+  RunUntilIdle();
+}
+
 // Multiple reservations for the same path should uniquify around each other.
 TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) {
   std::unique_ptr<MockDownloadItem> item1 = CreateDownloadItem(1);
Loading diff…

Original Bug Report

reported by [email protected]

Potential MotW bypass via case-sensitive path comparison

Flapjack, 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 security team.

Overview: A potential Mark-of-the-Web (MotW) bypass exists because DownloadPathReservationTracker uses case-sensitive path comparisons on case-insensitive filesystems. An attacker can use a mismatched-case file:// URL to bypass the self-download block and strip the MotW. This results in a copied executable lacking Gatekeeper or SmartScreen protections.

Affected files:

  • components/download/internal/common/download_path_reservation_tracker.cc

Estimated timestamp from git blame: 2021-10-21

Vulnerability Summary

A potential Mark-of-the-Web (MotW) bypass exists in DownloadPathReservationTracker::ValidatePathAndResolveConflicts. By exploiting a case mismatch on a case-insensitive filesystem (such as macOS APFS/HFS+ or Windows NTFS), an attacker can bypass the security check designed to prevent a file from being downloaded onto itself. This results in the creation of a duplicate file with its internet MotW stripped.

Technical Details

When reserving a download path, Chrome attempts to prevent MotW stripping by blocking downloads where the source and target paths are identical:

// components/download/internal/common/download_path_reservation_tracker.cc
if (*target_path == info.source_path)
  return PathValidationResult::SAME_AS_SOURCE;

The vulnerability occurs because base::FilePath::operator== performs a strict, case-sensitive string comparison on macOS (and for path bodies on Windows). However, the underlying filesystems on these operating systems are typically case-insensitive.

If a download is initiated from a file:// URL where the path case is artificially altered (e.g., PAYLOAD.EXE instead of payload.exe), the *target_path == info.source_path check evaluates to false.

Standard processing then continues: IsPathInUse correctly detects the file’s existence on disk (as base::PathExists relies on the case-insensitive OS API), and Chrome resolves this “conflict” by uniquifying the target filename (e.g., payload (1).exe).

Because the source scheme is file://, Chrome’s quarantine service (e.g., in quarantine_mac.mm) applies a local attribute such as kLSQuarantineTypeOtherDownload rather than kLSQuarantineTypeWebDownload. The resulting copy is treated as a locally sourced file, effectively stripping the restrictive internet MotW.

Potential Exploitation Steps

Note: These are suggested steps based on static code analysis; our tooling agent does not execute live proof-of-concept code to verify.

  1. A victim downloads a malicious file (e.g., payload.exe) to their Downloads folder, which correctly receives an internet MotW from the OS.
  2. The victim opens a locally saved attacker HTML file (file:// origin), which has the necessary privileges to request other file:// URLs.
  3. The HTML file triggers a programmatic download of the payload using an altered-case source URL but a normal-case target: <a href="file:///Users/user/Downloads/PAYLOAD.EXE" download="payload.exe">.
  4. The SAME_AS_SOURCE check is bypassed due to the case-sensitive string comparison in Chrome.
  5. Chrome creates a copy of the payload (e.g., payload (1).exe) and assigns it a local quarantine attribute.
  6. The new copy can be executed by the user without triggering Gatekeeper or SmartScreen internet-download warnings.

Suggested Fix

Path equality checks in ValidatePathAndResolveConflicts should account for the case sensitivity of the underlying filesystem. Use a case-insensitive comparison like base::FilePath::CompareEqualIgnoreCase on affected platforms, or preferably, compare the underlying filesystem identity (e.g., checking device and inode numbers) to robustly verify if the source and target represent the exact same physical file.

Evaluated with Chrome root at commit: 09ec9e7cc4d24823d20b6d37cf3d282734f6bf0f


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