High watch CVSS 9.6 chrome UAF 📄 Reporter bug report 🔧 Commit mapped

Overview

High
Severity
9.6
CVSS
No
Exploited ITW
Fixed
Fix Status
ImpactUse after free in ANGLE
DescriptionUse after free in ANGLE
ComponentANGLE
Sub-componentVulkan
Bug ClassUAF
Action tierwatch — corruption primitive but gated (uncommon) — not default-reachable
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.
Tracker536636648
Fix commitf56a8e4f5f28 (angle/angle) +51/-2
CWECWE-416 (Use-after-free)
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H
CISA KEVNot listed
CreditedGoogle
Reported2026-07-19 (per vendor advisory)
Fix landed2026-07-22 (public git)
Disclosed2026-08-25
Patch gap34 days — fix public in source before the advisory

Background

`DescriptorPoolHelper`
an ANGLE Vulkan-backend object that owns a VkDescriptorPool plus lists of released descriptor sets awaiting reuse or destruction.
`mPendingGarbageList` / `mFinishedGarbageList`
queues of released descriptor sets: pending garbage is still tagged with a ResourceUse/queue serial not yet known to have completed on the GPU, while finished garbage is safe to recycle or destroy.
`ResourceUse` / `QueueSerial`
a tag recording the GPU submission that must complete before a resource may be freed; garbage is only reclaimed once its serial is reached.
WeakPtr upgrade
obtaining a usable pointer to a descriptor set from a weak reference; if the object was already freed, the upgrade dereferences freed memory.

Root Cause Analysis

DynamicDescriptorPool’s destroy path iterated its mDescriptorPools and called pool->cleanupPendingGarbage(), which only reclaims garbage whose queue serial has been observed as finished. When a context hit an error during submission and took an early-out path, the released descriptor sets retained an unsubmitted ResourceUse whose serial would never be reached, so cleanupPendingGarbage left those entries on mPendingGarbageList. The pool was then torn down while descriptor sets were still pending, so a later unsafe WeakPtr upgrade to those descriptor sets (per the commit title) dereferenced memory that had been freed, a use-after-free at context destruction.

The fix adds DescriptorPoolHelper::forceFinishPendingGarbage, which unconditionally moves every entry from mPendingGarbageList to mFinishedGarbageList, and the destroy loop now calls it before pool->destroyGarbage() so no garbage lingers past pool teardown. The commit notes this is a no-op for normal runs where submission completed successfully.

Key insight
Teardown relied on GPU queue serials that never complete after a failed/early-out submission, so pending garbage (and the descriptor sets it referenced) survived pool destruction; force-finishing all pending garbage before destroyGarbage removes the dangling reference that a later WeakPtr upgrade would resurrect.

Attack Path

  1. Provoke a submission error Drive the Vulkan backend into an error during command submission so the context takes its early-out path (specific trigger not shown in the diff, inferred).
  2. Leave garbage pending The early-out leaves released descriptor sets on mPendingGarbageList tagged with an unsubmitted ResourceUse whose serial is never reached.
  3. Destroy the context DynamicDescriptorPool::destroy runs; pre-patch, cleanupPendingGarbage skips the still-pending entries and the pool is freed with references outstanding.
  4. Dangling access A later unsafe WeakPtr upgrade to a freed descriptor set dereferences freed memory, the use-after-free (inferred exploitation of the freed object).

Impact Assessment

An attacker able to induce a Vulkan submission-error path can cause a use-after-free of descriptor-set objects in the GPU process at context destruction. The precondition is reaching the error/early-out submission path with descriptor-set garbage still pending. The vendor advisory rates this high severity and does not report in-the-wild exploitation; NVD scores it CVSS 9.6. Any escalation beyond the UAF is not demonstrated by the patch.

Files Changed

  • src/libANGLE/renderer/vulkan/vk_helpers.h
  • src/tests/gl_tests/VulkanDescriptorSetTest.cpp
  • src/libANGLE/renderer/vulkan/vk_helpers.cpp

Audit Directions

  • Serial-gated cleanup on teardown
    Review any destructor or destroy path that reclaims GPU resources only when a queue serial has completed, since a never-completing serial strands the resource.
  • Error / early-out submission paths
    Audit submission code that bails out early for resources left tagged with an unsubmitted ResourceUse.
  • WeakPtr upgrades to GPU-lifetime objects
    Check every WeakPtr upgrade of descriptor sets and similar objects to confirm the target cannot have been freed while the weak reference persisted.
From f56a8e4f5f2852b9f58bbe1a9e79414b5246640c Mon Sep 17 00:00:00 2001
From: Charlie Lao <[email protected]>
Date: Tue, 21 Jul 2026 15:17:29 -0700
Subject: [PATCH] Vulkan: Fix UAF in DescriptorPoolHelper via unsafe WeakPtr upgrade

When context runs into error during submission, we may bail out early,
leaving some DescriptorSetHelpers has unsubmitted ResourceUse. This
cause potential UAF later on when context is destroyed. This CL prevents
such UAF possibility by force finish
DescriptorPoolHelper::mPendingGarbageList. This should have no behavior
change during normal context runs where submission went through
successfully.

Bug: b/536636648
Change-Id: I608ed2e61796aefc86d1a806472cfd70c2b8c719
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/8127746
Commit-Queue: Charlie Lao <[email protected]>
Reviewed-by: Shahbaz Youssefi <[email protected]>
Reviewed-by: Yuxin Hu <[email protected]>
---
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
index c80590c..afb5746 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
@@ -3678,6 +3678,15 @@
     }
 }
 
+void DescriptorPoolHelper::forceFinishPendingGarbage()
+{
+    while (!mPendingGarbageList.empty())
+    {
+        mFinishedGarbageList.push_back(std::move(mPendingGarbageList.front()));
+        mPendingGarbageList.pop_front();
+    }
+}
+
 bool DescriptorPoolHelper::recycleFromGarbage(Renderer *renderer,
                                               DescriptorSetPointer *descriptorSetOut)
 {
@@ -3800,7 +3809,11 @@
 
     for (DescriptorPoolPointer &pool : mDescriptorPools)
     {
-        pool->cleanupPendingGarbage();
+        // Usually all pending garbage should have been finished when DynamicDescriptorPool is
+        // destroyed. But when context runs into error and submit code path early out, we could have
+        // unfinished garbage in the pending list. So force all pending garbage to be cleared rather
+        // than being left in place until the pool itself is deleted.
+        pool->forceFinishPendingGarbage();
         pool->destroyGarbage();
         ASSERT(pool.unique());
     }
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.h b/src/libANGLE/renderer/vulkan/vk_helpers.h
index b92f33d..fce9a22 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.h
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.h
@@ -296,6 +296,7 @@
     bool recycleFromGarbage(Renderer *renderer, DescriptorSetPointer *descriptorSetOut);
     void destroyGarbage();
     void cleanupPendingGarbage();
+    void forceFinishPendingGarbage();
 
     bool hasValidDescriptorSet() const { return mValidDescriptorSets != 0; }
     bool canDestroy() const { return mValidDescriptorSets == 0 && mPendingGarbageList.empty(); }
diff --git a/src/tests/gl_tests/VulkanDescriptorSetTest.cpp b/src/tests/gl_tests/VulkanDescriptorSetTest.cpp
index 72a57ca..af9adaf 100644
--- a/src/tests/gl_tests/VulkanDescriptorSetTest.cpp
+++ b/src/tests/gl_tests/VulkanDescriptorSetTest.cpp
@@ -208,8 +208,43 @@
     mDescriptorSetLayoutCache.destroy(contextVk->getRenderer());
 }
 
+// Verify that DynamicDescriptorPool::destroy tears down cleanly even when descriptor sets that
+// were returned to the pool are still tagged with an outstanding queue serial.
+TEST_P(VulkanDescriptorSetLayoutDescTest, DestroyWithPendingGarbage)
+{
+    rx::ContextVk *contextVk = hackANGLE();
+
+    rx::vk::DescriptorSetLayoutDesc desc;
+    addBindings({0}, &desc);
+
+    rx::vk::DescriptorSetLayoutPtr descriptorSetLayout;
+    angle::Result result =
+        mDescriptorSetLayoutCache.getDescriptorSetLayout(contextVk, desc, &descriptorSetLayout);
+    ASSERT_EQ(result, angle::Result::Continue);
+
+    VkDescriptorPoolSize poolSize = {VK_DESCRIPTOR_TYPE_SAMPLER, 1};
+    rx::vk::DynamicDescriptorPool dynamicPool;
+    result = dynamicPool.init(contextVk, &poolSize, 1, *descriptorSetLayout);
+    ASSERT_EQ(result, angle::Result::Continue);
+
+    rx::vk::DescriptorSetPointer descriptorSet;
+    result = dynamicPool.allocateDescriptorSet(contextVk, *descriptorSetLayout, &descriptorSet);
+    ASSERT_EQ(result, angle::Result::Continue);
+    ASSERT_TRUE(descriptorSet);
+
+    // Tag the descriptor set with a queue serial that has not been reached so that it stays on the
+    // pool's pending garbage list once released.
+    descriptorSet->setQueueSerial(rx::QueueSerial(0, rx::Serial::Infinite()));
+    descriptorSet.reset();
+
+    dynamicPool.destroy(contextVk->getDevice());
+
+    descriptorSetLayout.reset();
+    mDescriptorSetLayoutCache.destroy(contextVk->getRenderer());
+}
+
 ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetTest, ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER());
-ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetLayoutDescTest, ES31_VULKAN());
+ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetLayoutDescTest, ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER());
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanDescriptorSetLayoutDescTest);
 
 }  // namespace
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/src/tests/gl_tests/VulkanDescriptorSetTest.cpp b/src/tests/gl_tests/VulkanDescriptorSetTest.cpp
index 72a57ca..af9adaf 100644
--- a/src/tests/gl_tests/VulkanDescriptorSetTest.cpp
+++ b/src/tests/gl_tests/VulkanDescriptorSetTest.cpp
@@ -208,8 +208,43 @@
     mDescriptorSetLayoutCache.destroy(contextVk->getRenderer());
 }
 
+// Verify that DynamicDescriptorPool::destroy tears down cleanly even when descriptor sets that
+// were returned to the pool are still tagged with an outstanding queue serial.
+TEST_P(VulkanDescriptorSetLayoutDescTest, DestroyWithPendingGarbage)
+{
+    rx::ContextVk *contextVk = hackANGLE();
+
+    rx::vk::DescriptorSetLayoutDesc desc;
+    addBindings({0}, &desc);
+
+    rx::vk::DescriptorSetLayoutPtr descriptorSetLayout;
+    angle::Result result =
+        mDescriptorSetLayoutCache.getDescriptorSetLayout(contextVk, desc, &descriptorSetLayout);
+    ASSERT_EQ(result, angle::Result::Continue);
+
+    VkDescriptorPoolSize poolSize = {VK_DESCRIPTOR_TYPE_SAMPLER, 1};
+    rx::vk::DynamicDescriptorPool dynamicPool;
+    result = dynamicPool.init(contextVk, &poolSize, 1, *descriptorSetLayout);
+    ASSERT_EQ(result, angle::Result::Continue);
+
+    rx::vk::DescriptorSetPointer descriptorSet;
+    result = dynamicPool.allocateDescriptorSet(contextVk, *descriptorSetLayout, &descriptorSet);
+    ASSERT_EQ(result, angle::Result::Continue);
+    ASSERT_TRUE(descriptorSet);
+
+    // Tag the descriptor set with a queue serial that has not been reached so that it stays on the
+    // pool's pending garbage list once released.
+    descriptorSet->setQueueSerial(rx::QueueSerial(0, rx::Serial::Infinite()));
+    descriptorSet.reset();
+
+    dynamicPool.destroy(contextVk->getDevice());
+
+    descriptorSetLayout.reset();
+    mDescriptorSetLayoutCache.destroy(contextVk->getRenderer());
+}
+
 ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetTest, ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER());
-ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetLayoutDescTest, ES31_VULKAN());
+ANGLE_INSTANTIATE_TEST(VulkanDescriptorSetLayoutDescTest, ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER());
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanDescriptorSetLayoutDescTest);
 
 }  // namespace
Loading diff…

Original Bug Report

reported by [email protected]

Potential GPU-HOST UAF/double-free in ANGLE DescriptorPoolHelper via unsafe WeakPtr upgrade

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. Please see https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.

Overview: A potential re-entrant double-free vulnerability exists in the ANGLE Vulkan backend’s descriptor set pool management. When a context is destroyed following a failed command submission, an unsafe WeakPtr-to-SharedPtr upgrade resurrects a parent allocation mid-delete. This results in a Use-After-Free write and a double-free on the host heap within the GPU process.

Affected files:

  • third_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.cpp
  • third_party/angle/src/libANGLE/renderer/vulkan/vk_utils.h

Estimated timestamp from git blame: 2024-12-02

1. Summary of the Issue (Meant for Human Triage)

A potential severe memory-safety vulnerability exists in the ANGLE Vulkan backend due to unsafe object lifetime management and the lack of release-build validation checks when upgrading weak pointers. Specifically, DescriptorSetHelper::destroy() upgrades a vk::WeakPtr<DescriptorPoolHelper> to a SharedPtr to return descriptor sets to the pool’s garbage list. In release builds, this upgrade lacks checks to verify if the underlying RefCounted object is currently being destroyed or has already been freed, as the assertIsReferenced() check compiles to a no-op.

Under certain conditions—such as context destruction following a failed vkQueueSubmit—a DynamicDescriptorPool will be cleared while still holding undrained pending garbage. This initiates a recursive destruction sequence: deleting the DescriptorPoolHelper calls the destructor on its std::deque of garbage items, which invokes DescriptorSetHelper::destroy(). This function resurrects the mid-destruction RefCounted<DescriptorPoolHelper> allocation (re-incrementing the refcount from 0 to 1), mutates the std::deque under active destruction, and subsequently invokes delete on the same RefCounted object a second time when the temporary SharedPtr goes out of scope.

The result is a re-entrant host-heap double-free / Use-After-Free (UAF) in the GPU process. Because ANGLE does not utilize MiraclePtr (BackupRefPtr) protection for these ref-counted structures, this heap corruption is exploitable. On platforms like Android where the GPU process is unsandboxed, this could lead to a browser-tier compromise.

Note: These steps are based on exhaustive static analysis of the codebase. Our tooling agent does not yet have the ability to run code to produce a live proof-of-concept.

2. Proof-of-Concept & Detailed Execution Flow

The potential vulnerability is triggered through the following sequence of events an attacker might control:

Step 1: Allocating Descriptor Sets with GPU Conversion A WebGL page issues draw calls that require vertex format conversion on the GPU (e.g., using gl.vertexAttribPointer with non-normalized gl.SHORT values).

  • VertexArrayVk::convertVertexBufferGPU -> UtilsVk::allocateDescriptorSetWithLayout (third_party/angle/src/libANGLE/renderer/vulkan/UtilsVk.cpp:5189).
  • commandBufferHelper->retainResource(descriptorSet.get()) stamps a DescriptorSetHelper with the current queue serial (e.g., N).
  • The local DescriptorSetPointer goes out of scope, calling DescriptorSetHelper::destroy(), which places it into the mPendingGarbageList of the pool via emplace_back.

Step 2: Inducing a Vulkan Submission Failure The attacker induces a GPU hang (via an expensive fragment shader) or exhausts Vulkan device memory, causing the next command buffer submission to fail.

Step 3: Incomplete Serial Tracking on Submit Failure During the context destruction (ContextVk::onDestroy in third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp:1250), finishImpl() attempts to submit pending command buffers.

  • vkQueueSubmit fails and returns VK_ERROR_DEVICE_LOST or VK_ERROR_OUT_OF_DEVICE_MEMORY inside CommandQueue::queueSubmitLocked (CommandQueue.cpp:1024).
  • Wrapped in ANGLE_VK_TRY, the error propagates immediately, skipping pushInFlightBatchLocked() at CommandQueue.cpp:1029.
  • The batch serial N never enters mInFlightCommands. When handleDeviceLost() executes, it only advances mLastCompletedSerials from the existing mInFlightCommands queue. Serial N is left uncompleted.

Step 4: Failure to Clear Pending Garbage on Teardown During teardown of DynamicDescriptorPool (vk_helpers.cpp:3793-3798):

for (DescriptorPoolPointer &pool : mDescriptorPools)
{
    pool->cleanupPendingGarbage();
    pool->destroyGarbage();
    ASSERT(pool.unique()); // Debug only
}
mDescriptorPools.clear();
  • pool->cleanupPendingGarbage() (vk_helpers.cpp:3659-3671) halts immediately because mRenderer->hasResourceUseFinished(garbage->getResourceUse()) evaluates to false for serial N.
  • pool->destroyGarbage() only flushes elements in mFinishedGarbageList.
  • The pending list remains fully intact. mDescriptorPools.clear() is called, releasing the last SharedPtr<DescriptorPoolHelper>.

Step 5: Re-entrant Destruction and Re-referencing

  • mDescriptorPools.clear() triggers ~SharedPtr() -> releaseRef() -> SafeDelete(mRefCounted) -> delete mRefCounted -> ~DescriptorPoolHelper -> ~std::deque<DescriptorSetPointer> (mPendingGarbageList).
  • While destructing the elements of mPendingGarbageList, ~SharedPtr<DescriptorSetHelper> runs, invoking DescriptorSetHelper::destroy(device) (vk_helpers.cpp:3560-3573):
void DescriptorSetHelper::destroy(VkDevice device)
{
    if (valid())
    {
        DescriptorPoolPointer pool(device, mPool);              // WeakPtr -> SharedPtr Upgrade!
        DescriptorSetPointer garbage(device, std::move(*this));
        pool->addPendingGarbage(std::move(garbage));            // Corrupts std::deque mid-destruction
        ASSERT(!valid());
    }
}
  • The constructor for upgrading WeakPtr to SharedPtr (vk_utils.h:854-864) runs:
SharedPtr(VkDevice device, const WeakPtr<T> &other)
    : mRefCounted(other.mRefCounted), mDevice(device)
{
    if (mRefCounted)
    {
        mRefCounted->assertIsReferenced(); // Maps to ASSERT(mRefCount != 0)
        mRefCounted->addRef();             // Resurrects mid-delete object!
    }
}
  • Critical Flaw: In Release builds, ASSERT expands to ANGLE_EAT_STREAM_PARAMETERS << !(condition). Because ANGLE_EAT_STREAM_PARAMETERS uses the compile-time constant ternary operator true ? static_cast<void>(0) : ... (third_party/angle/src/common/log_utils.h:260), the assertIsReferenced() check compiles out to zero instructions. The refcount is unconditionally incremented from 0 to 1 on a heap allocation currently executing its own delete operator.
  • pool->addPendingGarbage(...) invokes emplace_back on the mPendingGarbageList (std::deque), which is actively executing its own ~deque(), causing a UAF write.
  • Finally, when the local pool object goes out of scope at the end of DescriptorSetHelper::destroy(), ~SharedPtr() drops the refcount back to 0, executing SafeDelete(mRefCounted) for a second time. This nested delete on the same RefCounted object triggers a catastrophic double-free.

Suggested Fix:

  1. Modify DynamicDescriptorPool::destroy to unconditionally force-drain and clear mPendingGarbageList when tearing down, regardless of whether hasResourceUseFinished returns true (since the context is being destroyed).
  2. Alternatively, advance mLastCompletedSerials for dropped batches during vkQueueSubmit failures so that standard garbage collection processes them.
  3. Revisit the ANGLE WeakPtr implementation to include a distinct weak reference count or a validity boolean rather than relying entirely on a debug-only ASSERT to detect dead objects.

3. Technical Verification Details (Automated Audit Logs - Reviewers may skip this section)

> The vulnerability is a valid GPU-HOST-UAF (double-free) in the ANGLE Vulkan backend. The root cause is that DescriptorSetHelper::destroy() resurrects a DescriptorPoolHelper object during its own destruction by upgrading a WeakPtr to a SharedPtr (which lacks a runtime validity check in release builds). This path is reachable if a WebGL page issues a draw that requires format conversion and subsequently induces a vkQueueSubmit failure (e.g., via GPU hang or memory exhaustion). The failed batch’s queue serial is never pushed to mInFlightCommands, so handleDeviceLost() never marks it as completed. During ContextVk::onDestroy, the mPendingGarbageList fails to drain. When mDescriptorPools.clear() triggers delete on the pool’s RefCounted object, the undrained std::deque elements are destructed, calling DescriptorSetHelper::destroy(). This resurrects the mid-delete pool, calls emplace_back on the std::deque currently in its destructor (a heap UAF write), and upon the SharedPtr going out of scope, calls delete a second time on the same RefCounted object (double-free). > > ANGLE does not use MiraclePtr (BRP) for these ref-counted structures, so the UAF is unprotected. The Vulkan backend is default on Android, where the GPU process is UNSANDBOXED, meaning a memory corruption is treated as browser-tier. Per the severity guidelines, a GPU-process write primitive reachable by web content alone (A-SERVER) on an unsandboxed platform warrants Critical (S0). However, because triggering this requires inducing a device-lost or OOM condition and exploiting the issue during the teardown of the lost device before the GPU process is recycled, a -1 downgrade is applied for trigger complexity (similar to ‘Requiring browser shutdown’). Thus, the final severity is High (S1).

Automated Codebase Analysis Confirmations:

  • vkQueueSubmit Error Handling: Codebase investigator traced CommandQueue::queueSubmitLocked (CommandQueue.cpp:953-1035). The vkQueueSubmit call is wrapped in ANGLE_VK_TRY (vk_utils.h:1775-1784), which early-returns angle::Result::Stop on failure. The subsequent pushInFlightBatchLocked (line 1029) is permanently skipped.
  • Garbage Collection Halt: Codebase investigator traced DescriptorPoolHelper::cleanupPendingGarbage (vk_helpers.cpp:3664). It breaks the loop early if mRenderer->hasResourceUseFinished(garbage->getResourceUse()) is false, leaving the pending deque populated.
  • ASSERT compilation: Codebase investigator verified log_utils.h:260-271. When ANGLE_ENABLE_ASSERTS is disabled (Release config), ASSERT maps to ANGLE_EAT_STREAM_PARAMETERS, which utilizes true ? static_cast<void>(0) : .... The compiler completely optimizes away the condition. Therefore, mRefCounted->assertIsReferenced() inside the WeakPtr -> SharedPtr constructor (vk_utils.h:854) is definitively a no-op, permitting the 0->1 reference count increment on a deleted object.
  • MiraclePtr Status: ANGLE’s vk::WeakPtr and vk::SharedPtr internally utilize raw RefCountedStorage *mRefCounted and VkDevice mDevice fields, not raw_ptr. They fall outside the scope of PartitionAlloc’s BackupRefPtr protection.

Evaluated with Chrome root at commit: b96d2ec58f4f5f92b540a723966b199d6e9951b4


Results so far have been promising, but there can be wrong deductions. Feel free to adjust as follows:

  • If you are familiar with the severity guidelines, you may adjust the severity.
  • If this is a false positive, and there’s no work to be done, please close as WAI.
  • If there is work to do here but not a vulnerability, please change the issue type to Task/Bug/FR.

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