CVE-2026-76900 Overview
CordysCRM is an open source AI-powered customer relationship management platform that supports private deployment. CVE-2026-76900 is a Server-Side Request Forgery (SSRF) vulnerability [CWE-918] affecting CordysCRM version 1.7.3. The flaw resides in the approval workflow webhook feature, where ApprovalResourceService.sendWebHook reads a stored WebHookConfig.webHookUrl and forwards it to HttpClientUtils without invoking the SSRF validation applied to the testConnect path. Authenticated operators with the PROCESS_SETTING_ADD permission can point the webhook at internal URLs and force the server to fetch them during approval execution. The issue is fixed in version 1.7.4.
Critical Impact
An authenticated attacker can coerce the CordysCRM server to reach cloud metadata endpoints, perform internal network reconnaissance, and interact with internal services otherwise unreachable from the public network.
Affected Products
- CordysCRM version 1.7.3
- CordysCRM prior versions using the same approval-flow webhook logic
- Deployments granting the PROCESS_SETTING_ADD permission to lower-trust operators
Discovery Timeline
- 2026-09-18 - CVE CVE-2026-76900 published to the National Vulnerability Database
- 2026-09-24 - Last updated in NVD database
Technical Details for CVE-2026-76900
Vulnerability Analysis
The vulnerability lives in the approval-flow webhook execution path. ApprovalResourceService.sendWebHook retrieves a persisted WebHookConfig object from an approval-node configuration and passes webHookUrl through ApprovalFlowService.updateApprovalPostField into HttpClientUtils. The optional testConnect code path calls SSRFValidationService.validate on the URL, but the production sendWebHook execution path does not. As a result, a URL stored during approval-node configuration is fetched by the server at approval time without host, scheme, or address-range checks. This lets the server reach cloud metadata services such as 169.254.169.254, RFC1918 hosts, and localhost-bound admin interfaces.
Root Cause
The root cause is inconsistent input validation between two code paths that consume the same untrusted URL. SSRFValidationService.validate was invoked only when administrators clicked "test connection", not when the stored configuration was later executed by the approval engine. Persisted webhook targets therefore bypassed all address-family and destination filtering.
Attack Vector
An authenticated user holding PROCESS_SETTING_ADD submits POST /approval-flow/add with a WebHookConfig pointing webHookUrl at an internal resource. When any approval is later processed through POST /approval-action/approve, the server issues the outbound HTTP request. Responses and side effects flow back through the approval infrastructure, enabling metadata theft, internal reconnaissance, and interaction with unauthenticated internal APIs.
// Patch: SSRF validation moved out of testConnect and enforced in shared HTTP utility
public void testConnect(WebHookConfig webHookConfig) {
if (webHookConfig != null && webHookConfig.getWebHookEnable()) {
HashMap<String, Object> resultObj = new HashMap<>();
- // SSRF安全校验
- ssrfValidationService.validate(webHookConfig.getWebHookUrl());
switch (webHookConfig.getWebHookMethod()) {
case "POST":
resultObj = sendPost(webHookConfig, null, null, true, null);
// HttpClientUtils now imports and applies SSRFValidationService centrally
package cn.cordys.crm.integration.common.utils;
+import cn.cordys.common.service.SSRFValidationService;
+import cn.cordys.common.util.CommonBeanFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.*;
Source: GitHub Commit e0ae23e
Detection Methods for CVE-2026-76900
Indicators of Compromise
- Outbound HTTP requests from the CordysCRM application server to link-local metadata addresses such as 169.254.169.254 or GCP/Azure metadata hostnames.
- Application-server connections to RFC1918 ranges or 127.0.0.1 originating from the approval processing thread.
- Approval-node configurations whose webHookUrl fields point to non-business hostnames, raw IP addresses, or unusual ports.
Detection Strategies
- Inspect audit logs for POST /approval-flow/add requests that persist WebHookConfig entries with private, loopback, or metadata URLs.
- Correlate POST /approval-action/approve invocations with unexpected egress connections from the CordysCRM host.
- Review database records for approval nodes containing webhook URLs that fail an allowlist of expected external destinations.
Monitoring Recommendations
- Enable egress firewall logging on the CordysCRM host and alert on any traffic to cloud metadata endpoints.
- Monitor for HTTP responses containing IAM credentials, instance identity documents, or Kubernetes service account tokens.
- Track privilege assignments of PROCESS_SETTING_ADD and alert when the permission is granted outside change-management windows.
How to Mitigate CVE-2026-76900
Immediate Actions Required
- Upgrade CordysCRM to version 1.7.4, which enforces SSRF validation inside HttpClientUtils for both testConnect and sendWebHook paths.
- Audit existing approval-node webhook configurations and remove entries pointing at internal, loopback, or cloud metadata addresses.
- Restrict the PROCESS_SETTING_ADD permission to a minimum set of trusted administrators.
Patch Information
The fix is delivered in CordysCRM v1.7.4 via commit e0ae23e. Additional context is available in the GitHub Security Advisory GHSA-fg6q-pfj7-fghw and the Pull Request Discussion. The patch centralizes SSRFValidationService.validate calls within HttpClientUtils so every outbound request is filtered.
Workarounds
- Deploy CordysCRM behind an egress proxy that blocks traffic to RFC1918, loopback, and link-local metadata addresses.
- Apply host-based firewall rules on the application server to deny outbound connections to 169.254.169.254 and internal management subnets.
- Where possible, use IMDSv2 with hop-limit 1 on AWS instances to reduce the impact of SSRF against cloud metadata.
# Example iptables rules to block SSRF egress to metadata and internal ranges
iptables -A OUTPUT -m owner --uid-owner cordyscrm -d 169.254.169.254 -j REJECT
iptables -A OUTPUT -m owner --uid-owner cordyscrm -d 10.0.0.0/8 -j REJECT
iptables -A OUTPUT -m owner --uid-owner cordyscrm -d 172.16.0.0/12 -j REJECT
iptables -A OUTPUT -m owner --uid-owner cordyscrm -d 192.168.0.0/16 -j REJECT
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.
