CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-38CW-85XC-XR9X

Veramo ORM: Decentralized Identity, Centralized SQL Injection

Alon Barad
Alon Barad
Software Engineer

Feb 17, 2026·5 min read·32 visits

Executive Summary (TL;DR)

Critical SQL Injection in Veramo data store (< v6.0.2) allows attackers to dump the entire database—including private keys—by injecting malicious SQL into the 'order' parameter. Patch immediately.

Veramo, a popular framework for Decentralized Identifiers (DIDs) and Verifiable Credentials, shipped with a critical SQL injection vulnerability in its data store ORM. By manipulating the sorting parameters of a query, an unauthenticated attacker could bypass input sanitization and execute arbitrary SQL commands. This flaw allows for the complete exfiltration of the database, including the most sensitive asset in the ecosystem: the private keys used to sign credentials. The irony of a 'self-sovereign' identity system losing its sovereignty to a 1990s-style attack vector is palpable.

The Hook: Your Keys, My Database

Veramo is the Swiss Army knife for the decentralized web. It promises 'Self-Sovereign Identity' (SSI)—the idea that you, and only you, control your digital identity through cryptographic keys and Verifiable Credentials. It's a noble goal, built on complex standards like DIDs (Decentralized Identifiers). But as with all complex cryptographic castles, the drawbridge is usually built by a sleep-deprived developer using an ORM.

In this specific case, the vulnerability isn't in the fancy cryptography. It's in the boring, mundane layer that stores data. The @veramo/data-store package handles saving and retrieving claims, identifiers, and credentials. It wraps TypeORM to make life easier for developers.

Unfortunately, in versions prior to 6.0.2, it made life significantly easier for hackers too. By failing to validate input in the query builder, Veramo inadvertently turned its database into a public library where the 'fiction' section contains your private keys.

The Flaw: Trusting the Sort Order

The root cause is a classic failure to sanitize inputs passed to a Query Builder. Modern ORMs like TypeORM are generally good at preventing SQL injection if you use them correctly. They automatically parameterize values in where clauses. However, they often trust developers to handle structural elements—like column names and aliases—responsibly.

In Veramo's DataStoreORM, specifically within the decorateQB() function, the code accepted a user-controlled order array. This array dictates how results are sorted. The application took the column property from this user input and plugged it directly into the query as an alias or an orderBy target.

Because the input wasn't whitelisted against actual table columns, the database engine treated the injected string as part of the SQL structure. This isn't just a 'syntax error' waiting to happen; it's a full breakout. The code effectively said, 'I trust the user to tell me which column to sort by,' without realizing the user might want to sort by "some_column" UNION ALL SELECT private_key....

The Code: The Smoking Gun

Let's look at the breakdown. The vulnerability stems from how the order loop handled column names. It blindly trusted item.column.

The Vulnerable Logic (Conceptual):

// Inside decorateQB()
if (args.order) {
  args.order.forEach((item) => {
    // DANGEROUS: item.column is injected directly into the query builder
    qb.addSelect(item.column, 'alias_name');
    qb.addOrderBy('alias_name', item.direction);
  });
}

The Fix (Commit 067e39dd76f11ee2d25b99c8361d4f02a4223e3b):

The maintainers introduced a strict allowlist. Instead of trusting the input, they now verify that the requested column actually exists in a hardcoded ALLOWED_COLUMNS list.

// The Remediation
const ALLOWED_COLUMNS = ['issuer', 'subject', 'issuanceDate', ...];
 
if (args.order) {
  args.order.forEach((item) => {
    // Check if the column is in the allowlist
    if (!ALLOWED_COLUMNS.includes(item.column)) {
      throw new Error(`Invalid column name: ${item.column}`);
    }
    // Safe to proceed
    qb.addOrderBy(item.column, item.direction);
  });
}

This is the difference between a secure application and a leaky sieve. By enforcing an allowlist, the attack surface for this vector drops to zero.

The Exploit: Stealing the Crown Jewels

How bad can a sorting bug be? Fatal. The proof-of-concept payload provided in the disclosure demonstrates a sophisticated UNION-based injection. The attacker crafts a payload that breaks out of the addSelect or orderBy context, closes the previous query logic, and appends a UNION ALL SELECT to retrieve data from the private-key table.

The Payload:

{
  "order": [
    {
      "direction": "ASC",
      "column": "issuanceDate\" AS \"issuanceDate\" FROM \"claim\" \"claim\" LEFT JOIN ... WHERE 1=0 UNION ALL SELECT ..., (SELECT json_object('privateKeyHex', privateKeyHex) ), ... FROM `private-key`-- -"
    }
  ]
}

Breakdown of the Attack:

  1. Breakout: The quote " after issuanceDate closes the identifier context.
  2. Logic Reset: The attacker reconstructs the necessary FROM and JOIN clauses to satisfy the original query structure, then adds WHERE 1=0 to ensure the original query returns nothing.
  3. The Heist: The UNION ALL SELECT appends the results of the attacker's query. In this case, they are selecting the privateKeyHex from the private-key table.
  4. Formatting: They use json_object to format the stolen key nicely within the result set structure expected by the application.
  5. Cleanup: The comment sequence -- - comments out the rest of the original query to prevent syntax errors.

The result? The API returns a list of 'claims' that are actually the server's private keys.

The Impact: Identity Theft at Scale

In a centralized system, a database breach is bad. In a decentralized identity system, it's existential. The Veramo agent often acts as a custodian for DIDs. If an attacker extracts the private keys:

  1. Impersonation: They can sign Verifiable Credentials as the issuer. If the issuer is a bank or a government agency, the attacker can mint fake IDs, fake loan approvals, or fake diplomas.
  2. Revocation Authority: They can revoke legitimate credentials, effectively deleting a user's digital existence.
  3. Permanent Compromise: Unlike a password, you can't just 'reset' a private key associated with an immutable DID on a blockchain. The DID itself is burned. The reputation attached to it is destroyed.

This vulnerability scores a near-perfect severity because it allows unauthenticated remote attackers to completely undermine the trust model of the entire system.

The Fix: Upgrade or Die

There is no fancy workaround here. You cannot WAF your way out of this reliably because the injection happens inside a complex JSON object structure that might look legitimate to generic filters.

Action Plan:

  1. Update Immediately: Upgrade @veramo/data-store and @veramo/data-store-json to version 6.0.2 or higher.
  2. Rotate Keys: If you were running a vulnerable version on a public-facing endpoint, you must assume your keys are compromised. Rotate your DIDs and revocation registries. Yes, it's painful. No, you don't have a choice.
  3. Audit Logs: Check your database logs for UNION statements or weird syntax errors involving the private-key table. If you see them, you've been hit.

Official Patches

VeramoVeramo v6.0.2 Release Notes

Fix Analysis (1)

Technical Appendix

CVSS Score
9.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
0.04%
Top 100% most exploited

Affected Systems

@veramo/data-store@veramo/data-store-jsonVeramo Agents utilizing SQL or JSON file databases

Affected Versions Detail

Product
Affected Versions
Fixed Version
@veramo/data-store
Veramo
< 6.0.26.0.2
@veramo/data-store-json
Veramo
< 6.0.26.0.2
AttributeDetail
Vulnerability IDGHSA-38cw-85xc-xr9x
CWECWE-89 (SQL Injection)
CVSS9.8 (Critical)
Attack VectorNetwork
ImpactData Exfiltration (Private Keys)
Patch Commit067e39dd76f11ee2d25b99c8361d4f02a4223e3b

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059.006Command and Scripting Interpreter: Python/SQL
Execution
T1555Credentials from Password Stores
Credential Access
CWE-89
SQL Injection

Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

Known Exploits & Detection

GitHub AdvisoryProof of Concept demonstrating extraction of private keys via UNION SELECT
NucleiDetection Template Available

Vulnerability Timeline

Patch Committed (v6.0.2)
2026-01-16
Advisory Published
2026-01-16

References & Sources

  • [1]GitHub Advisory GHSA-38cw-85xc-xr9x
  • [2]Veramo Documentation

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 11 hours ago•GHSA-7PPR-R889-MCF2
7.5

GHSA-7PPR-R889-MCF2: Unbounded WebSocket Message Aggregation in http4s-blaze-server leads to Denial of Service

An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.

Alon Barad
Alon Barad
6 views•5 min read
•about 12 hours ago•GHSA-95CV-R8X4-VH75
7.6

GHSA-95cv-r8x4-vh75: Path Traversal Vulnerability in OpenList Batch Rename Handler

A critical path traversal vulnerability has been identified in the OpenList Go-based backend package. The vulnerability exists within the batch rename handler because the application does not validate the source filename parameter before constructing filesystems paths. This omission allows authenticated users to escape their designated directory and rename files in sibling paths.

Amit Schendel
Amit Schendel
7 views•7 min read
•about 13 hours ago•GHSA-P6PH-3JX2-3337
4.3

GHSA-P6PH-3JX2-3337: Horizontal Privilege Escalation and Metadata Information Disclosure via Bleve Search in OpenList

OpenList version 4.2.3 and prior is vulnerable to an authorization bypass and metadata leakage. When configured with the Bleve search engine backend, OpenList fails to perform separator-aware path matching when validating tenant containment. This allows authenticated users to access sibling directories sharing similar name prefixes. Furthermore, the search backend returns unfiltered global result counts, leaking existence verification data of unauthorized files via side-channel analysis.

Amit Schendel
Amit Schendel
7 views•5 min read
•about 14 hours ago•GHSA-86CX-WWF4-PHQ4
6.5

GHSA-86cx-wwf4-phq4: Path Prefix Confusion Authorization Bypass in OpenList

An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.

Amit Schendel
Amit Schendel
6 views•6 min read
•about 15 hours ago•CVE-2026-16584
7.0

CVE-2026-16584: Security Policy Bypass in AWS API MCP Server via Startup Initialization Failure

A security policy bypass vulnerability exists in the AWS API MCP Server (awslabs-aws-api-mcp-server) from version 0.2.13 through 1.3.46. When the server fails to load the read-only operations index during startup (due to transient network failures, file permission issues, or other exceptions), it logs a warning but continues running in an insecure, degraded state. Under this condition, the security policy engine fails open, silently skipping all subsequent security checks and consent prompts for the lifetime of the process. This permits unauthorized mutating AWS CLI commands to execute via indirect prompt injection attacks.

Amit Schendel
Amit Schendel
7 views•7 min read
•about 16 hours ago•GHSA-6V4M-FW66-8R4X
6.5

GHSA-6V4M-FW66-8R4X: Path Disclosure and Shell Expansion Bypass in Shescape

An incomplete escaping vulnerability in the npm package 'shescape' allows unauthenticated users to trigger dynamic shell expansions, absolute path disclosure, and command block break-outs on Unix and Windows systems.

Alon Barad
Alon Barad
6 views•7 min read