Every CVE Search/ Get API key

CVE-2026-49989

CrateDB's Blob HTTP handler bypasses authorization

7.1 HighFix available

CrateDB is a distributed SQL database. Prior to versions 6.2.8 and 6.3.2, any authenticated user can read or delete any blob whose SHA-1 digest they know, and can plant new blobs unconditionally, in any blob table, regardless of GRANTs. CrateDB has two ways to access blob storage: SQL (SELECT ... FROM blob.<table> and friends) and the blob HTTP API (GET|PUT|DELETE /_blobs/{table}/{digest}). The SQL path goes through AccessControl, which is what enforces privilege grants; that's why SELECT digest FROM blob.secret_blobs fails for a user who has no grants on the table. The HTTP path authenticates the request but never asks AccessControl whether the authenticated user is allowed to touch the table. So a user with no grants gets MissingPrivilegeException from SQL and 200 OK plus the blob bytes from GET /_blobs/secret_blobs/<digest>. Deployments that don't use BLOB TABLE are unaffected. Authentication itself still works; the bug is strictly that being authenticated as anyone is treated as sufficient for any blob op. Versions 6.2.8 and 6.3.2 fix the issue.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
Low
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
High
Availability
None

Exploit likelihood

0.47%Up 0.2 points since Aug 15, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.1

CrateDB's Blob HTTP handler bypasses authorization

CrateDB is a distributed SQL database. Prior to versions 6.2.8 and 6.3.2, any authenticated user can read or delete any blob whose SHA-1 digest they know, and can plant new blobs unconditionally, in any blob table, regardless of GRANTs. CrateDB has two ways to access blob storage: SQL (SELECT ... FROM blob.<table> and friends) and the blob HTTP API (GET|PUT|DELETE /_blobs/{table}/{digest}). The SQL path goes through AccessControl, which is what enforces privilege grants; that's why SELECT digest FROM blob.secret_blobs fails for a user who has no grants on the table. The HTTP path authenticates the request but never asks AccessControl whether the authenticated user is allowed to touch the table. So a user with no grants gets MissingPrivilegeException from SQL and 200 OK plus the blob bytes from GET /_blobs/secret_blobs/<digest>. Deployments that don't use BLOB TABLE are unaffected. Authentication itself still works; the bug is strictly that being authenticated as anyone is treated as sufficient for any blob op. Versions 6.2.8 and 6.3.2 fix the issue.

Record
CVE-2026-49989
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N
Weakness
CWE-863
Updated
2026-11-02
EUVDEUVD-2026-58717 7.1

CrateDB is a distributed SQL database. Prior to versions 6.2.8 and 6.3.2, any authenticated user can read or delete any blob whose SHA-1 digest they know, and can plant new blobs unconditionally, in any blob table, regardless of GRANTs. CrateDB has two ways to access blob storage: SQL (SELECT ... FROM blob.<table> and friends) and the blob HTTP API (GET|PUT|DELETE /_blobs/{table}/{digest}). The SQL path goes through AccessControl, which is what enforces privilege grants; that's why SELECT digest FROM blob.secret_blobs fails for a user who has no grants on the table. The HTTP path authenticates the request but never asks AccessControl whether the authenticated user is allowed to touch the table. So a user with no grants gets MissingPrivilegeException from SQL and 200 OK plus the blob bytes from GET /_blobs/secret_blobs/<digest>. Deployments that don't use BLOB TABLE are unaffected. Authentication itself still works; the bug is strictly that being authenticated as anyone is treated as sufficient for any blob op. Versions 6.2.8 and 6.3.2 fix the issue.

Record
EUVD-2026-58717
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-2xv8-gjwh-fv8p 0.0

CrateDB's Blob HTTP handler bypasses authorization

Component: io.crate.protocols.http.HttpBlobHandler Affected: verified against CrateDB 6.2.7 (latest at time of report; the bug has existed since the blob HTTP handler was introduced) Impact: any authenticated user can read or delete any blob whose SHA-1 digest they know, and can plant new blobs unconditionally, in any blob table, regardless of GRANTs.


Summary

CrateDB has two ways to access blob storage: SQL (SELECT ... FROM blob.<table> and friends) and the blob HTTP API (GET|PUT|DELETE /_blobs/{table}/{digest}). The SQL path goes through AccessControl, which is what enforces privilege grants; that's why SELECT digest FROM blob.secret_blobs fails for a user who has no grants on the table.

The HTTP path authenticates the request but never asks AccessControl whether the authenticated user is allowed to touch the table. So a user with no grants gets MissingPrivilegeException from SQL and 200 OK plus the blob bytes from GET /_blobs/secret_blobs/<digest>.

Where it lives

server/src/main/java/io/crate/protocols/http/HttpBlobHandler.java. The dispatcher:

// HttpBlobHandler.java:176
private void handleBlobRequest(@Nullable HttpContent content) throws IOException {
    if (possibleRedirect(index, digest)) {
        return;
    }

    if (method.equals(HttpMethod.GET)) {
        get(index, digest);
        reset();
    } else if (method.equals(HttpMethod.HEAD)) {
        head(index, digest);
    } else if (method.equals(HttpMethod.PUT)) {
        put(content, index, digest);
    } else if (method.equals(HttpMethod.DELETE)) {
        delete(index, digest);
    } else {
        simpleResponse(HttpResponseStatus.METHOD_NOT_ALLOWED);
    }
}

No AccessControl reference, no privilege check. Each branch goes straight to the relevant blob op (get/head/put/delete); for example:

// HttpBlobHandler.java:287
private void get(String index, final String digest) throws IOException {
    if (range != null) {
        partialContentResponse(index, digest);
    } else {
        fullContentResponse(index, digest);
    }
}

grep -n 'AccessControl\|ensureMaySee\|checkPermission' HttpBlobHandler.java returns nothing.

The APIs that should be called here, used by the SQL path before every statement is dispatched:

  • server/src/main/java/io/crate/auth/AccessControl.java (interface, declares ensureMayExecute(...) and ensureMaySee(...))
  • server/src/main/java/io/crate/auth/AccessControlImpl.java:133 (concrete impl)

Threat model

Unconditional in code, gated in practice by digest knowledge; CrateDB has no enumeration channel. HEAD /_blobs/<table>/<digest> is the existence oracle; candidate digests may come from side channels such as app metadata, logs, known-file probes.

| Capability | Needs digest? | Impact | |---|---|---| | Read or delete a blob | yes | High when digests leak, nil otherwise | | Plant new blobs (PUT) | no | Storage pollution; SHA-1 check blocks forging under a victim's digest |

Digest secrecy is not a documented security boundary.

Reproduction

End-to-end Docker PoC. Two users, one blob, both ingress paths exercised side by side.

./run.sh brings up a CrateDB container with HBA enabled, creates an admin (with ALL PRIVILEGES) and an unprivileged user (with no grants), uploads a blob as admin, then runs six steps:

  1. Admin uploads a blob via PUT /_blobs/.... Success (201).
  2. Admin reads via SQL. Success.
  3. Unprivileged user reads via SQL. Denied (correct, this is what we want).
  4. Unprivileged user reads via GET /_blobs/.... 200 OK plus the blob payload (the bug).
  5. Unprivileged user deletes via DELETE /_blobs/.... 204 No Content (the bug, again).
  6. Admin re-checks via SQL. Confirms the blob is gone, deleted by a user with zero grants.

Sample output from a real run:

=== Step 3: Unprivileged user CANNOT read via SQL (expected) ===
[PASS] Unprivileged user correctly denied SQL access
[INFO] Server…
Record
GHSA-2xv8-gjwh-fv8p
CVSS 3.1
0.0 NoneCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N
Weakness
CWE-863
Updated
2026-11-02
NVD 7.1

CrateDB is a distributed SQL database. Prior to versions 6.2.8 and 6.3.2, any authenticated user can read or delete any blob whose SHA-1 digest they know, and can plant new blobs unconditionally, in any blob table, regardless of GRANTs. CrateDB has two ways to access blob storage: SQL (SELECT ... FROM blob.<table> and friends) and the blob HTTP API (GET|PUT|DELETE /_blobs/{table}/{digest}). The SQL path goes through AccessControl, which is what enforces privilege grants; that's why SELECT digest FROM blob.secret_blobs fails for a user who has no grants on the table. The HTTP path authenticates the request but never asks AccessControl whether the authenticated user is allowed to touch the table. So a user with no grants gets MissingPrivilegeException from SQL and 200 OK plus the blob bytes from GET /_blobs/secret_blobs/<digest>. Deployments that don't use BLOB TABLE are unaffected. Authentication itself still works; the bug is strictly that being authenticated as anyone is treated as sufficient for any blob op. Versions 6.2.8 and 6.3.2 fix the issue.

Record
CVE-2026-49989
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Weakness
CWE-863
Updated
2026-11-02
OSV 7.1

CrateDB's Blob HTTP handler bypasses authorization

CrateDB is a distributed SQL database. Prior to versions 6.2.8 and 6.3.2, any authenticated user can read or delete any blob whose SHA-1 digest they know, and can plant new blobs unconditionally, in any blob table, regardless of GRANTs. CrateDB has two ways to access blob storage: SQL (SELECT ... FROM blob.<table> and friends) and the blob HTTP API (GET|PUT|DELETE /_blobs/{table}/{digest}). The SQL path goes through AccessControl, which is what enforces privilege grants; that's why SELECT digest FROM blob.secret_blobs fails for a user who has no grants on the table. The HTTP path authenticates the request but never asks AccessControl whether the authenticated user is allowed to touch the table. So a user with no grants gets MissingPrivilegeException from SQL and 200 OK plus the blob bytes from GET /_blobs/secret_blobs/<digest>. Deployments that don't use BLOB TABLE are unaffected. Authentication itself still works; the bug is strictly that being authenticated as anyone is treated as sufficient for any blob op. Versions 6.2.8 and 6.3.2 fix the issue.

Record
CVE-2026-49989
CVSS 4.0
7.1 HighCVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N
Weakness
CWE-863
Updated
2026-11-02
OSVGHSA-2xv8-gjwh-fv8p 0.0

CrateDB's Blob HTTP handler bypasses authorization

Component: io.crate.protocols.http.HttpBlobHandler Affected: verified against CrateDB 6.2.7 (latest at time of report; the bug has existed since the blob HTTP handler was introduced) Impact: any authenticated user can read or delete any blob whose SHA-1 digest they know, and can plant new blobs unconditionally, in any blob table, regardless of GRANTs.


Summary

CrateDB has two ways to access blob storage: SQL (SELECT ... FROM blob.<table> and friends) and the blob HTTP API (GET|PUT|DELETE /_blobs/{table}/{digest}). The SQL path goes through AccessControl, which is what enforces privilege grants; that's why SELECT digest FROM blob.secret_blobs fails for a user who has no grants on the table.

The HTTP path authenticates the request but never asks AccessControl whether the authenticated user is allowed to touch the table. So a user with no grants gets MissingPrivilegeException from SQL and 200 OK plus the blob bytes from GET /_blobs/secret_blobs/<digest>.

Where it lives

server/src/main/java/io/crate/protocols/http/HttpBlobHandler.java. The dispatcher:

// HttpBlobHandler.java:176
private void handleBlobRequest(@Nullable HttpContent content) throws IOException {
    if (possibleRedirect(index, digest)) {
        return;
    }

    if (method.equals(HttpMethod.GET)) {
        get(index, digest);
        reset();
    } else if (method.equals(HttpMethod.HEAD)) {
        head(index, digest);
    } else if (method.equals(HttpMethod.PUT)) {
        put(content, index, digest);
    } else if (method.equals(HttpMethod.DELETE)) {
        delete(index, digest);
    } else {
        simpleResponse(HttpResponseStatus.METHOD_NOT_ALLOWED);
    }
}

No AccessControl reference, no privilege check. Each branch goes straight to the relevant blob op (get/head/put/delete); for example:

// HttpBlobHandler.java:287
private void get(String index, final String digest) throws IOException {
    if (range != null) {
        partialContentResponse(index, digest);
    } else {
        fullContentResponse(index, digest);
    }
}

grep -n 'AccessControl\|ensureMaySee\|checkPermission' HttpBlobHandler.java returns nothing.

The APIs that should be called here, used by the SQL path before every statement is dispatched:

  • server/src/main/java/io/crate/auth/AccessControl.java (interface, declares ensureMayExecute(...) and ensureMaySee(...))
  • server/src/main/java/io/crate/auth/AccessControlImpl.java:133 (concrete impl)

Threat model

Unconditional in code, gated in practice by digest knowledge; CrateDB has no enumeration channel. HEAD /_blobs/<table>/<digest> is the existence oracle; candidate digests may come from side channels such as app metadata, logs, known-file probes.

| Capability | Needs digest? | Impact | |---|---|---| | Read or delete a blob | yes | High when digests leak, nil otherwise | | Plant new blobs (PUT) | no | Storage pollution; SHA-1 check blocks forging under a victim's digest |

Digest secrecy is not a documented security boundary.

Reproduction

End-to-end Docker PoC. Two users, one blob, both ingress paths exercised side by side.

./run.sh brings up a CrateDB container with HBA enabled, creates an admin (with ALL PRIVILEGES) and an unprivileged user (with no grants), uploads a blob as admin, then runs six steps:

  1. Admin uploads a blob via PUT /_blobs/.... Success (201).
  2. Admin reads via SQL. Success.
  3. Unprivileged user reads via SQL. Denied (correct, this is what we want).
  4. Unprivileged user reads via GET /_blobs/.... 200 OK plus the blob payload (the bug).
  5. Unprivileged user deletes via DELETE /_blobs/.... 204 No Content (the bug, again).
  6. Admin re-checks via SQL. Confirms the blob is gone, deleted by a user with zero grants.

Sample output from a real run:

=== Step 3: Unprivileged user CANNOT read via SQL (expected) ===
[PASS] Unprivileged user correctly denied SQL access
[INFO] Server…
Record
GHSA-2xv8-gjwh-fv8p
CVSS 3.1
0.0 NoneCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N
Weakness
CWE-863
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
io.crate:crate
Maven
before 6.2.8
6.2.8
io.crate:crate
Maven
6.3.0 up to 6.3.2
6.3.2

History

History
RecordedChangedSources
aliasesEUVD
first indexedCVE List, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-49989 is a high vulnerability (CVSS 7.1) in Crate, published July 1, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.47%, the 40th percentile. Fixed in io.crate:crate 6.2.8.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open