ClawdBot VS Code Trojan Analysis and OpenClaw Security Risks March 6, 2026 March 19, 2026 Contributors: Sandeep Kamble, BugDazz Autonomous Pentest AI, Rabit0 Model Publication Date: March 19, 2026 Severity Rating: Critical (CVSS Score: 8.8) Vulnerability Status: Zero-day at time of discovery A financial services firm was two weeks from go-live on an internal AI assistant. The stack was Spring AI with MariaDB as the vector store, a RAG pipeline over policy and compliance documents, and a chat interface for employees. Access control was done through metadata filters on the vector store — an HR analyst should only retrieve documents tagged `department: HR`, not `Finance` or `Legal`. We were brought in for a pre-production security review. Before starting the manual audit, we ran Bugdazz — our autonomous pentest AI built on the Rabit0 model — against the Spring AI source and the customer’s integration code. Rabit0 does taint analysis: it traces user-controlled input from entry points through transformations to database or command sinks, looking for paths where sanitization is absent or incomplete. It doesn’t match signatures — it reads the code and reasons about what reaches what. First pass. It flagged `MariaDBFilterExpressionConverter` with: “String values are quoted but not escaped before SQL insertion. Injection likely if filter values come from user input.” We took it from there. Table of Contents Toggle Executive Summary Before diving into exploitation mechanics and mitigation steps, it’s important to understand the basic profile of the vulnerability. Here is a brief snapshot: CVE ID: CVE-2026-22730 Severity: High (CVSS 8.8 – SQL Injection) Affected Versions: Spring AI 1.0.x versions prior to 1.0.4 and 1.1.x versions prior to 1.1.3 Fixed Versions: Spring AI 1.0.4 and 1.1.3 (or later) Attack Vector: SQL Injection via improper handling of string values in filter expressions, where user-controlled input is directly embedded into SQL queries without escaping Privileges Required: Low (authenticated user capable of supplying filter input) User Interaction: None (exploitation possible via crafted HTTP requests) Impact: Access control bypass leading to unauthorized data retrieval across restricted datasets, exposure of sensitive information, and potential full data deletion causing service disruption The Vulnerable Code `MariaDBFilterExpressionConverter` converts Spring AI’s `Filter.Expression` AST — the structured representation of a filter like `department == ‘Finance’` — into a SQL predicate string. The class that does this lives at: vector-stores/spring-ai-mariadb-store/src/main/java/org/springframework/ ai/vectorstore/mariadb/MariaDBFilterExpressionConverter.java The method responsible for serializing string values into SQL, at line 49: </> java @Override protected void doSingleValue(Object value, StringBuilder context) { if (value instanceof String) { context.append(String.format("'%s'", value)); // no escaping } else { context.append(value); } } String values are wrapped in single quotes via `String.format(“‘%s'”, value)` and appended directly. No escaping of `’`, no escaping of `\`, nothing. If the value contains a single quote, the SQL string literal terminates at that character and whatever follows is parsed as raw SQL. This output then feeds into two places in `MariaDBVectorStore.java`. Two Injection Points 1. Similarity search — line 355 </> java String nativeFilterExpression = this.filterExpressionConverter .convertExpression(request.getFilterExpression()); if (StringUtils.hasText(nativeFilterExpression)) { jsonPathFilter = "and " + nativeFilterExpression + " "; } final String sql = String.format( "SELECT * FROM (select %s, %s, %s, vec_distance_%s(%s, ?) as distance " + "from %s) as t where distance < ? %sorder by distance asc LIMIT ?", this.idFieldName, this.contentFieldName, this.metadataFieldName, distanceType, this.embeddingFieldName, getFullyQualifiedTableName(), jsonPathFilter); The `?` placeholders bind the embedding vector and distance threshold. The filter expression — `jsonPathFilter` — is placed via `String.format`, outside of parameterized binding entirely. 2. Filter-based delete — line 329 </> java @Override protected void doDelete(Filter.Expression filterExpression) { String nativeFilterExpression = this.filterExpressionConverter.convertExpression(filterExpression); String sql = String.format("DELETE FROM %s WHERE %s", getFullyQualifiedTableName(), nativeFilterExpression); this.jdbcTemplate.update(sql); } No parameterization anywhere. The entire `WHERE` clause is the converted expression, executed directly via `jdbcTemplate.update`. Proof of Concept We built a minimal reproduction: MariaDB 11.2 in Docker, a Spring Boot app replicating the vulnerable filter converter, three documents seeded with department metadata. </> sql INSERT INTO vector_store (id, content, metadata, embedding) VALUES ('1', 'HR Policy Document', '{"department": "HR", "accessLevel": "user"}', '[0.1, 0.2, 0.3]'), ('2'...
A critical SQL injection vulnerability (CVE-2026-22730, CVSS 8.8) exists in Spring AI's MariaDB vector store, where improper handling of string values in filter expressions allows authenticated users to bypass access controls and retrieve unauthorized data. Affected versions are Spring AI 1.0.x prior to 1.0.4 and 1.1.x prior to 1.1.3. The fix is applied in Spring AI versions 1.0.4 and 1.1.3.