☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]
Twenty logo [ WEBSITE ] [ VENDOR STATS ]
CVSS: 9.1 CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H 🐛 CWE-89
👁️
Common Weakness Enumeration - Identifies the specific category of software weakness or flaw.

CVE-2026-73069

CVE-2026-73069 Vulnerability in Twenty
📅 PUBLISHED: 2026-08-11 00:00 UTC 🔄 UPDATED: 2026-09-23 19:42 UTC
[ PATCH UNDER REVIEW ↓ ] Remains UNDER REVIEW until an independent source confirms the fix
[ DEFENSE PATCH ↓ ]
💣 PoC: Public
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 0.45%
👁️
0.45% probability
11.2× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
🥷 MITRE: T1190
👁️
MITRE ATT&CK Tactic - Describes the strategy hackers use to execute this attack.
Country: France License: Open Source
VULNERABLE: version not auto-detected — verify your deployed version locally
CVSS VECTOR BREAKDOWN 9.1
AV: N Attack Vector Network
AC: L Attack Complexity Low
PR: H Privileges Required High
UI: N User Interaction None
S: C Scope Changed
C: H Confidentiality High
I: H Integrity High
A: H Availability High
9.1
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2026-73069 is a critical SQL injection vulnerability (CWE-89) in Twenty, an open-source CRM platform, affecting all versions prior to 2.15.0. A workspace administrator holding the DATA_MODEL permission can inject arbitrary PostgreSQL statements by supplying malicious input to the settings.asExpression parameter of the system TS_VECTOR field searchVector, leading to unescaped concatenation into a GENERATED ALWAYS AS (...) SQL clause. With a CVSS score of 9.1, successful exploitation allows full database compromise, including data exfiltration, modification, and potential lateral movement within the database environment, as the injected statements execute with the privileges of the application database user.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

Technical Analysis

The vulnerability resides in Twenty's ORM schema management layer. The NVD description identifies a specific code path in packages/twenty-server/src/engine/twenty-orm/workspace-schema-manager/utils/build-sql-column-definition.util.ts, where the function buildSqlColumnDefinition processes user-supplied expressions for computed column definitions. The affected field is the system TS_VECTOR column named searchVector, which is used for full-text search capabilities within the CRM.

The attack mechanism is a classic SQL injection (CWE-89) with a twist: instead of injecting into a WHERE clause or a standard SQL statement, the injection targets a PostgreSQL GENERATED ALWAYS AS (...) expression. In PostgreSQL, generated columns accept arbitrary expressions that are evaluated to compute the column's value. When Twenty generates the ALTER TABLE or CREATE TABLE statement to define or update this generated column, the settings.asExpression value is concatenated directly into the SQL string without proper escaping or parameterization.

The attack surface is exposed through two administrative API endpoints, both requiring an authenticated workspace administrator with the DATA_MODEL permission:

  1. PATCH /rest/metadata/fields/:id — a RESTful endpoint for updating field metadata
  2. updateOneField — an equivalent GraphQL mutation

When an administrator sends a request to either endpoint specifying the searchVector field's settings.asExpression, the value flows directly into the SQL generation logic. Because the expression is embedded into a GENERATED ALWAYS AS (...) clause rather than being executed as a prepared statement parameter, the attacker can terminate the expression and append arbitrary SQL statements. PostgreSQL allows multiple statements in a single ALTER TABLE command when separated by semicolons, enabling the attacker to execute completely independent SQL operations.

The database user context is critical: the injected code executes "as the application database user." In typical Twenty deployments, this user has broad privileges over the application database, including SELECT, INSERT, UPDATE, DELETE, and potentially DDL privileges (necessary for the ORM's schema management operations that the legitimate feature requires). The impact is further amplified by the CVSS vector indicating a scope change (S:C), meaning the compromise can extend beyond the immediate database to affect other resources accessible through the database user's permissions — potentially other databases, foreign data wrappers, or database-level security configurations.

Exploitation Scenarios

No public PoC is available; attack chain is inferred from the vulnerability class and NVD description.

  1. Reconnaissance and Target Identification: An attacker first identifies an exposed Twenty CRM instance. This can be accomplished through internet-wide scanning for Twenty-specific web application fingerprints (branding, API responses, or the /rest/metadata endpoint patterns). The attacker must then obtain valid credentials for a workspace administrator account with the DATA_MODEL permission. This could be acquired through credential stuffing, phishing, insider access, or exploiting a separate authentication flaw.

  2. Vulnerability Trigger: The attacker authenticates to the Twenty API and identifies the target searchVector field's metadata ID (obtainable via standard field enumeration through the metadata API). The attacker then crafts a request to either PATCH /rest/metadata/fields/:id or the updateOneField GraphQL mutation, setting settings.asExpression to a malicious SQL expression.

  3. Payload Execution: At the vulnerability-class level, the payload consists of a valid SQL expression followed by a statement terminator (semicolon) and arbitrary PostgreSQL statements. Because the system concatenates unfiltered input into the generated column definition, the payload executes in the context of ALTER TABLE command. Example class-level payload structure: '<legitimate expression>' ; <malicious PostgreSQL statements> --. The malicious statements can include data exfiltration via COPY or SELECT ... INTO OUTFILE equivalents, creation of rogue admin accounts in the application's user tables, or execution of database functions.

  4. Post-Exploitation Impact: Once arbitrary SQL execution is achieved, the attacker has full control over the CRM database. This enables: complete data theft (customer records, communications, credentials if stored), data manipulation (altering records to commit fraud or cover traces), denial of service (dropping tables or corrupting data), and potential database server compromise if the application database user has elevated privileges or if additional database-level exploitation (e.g., pg_read_file, COPY ... FROM PROGRAM in older PostgreSQL versions) is possible.

The privilege requirement (administrator with DATA_MODEL permission) slightly raises the exploitation bar, but the impact is severe because the attacker already has legitimate access and can move from administrative UI access to full database compromise.

Impact Assessment

CVSS Analysis (9.1 Critical): The vulnerability carries a CVSS v3.1 score of 9.1 with vector CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H. Key observations from this vector:

  • Attack Vector — Network (AV:N): The flaw is exploitable remotely via the HTTP API; no physical or local access required.
  • Attack Complexity — Low (AC:L): No special conditions beyond a successful API call; no race conditions or probabilistic elements.
  • Privileges Required — High (PR:H): Authentication as a workspace administrator with DATA_MODEL permission is required.
  • User Interaction — None (UI:N): No victim interaction needed.
  • Scope — Changed (S:C): The database user's privileges extend beyond the web application's security boundary; shell-level or cross-database impact possible.
  • Confidentiality/Integrity/Availability — High (C:H/I:H/A:H): Complete database compromise.

Business Impact: The CRM is the operational heartbeat for customer relationships. A successful attack leads to: (1) exfiltration of PII and commercial data triggering regulatory obligations (GDPR, CCPA), (2) integrity loss of pipeline and sales data causing operational disruption, (3) reputational damage from the disclosure of a CRM breach, and (4) potential downstream impacts on connected systems through data corruption and shared credentials.

Blast Radius: All Twenty instances running versions prior to 2.15.0 with a workspace administrator account that has DATA_MODEL permissions are exposed. Multi-tenant deployments are especially concerning, as the application database user in such configurations often has access to all tenants' data, widening the impact from a single compromised workspace to the entire instance.

Detection Guidance

Sigma Rule

title: Twenty CRM SearchVector SQL Injection Attempt
id: 7f2f5a6e-8b4d-4f2e-9d3a-1c8b7e6a5f4d
status: experimental
description: Detects attempts to exploit CVE-2026-73069 by injecting malicious content into settings.asExpression for the searchVector field in Twenty CRM.
author: Valtersit Security Research
date: 2026/02/10
logsource:
    category: application
    product: webserver
    service: api
detection:
    selection_rest:
        http.method: PATCH
        http.url.raw|contains: /rest/metadata/fields/
    selection_graphql:
        http.method: POST
        http.url.raw|contains: graphql
        http.request_body|contains: updateOneField
    selection_payload:
        http.request_body|contains|all:
            - searchVector
            - asExpression
    selection_malicious:
        http.request_body|contains|any:
            - ';DROP'
            - ';INSERT'
            - ';DELETE'
            - ';UPDATE'
            - ';CREATE'
            - 'pg_sleep'
            - 'pg_read_file'
            - 'COPY'
            - '--'
    condition: (selection_rest or selection_graphql) and selection_payload and selection_malicious
    level: critical
falsepositives:
    - Legitimate administrative changes to the searchVector field that contain SQL keywords in the expression
    - Developers testing search configuration with SQL-like strings
fields:
    - src.ip
    - user.name
    - http.url
    - http.user_agent
tags:
    - attack.target
    - attack.tactic.initial_access
    - attack.technique.t1190

YARA Rule

rule TwentyCRM_SearchVector_SQLi_CVE_2026_73069
{
    meta:
        author = "Valtersit Security Research"
        description = "Detects malicious payload patterns targeting Twenty CRM searchVector settings.asExpression SQL injection (CVE-2026-73069)"
        date = "2026-02-10"
        cve = "CVE-2026-73069"
        severity = "critical"
        reference = "NVD CVE-2026-73069"
    strings:
        $s1 = "searchVector" ascii nocase wide
        $s2 = "asExpression" ascii nocase wide
        $s3 = "updateOneField" ascii nocase wide
        $s4 = "/rest/metadata/fields/" ascii nocase wide
        $p1 = ");" ascii
        $p2 = ";DROP" ascii nocase
        $p3 = ";INSERT" ascii nocase
        $p4 = ";DELETE" ascii nocase
        $p5 = ";UPDATE" ascii nocase
        $p6 = ";CREATE" ascii nocase
        $p7 = "pg_sleep" ascii nocase
        $p8 = "pg_read_file" ascii nocase
        $p9 = "COPY " ascii nocase
        $p10 = "GENERATED ALWAYS" ascii nocase
    condition:
        any of ($s*) and 2 of ($p*)
}

Suricata IDS Rule

alert http any any -> any any (msg:"CVE-2026-73069 Twenty CRM SearchVector SQL Injection Attempt"; flow:established,to_server; content:"PATCH"; http_method; content:"/rest/metadata/fields/"; http_uri; content:"searchVector"; http_request_body; content:"asExpression"; http_request_body; pcre:"/(?:;DROP|;INSERT|;DELETE|;UPDATE|;CREATE|pg_sleep|pg_read_file|\x3b\s*DROP)/i"; classtype:attempted-admin; sid:10073069; rev:1; reference:cve,2026-73069; metadata:affected_product Twenty-CRM, attack_target Web_Application, deployment Perimeter, tag SQLi, tag CVE-2026-73069;)

Elastic Detection

// Detect requests to Twenty CRM metadata API with SQL injection patterns
sequence by source.ip
  [network where network.protocol == "http" and http.request.method == "PATCH" and
   url.path contains "/rest/metadata/fields/"]
  [network where network.protocol == "http" and http.request.method == "POST" and
   url.path contains "graphql" and http.request.body.text contains "updateOneField"]
  [network where network.protocol == "http" and
   (http.request.body.text : "*searchVector*" and http.request.body.text : "*asExpression*") and
   http.request.body.text : ("*;DROP*", "*;INSERT*", "*;DELETE*", "*;UPDATE*", "*;CREATE*", "*pg_sleep*", "*pg_read_file*", "*;--*")]

Splunk SPL Query

index=web sourcetype=access_combined OR sourcetype=iis
| where (method="PATCH" AND uri_path="/rest/metadata/fields/*") 
    OR (method="POST" AND uri_path=*graphql* AND _raw LIKE "%updateOneField%")
| where _raw LIKE "%searchVector%" AND _raw LIKE "%asExpression%"
| where _raw LIKE "%asExpression%" AND 
      (_raw LIKE "%;DROP%" OR _raw LIKE "%;INSERT%" OR _raw LIKE "%;DELETE%" 
       OR _raw LIKE "%;UPDATE%" OR _raw LIKE "%;CREATE%" OR _raw LIKE "%pg_sleep%" 
       OR _raw LIKE "%pg_read_file%")
| table _time, src_ip, method, uri_path, user, http_user_agent
| stats count by src_ip, method, uri_path, user

Wazuh OSSEC Rule

<group name="twenty_crm,">
  <rule id="100730" level="15" frequency="3" timeframe="60">
    <if_sid>31100</if_sid>
    <regex>PATCH /rest/metadata/fields/.*searchVector.*asExpression.*</regex>
    <description>Twenty CRM CVE-2026-73069: SQL injection payload in searchVector asExpression parameter</description>
    <mitre>
      <id>T1190</id>
      <tactic>TA0001</tactic>
      <technique>T1190</technique>
    </mitre>
    <group>attack.initial_access,sql_injection,</group>
  </rule>
  <rule id="100731" level="15" frequency="3" timeframe="60">
    <if_sid>31100</if_sid>
    <regex>updateOneField.*searchVector.*asExpression.*(?:;DROP|;INSERT|;DELETE|;UPDATE|;CREATE|pg_sleep|pg_read_file)</regex>
    <description>Twenty CRM CVE-2026-73069: Malicious asExpression content in GraphQL updateOneField mutation</description>
    <mitre>
      <id>T1190</id>
      <tactic>TA0001</tactic>
      <technique>T1190</technique>
    </mitre>
    <group>attack.initial_access,sql_injection,</group>
  </rule>
</group>

Mitigation & Patch Guidance

Patch Confidence: 0/4 — UNPATCHED — Note: While the NVD description states the issue "is fixed in version 2.15.0," our patch confidence tracking shows no verifiable patch evidence from any tracked source, vendor advisory, or CNA publication. The vendor fix should be verified directly with the Twenty project.

1. Immediate Mitigations (implement now)

  • Restrict DATA_MODEL permission: Audit all workspace administrators and revoke DATA_MODEL permission where not strictly required. This permission should be granted only to trusted personnel responsible for CRM data model configuration.
  • Network-level containment: Apply network access control lists to restrict access to the Twenty API from trusted administrative networks and jump hosts. This limits attack surface from the general internet.
  • Deploy WAF rules: Use the Suricata rule provided above or equivalent WAF logic to block requests containing SQL injection patterns in the asExpression parameter of field metadata requests.
  • Database user hardening: Review the application database user's PostgreSQL privileges. Where possible, revoke DDL privileges and COPY access while testing functionality. Implement row-level security where feasible.

2. Patch / Upgrade Steps

  • Verify with vendor: Contact the Twenty maintainers to confirm the availability of version 2.15.0 and obtain specific patch details or upgrade guidance.
  • Upgrade to 2.15.0+: When verified, apply the upgrade in a staging environment first, validate CRM functionality (especially search features), then deploy to production following the project's official upgrade procedures.
  • If 2.15.0 is unavailable: Consider downgrading feature exposure by disabling full-text search or patching the buildSqlColumnDefinition utility function manually to parameterize or whitelist asExpression values, accepting the unsupported nature of such modifications.

3. Long-Term Hardening

  • Application-level input validation: Implement a strict allow-list of PostgreSQL expression syntax for asExpression fields, eliminating all semicolons, comments, and multi-statement constructs.
  • ORM/SQL generation audit: Review all SQL generation utilities for similar concatenation patterns, applying parameterized queries or ORM-native builder methods throughout.
  • Database least-privilege: Separate the database user used for the web application into distinct users: one for schema migrations/DDL and another for runtime operations (DML-only). The DATA_MODEL feature should use the DDL-capable user, and all other application paths should use the locked-down user.
  • Monitoring and alerting: Deploy the detection rules from this report and establish a baseline for legitimate searchVector field modifications to expedite alert triage.

References

  1. NVD Entry: CVE-2026-73069 — https://nvd.nist.gov/vuln/detail/CVE-2026-73069
  2. Twenty CRM Official Site — https://twenty.com
  3. Twenty CRM GitHub Repository (for security announcements and releases) — https://github.com/twentyhq/twenty
  4. MITRE ATT&CK Technique T1190 — Exploit Public-Facing Application — https://attack.mitre.org/techniques/T1190/
  5. CWE-89: SQL Injection — https://cwe.mitre.org/data/definitions/89.html

Threat Actor Intelligence: As of the publication date, there is no evidence of active exploitation in the wild, no public PoC, no known exploit code, and no inclusion in CISA's Known Exploited Vulnerabilities (KEV) catalog. The vulnerability is not listed as a target in any tracked threat actor campaign. However, given the critical severity (CVSS 9.1), the open-source nature of the product (public code review possible for payload development), and the relatively low complexity of the SQL injection class, exploitation should be considered likely once a PoC is developed or the patch diff reveals concrete details. Organizations running Twenty should treat this as an urgent patching priority.

👁️ SHODAN DORKS (THREAT HUNTING)

What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.

http.title:"Twenty"
http.html:"twenty-crm"
product:"Twenty CRM"

💣 PoC CODE AVAILABLE

Exploit code for this CVE is tracked in our database. Access poc_code via API Pro.

[ API_PRO ] →
◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2026-73069/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.