← Back to Feed CACHED · 2026-10-06 13:30:25 · CACHE_KEY CVE-2026-105763
CVE-2026-105763 · CWE-522 · Disclosed 2026-10-06

Twenty CRM GraphQL connectedAccounts Plaintext IMAP/SMTP/CalDAV Credential Disclosure

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

Like leaving every employee's email password on a shared whiteboard that only coworkers can see

CVE-2026-105763 affects Twenty, an open-source CRM platform, in versions 1.20.10 through 2.6.x (fixed in 2.7.0). The /metadata GraphQL endpoint's connectedAccounts query returned the connectionParameters field — including plaintext IMAP, SMTP, and CalDAV passwords, hostnames, ports, and usernames — for *every* connected account in the workspace, regardless of who was asking. Any user holding the default Member role could harvest every colleague's external mail and calendar credentials with a single GraphQL request. The root cause was a missing @HideField() decorator on the DTO, unscoped database queries that returned all workspace rows, and plaintext storage of passwords at rest. Workspaces configured exclusively with Google or Microsoft OAuth are not affected, because no password is stored.

The vendor scored this CRITICAL at 9.6 using CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N. That vector is technically defensible — the scope change to external email/calendar accounts is legitimate, and the attack complexity is genuinely low. However, the vendor score overstates real-world urgency for enterprise defenders. The bug requires authenticated access as a workspace member (not unauthenticated remote), Twenty is a niche open-source CRM (not a ubiquitous infrastructure component), a large fraction of modern deployments use OAuth and are therefore immune, and there is no public PoC, no KEV listing, and no observed exploitation. A reassessed score of HIGH / 7.5 better captures the operational risk.

"Insider-accessible GraphQL query leaks plaintext email passwords; real risk is high but not fleet-critical."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Obtain workspace membership

The attacker must hold a valid workspace-member account in the target Twenty instance. This is the default role granted upon invitation. No privilege escalation is needed; the standard Member role is sufficient. Self-registration may or may not be enabled depending on the deployment.
Conditions required:
  • Valid Twenty workspace account with Member role
  • Network access to the Twenty GraphQL endpoint
Where this breaks in practice:
  • Workspace accounts are invitation-only by default — attacker must be a current or recently-offboarded employee, contractor, or partner.
  • Twenty instances are typically internal-only or behind VPN, limiting external attacker access.
Detection/coverage: Authentication logs in Twenty and upstream identity provider will record the session. Anomalous login from a new IP/device can trigger alerting.
STEP 02

Query /metadata connectedAccounts via GraphQL

The attacker sends a GraphQL query to the /metadata endpoint requesting connectedAccounts { connectionParameters }. No special tooling is needed — any HTTP client, browser dev-tools, or GraphQL explorer will work. The query returns all connected accounts in the workspace, not just the caller's. The response contains plaintext IMAP/SMTP host, port, username, and password, plus CalDAV credentials where configured.
Conditions required:
  • Vulnerable Twenty version (1.20.10–2.6.x)
  • At least one workspace member has connected an IMAP/SMTP or CalDAV account (not OAuth)
Where this breaks in practice:
  • Workspaces that use only Google or Microsoft OAuth store no password — the response is empty for those accounts.
  • Organizations using modern mail providers increasingly default to OAuth flows, reducing the population of plaintext-credential accounts.
Detection/coverage: GraphQL query logs (if enabled) will show the /metadata connectedAccounts query. SOC teams can alert on queries containing connectionParameters from non-admin users. No known scanner or IDS signature exists yet.
STEP 03

Harvest plaintext credentials from response

The GraphQL response contains structured JSON with each workspace member's email credentials in cleartext. The attacker parses the response to extract usernames, passwords, hosts, and ports for IMAP, SMTP, and CalDAV services. No cracking or decryption is needed — the passwords are returned as-is.
Conditions required:
  • Successful response from step 2
Where this breaks in practice:
  • If the workspace has few members or all use OAuth, the credential yield is minimal or zero.
Detection/coverage: No detection opportunity at this step — the data is already in the attacker's HTTP response.
STEP 04

Access victims' external email and calendar

Using the harvested IMAP/SMTP credentials, the attacker connects to the victims' mail servers directly. They can read, send, and delete email. With CalDAV credentials, they can read and manipulate calendar entries. This access is indistinguishable from the legitimate user's access at the mail-provider level.
Conditions required:
  • Harvested credentials are still valid (not rotated)
  • Mail/CalDAV server is reachable from attacker's network
Where this breaks in practice:
  • If the mail provider enforces MFA on IMAP/SMTP login (rare but possible), credentials alone are insufficient.
  • App-specific password policies or IP-allowlisting at the mail provider can block external access.
Detection/coverage: Mail provider logs will show logins from the attacker's IP. Impossible Travel or new-device alerts in the mail provider's security dashboard would fire.
STEP 05

Pivot via password reset on third-party services

With full email access, the attacker can initiate password-reset flows on any third-party service tied to the victim's email address. This extends the compromise beyond email/calendar to SaaS accounts, internal tools, or personal accounts. The attacker intercepts the reset email, completes the flow, and potentially locks the victim out.
Conditions required:
  • Victim uses the compromised email address for other service registrations
  • Third-party services do not require secondary verification beyond email
Where this breaks in practice:
  • Services with MFA enabled will block the password-reset pivot.
  • If the victim notices the reset email or lockout, the attack window closes quickly.
Detection/coverage: Third-party services may generate alerts on password changes. Email forwarding rules or read/delete patterns may trigger mail provider anomaly detection.
03 · Compensating Control

1
HIGH 7.5→MEDIUM 5.5
SEVERITY REDUCED
Rotate all IMAP/SMTP/CalDAV credentials immediately — Assume all plaintext credentials stored in Twenty are compromised. Change passwords at the mail provider for every user who connected via IMAP/SMTP/CalDAV. This is a day-zero action regardless of patch timeline. Under the noisgate mitigation SLA for HIGH, deploy within 30 days — but credential rotation should happen within hours of triage.
2
HIGH 7.5→IGNORE 0.0
SEVERITY REDUCED
Migrate connected accounts to Google or Microsoft OAuth — OAuth-only workspaces are explicitly unaffected by this CVE. Reconfigure all email/calendar integrations to use OAuth flows instead of IMAP/SMTP credentials. This eliminates the attack surface entirely for future exploitation. Deploy within 30 days per noisgate mitigation SLA.
3
HIGH 7.5→LOW 3.0
SEVERITY REDUCED
Restrict /metadata GraphQL endpoint to admin-only via reverse proxy — If immediate upgrade to 2.7.0 is not feasible, add a WAF or reverse-proxy rule that blocks non-admin requests to the /metadata GraphQL path containing connectedAccounts. This breaks the query path without modifying application code. Test carefully to avoid breaking legitimate admin workflows. Deploy within 30 days per noisgate mitigation SLA.
4
HIGH 7.5→IGNORE 0.0
SEVERITY REDUCED
Upgrade to Twenty 2.7.0 — The definitive fix. Version 2.7.0 adds @HideField() to the DTO, scopes queries to the caller's own accounts, and encrypts credentials at rest. Note that 2.7.0 includes breaking changes — review release notes and test in staging first. Under the noisgate remediation SLA for HIGH, deploy within 180 days.
5
HIGH 7.5→MEDIUM 5.0
SEVERITY REDUCED
Enable mail-provider MFA and app-password policies — Even if credentials are leaked, MFA on the mail provider blocks direct IMAP/SMTP login with stolen credentials. Configure app-specific passwords or conditional access policies at the mail provider. This does not fix the Twenty vulnerability but breaks the downstream exploitation chain. Deploy within 30 days.
What doesn't work
  • Network segmentation alone — the attacker is already an authenticated workspace member; restricting network access to the Twenty instance does not prevent them from querying it, since they need access to use the CRM.
  • Twenty's built-in role system (pre-2.7.0) — the vulnerability is exploitable by the default Member role; no role-based restriction in the application prevents the query.
  • Disabling GraphQL introspection — the attacker does not need introspection to craft the query; the field name connectionParameters is documented and discoverable without introspection.
04 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNot observed. Not listed in CISA KEV. No reports of active exploitation from any threat intelligence source as of 2026-10-06.
Proof of conceptNone public. No dedicated PoC repository found on GitHub. Not indexed on pocindex.io, ExploitDB, or Nuclei templates. The attack is trivially reproducible with a single GraphQL query, so a formal PoC is unnecessary — any authenticated user with curl can reproduce it.
EPSS scoreNot yet scored. CVE was published 2026-10-06; FIRST EPSS data is not yet available. Given the niche product and authentication requirement, expect a low-to-moderate EPSS percentile once scored.
KEV statusNot listed. No CISA KEV entry. No known government or critical-infrastructure impact.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N — Network-accessible, low complexity, low privileges, no user interaction, scope change to external services. Confidentiality and integrity impacts are high (full credential theft + email manipulation). No availability impact.
Affected versionsTwenty 1.20.10 through 2.6.x (all releases before 2.7.0). Versions ≤1.20.9 are not affected.
Fixed version2.7.0 — the fix adds @HideField() to the DTO, scopes the database query to the calling user's own accounts, and encrypts credentials at rest. Note: 2.7.0 includes breaking changes; review the release notes.
Exposure surfaceTwenty has 44,000+ GitHub stars and is adopted primarily by small-to-medium sales teams (1–50 users). Self-hosted instances are typically behind corporate networks or VPNs. The Twenty managed cloud (twenty.com) is presumably already patched. No Shodan/Censys/GreyNoise fingerprint data is available for Twenty-specific scanning.
Disclosure timelineGHSA-mq5c-qp77-2cv3 published 2026-09-01. CVE-2026-105763 published 2026-10-06. Fix available in 2.7.0 since at least September 2026.
ReporterJan Kahmen (turingpoint). Reported via GitHub Security Advisory process.

Sources.

  1. GitHub Security Advisory GHSA-mq5c-qp77-2cv3
  2. TheHackerWire — CVE-2026-105763 Analysis
  3. SecurityOnline — Twenty CRM Flaw Exposes Plaintext Passwords
  4. Strix AI — CVE-2026-105763 Detail
  5. VulDB — CVE-2026-105763
  6. Twenty CRM Official Site
  7. NVD — CWE-522: Insufficiently Protected Credentials
05 · The Call

Final Verdict
↓ DOWNGRADED to HIGH (7.5/10)

Why this verdict

  • Authentication gate: The attack requires a valid workspace Member account (PR:L). This is not unauthenticated remote exploitation — the attacker must already be an insider or have compromised an insider's credentials, which narrows the threat population significantly.
  • OAuth exclusion removes a large fraction of targets: Workspaces using Google or Microsoft OAuth — the dominant configuration in modern deployments — store no IMAP/SMTP/CalDAV passwords and are completely unaffected. The vulnerable population is limited to teams using legacy IMAP/SMTP credential flows.
  • Niche LoB application, not infrastructure: Twenty is a CRM for small sales teams. It is not a domain controller, identity provider, hypervisor, CI/CD system, backup appliance, or network edge device. Compromise of a Twenty instance does not yield fleet-scale, domain-scale, or supply-chain-scale impact.
  • Role multiplier: (a) *Low-value role:* developer sandbox or demo — negligible blast radius, no real credentials. (b) *Typical role:* production CRM for a 5–30 person sales team — credential theft affects those individuals' email accounts; blast radius is user-level to team-level, not host/domain/fleet. (c) *High-value role:* Twenty is not canonically deployed in any high-value infrastructure role (not an IdP, CA, hypervisor, CI/CD, backup, edge appliance, or DC). Even in the worst case, the blast radius is bounded by the number of workspace members with IMAP/SMTP credentials — typically single digits. This does not trigger the HIGH or CRITICAL floor rule because the affected component is not an infrastructure-class product and no deployment role reaches domain/fleet/supply-chain impact.
  • No exploitation evidence or tooling: No public PoC, no KEV listing, no observed campaigns. The attack is trivial to execute but nobody appears to be doing it.
  • Scope change is real but bounded: The S:C in the CVSS vector is justified — impact extends to external email/calendar services — but the downstream impact is bounded by whether those services enforce MFA and by the number of non-OAuth connected accounts in the workspace.

Why not higher?

CRITICAL would be appropriate if Twenty were a canonical high-value-role component (identity provider, domain controller, hypervisor, network edge) or if the attack were unauthenticated. It is neither. The vulnerability requires insider access, affects a niche LoB CRM, and a large fraction of deployments (OAuth-only) are immune. There is no evidence of active exploitation, no public PoC weaponization, and the blast radius is user-level rather than fleet-level. The vendor's 9.6 CRITICAL reflects the theoretical CVSS math but not real-world operational urgency.

Why not lower?

MEDIUM would understate the risk because the attack is trivially exploitable once authenticated — a single GraphQL query, no special tooling, no user interaction. The credential exposure is *immediate and complete* for all non-OAuth workspace members. The scope change to external email accounts is real and enables meaningful downstream compromise (password resets, BEC). For organizations using IMAP/SMTP with Twenty, this is a genuine and urgent exposure that demands prompt remediation.

06 · Verification

Crowdsourced verification payload.

Run on any machine with network access to the Twenty instance and curl + jq installed. You need a valid workspace member's JWT or API token. Usage: bash check_cve_2026_105763.sh https://twenty.example.com YOUR_JWT_TOKEN

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# CVE-2026-105763 Checker — Twenty CRM Plaintext Credential Exposure
# Tests whether the /metadata GraphQL endpoint leaks connectionParameters.
# Usage: bash check_cve_2026_105763.sh <TWENTY_BASE_URL> <JWT_TOKEN>
# Exit codes: 0 = VULNERABLE, 1 = PATCHED, 2 = UNKNOWN

set -euo pipefail

if [ $# -lt 2 ]; then
  echo "Usage: $0 <TWENTY_BASE_URL> <JWT_TOKEN>"
  echo "Example: $0 https://twenty.example.com eyJhbGciOi..."
  exit 2
fi

BASE_URL="${1%/}"
TOKEN="$2"
ENDPOINT="${BASE_URL}/metadata"

# GraphQL query that reproduces the vulnerability
QUERY='{"query":"{ connectedAccounts { edges { node { id handle connectionParameters } } } }"}'

echo "[*] Testing CVE-2026-105763 against ${ENDPOINT}"
echo "[*] Sending connectedAccounts query with connectionParameters field..."

RESPONSE=$(curl -s -w "\n%{http_code}" \
  -X POST "${ENDPOINT}" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  -d "${QUERY}" 2>/dev/null) || { echo "UNKNOWN — curl failed"; exit 2; }

HTTP_CODE=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | sed '$d')

if [ "$HTTP_CODE" -lt 200 ] || [ "$HTTP_CODE" -ge 500 ]; then
  echo "UNKNOWN — HTTP ${HTTP_CODE}, server error or unreachable."
  exit 2
fi

# Check if connectionParameters contains credential fields
if echo "$BODY" | jq -e '.data.connectedAccounts.edges[].node.connectionParameters' >/dev/null 2>&1; then
  HAS_PASSWORD=$(echo "$BODY" | jq -r '[.data.connectedAccounts.edges[].node.connectionParameters] | map(select(. != null)) | length')
  if [ "$HAS_PASSWORD" -gt 0 ]; then
    echo "VULNERABLE — connectionParameters returned with data for ${HAS_PASSWORD} account(s)."
    echo "[!] Plaintext credentials may be exposed. Do NOT print them."
    echo "[!] Upgrade to Twenty 2.7.0 and rotate all IMAP/SMTP/CalDAV passwords."
    exit 0
  fi
fi

# Check for errors indicating the field is hidden (patched behavior)
if echo "$BODY" | jq -e '.errors' >/dev/null 2>&1; then
  ERROR_MSG=$(echo "$BODY" | jq -r '.errors[0].message // empty')
  echo "PATCHED — Server rejected the query: ${ERROR_MSG}"
  exit 1
fi

# Empty edges array — could be patched (scoped to caller, no accounts) or no data
EDGE_COUNT=$(echo "$BODY" | jq -r '.data.connectedAccounts.edges | length' 2>/dev/null || echo "")
if [ "$EDGE_COUNT" = "0" ]; then
  echo "UNKNOWN — Query returned zero connected accounts. Could be patched (scoped to caller) or no accounts exist."
  echo "[*] Verify the Twenty version manually: check docker image tag or package.json for >= 2.7.0."
  exit 2
fi

echo "UNKNOWN — Unexpected response. Manual review required."
exit 2