CVE-2026-73292 Overview
CVE-2026-73292 is a Cross-Site Request Forgery (CSRF) vulnerability [CWE-352] in Semaphore UI, a web interface for managing DevOps tools such as Ansible, Terraform, and OpenTofu. The /api/users/{id}/password endpoint accepts cross-site requests using the authenticated user's session cookie without CSRF protection or current-password confirmation. An unauthenticated remote attacker can trick an authenticated administrator into visiting a malicious page that silently changes the administrator's password. Successful exploitation grants the attacker full control of the targeted Semaphore account, including administrative privileges over DevOps automation pipelines. The issue is fixed in Semaphore UI version 2.18.21.
Critical Impact
A single click on an attacker-controlled link by an authenticated Semaphore administrator can result in complete account takeover and hijacking of DevOps automation infrastructure.
Affected Products
- Semaphore UI versions prior to 2.18.21
- Semaphore UI deployments exposed over HTTP without TLS
- Self-hosted Semaphore instances used for Ansible, Terraform, and OpenTofu automation
Discovery Timeline
- 2026-08-12 - CVE-2026-73292 published to the National Vulnerability Database (NVD)
- 2026-08-12 - Last updated in NVD database
- Fix release - Semaphore UI version 2.18.21 published with the CSRF mitigation
Technical Details for CVE-2026-73292
Vulnerability Analysis
Semaphore UI exposes a password-change API at /api/users/{id}/password. Prior to version 2.18.21, this endpoint accepted authenticated requests based solely on the presence of the semaphore session cookie. The endpoint did not require a CSRF token, an Origin/Referer check, or re-entry of the current password.
The session cookie was also issued without a SameSite attribute, so browsers attached it to cross-site POST requests by default. An attacker who hosts a malicious HTML page can auto-submit a form to a targeted Semaphore instance. If a logged-in user visits that page, the browser sends the request with the user's valid session cookie, and Semaphore changes the password to a value chosen by the attacker.
Because administrators typically hold long-lived sessions in DevOps consoles, the window for exploitation is wide. Post-exploitation, the attacker can log in, modify project inventories, alter Ansible playbooks, and pivot into managed infrastructure.
Root Cause
The root cause is missing CSRF protection on a state-changing endpoint combined with a permissive session cookie configuration. The semaphore cookie was set with HttpOnly but no SameSite attribute and no Secure flag, allowing cross-site inclusion. The password-change handler also did not enforce current-password confirmation, removing the last line of defense.
Attack Vector
Exploitation requires only that an authenticated Semaphore user, ideally an administrator, load an attacker-controlled web page. The page auto-submits a POST to the target Semaphore host's /api/users/{id}/password endpoint. No credentials, prior access, or elevated privileges are required from the attacker.
// Patch applied in api/login.go — sets SameSite=Lax and Secure on the session cookie
Value: encoded,
Path: "/",
HttpOnly: true,
+ // SameSite=Lax prevents the session cookie from being attached to
+ // cross-site POST requests, which mitigates CSRF (e.g. the password
+ // change endpoint). Top-level GET navigations still carry the cookie
+ // so following a link into Semaphore keeps the user logged in.
+ SameSite: http.SameSiteLaxMode,
+ // Secure is only enforced when Semaphore is served over HTTPS, so that
+ // it can still be used without TLS inside private networks.
+ Secure: isSecureWebHost(),
})
}
+// isSecureWebHost reports whether Semaphore's public web host uses HTTPS, in
+// which case cookies should carry the Secure attribute.
+func isSecureWebHost() bool {
+ return util.WebHostURL != nil && util.WebHostURL.Scheme == "https"
+}
Source: Semaphore commit 2d6e2e3
Detection Methods for CVE-2026-73292
Indicators of Compromise
- Unexpected POST requests to /api/users/{id}/password originating from browser referers outside the Semaphore host.
- Password changes for administrator accounts that do not correspond to helpdesk tickets or user requests.
- New or unrecognized login sessions to Semaphore immediately following a password-change event.
- Modifications to Ansible/Terraform/OpenTofu projects, inventories, or credentials shortly after suspicious password changes.
Detection Strategies
- Review Semaphore access logs for POST /api/users/*/password requests where the Referer or Origin header does not match the Semaphore web host.
- Correlate password-change events with subsequent authentication from new IP addresses or user-agent strings.
- Alert on any password-change event affecting privileged Semaphore accounts.
Monitoring Recommendations
- Forward Semaphore application and reverse-proxy logs to a centralized logging or SIEM platform for long-term retention and correlation.
- Monitor outbound activity from hosts running Semaphore for anomalous connections to managed infrastructure that could indicate abuse of hijacked automation.
- Enable audit logging for changes to Semaphore projects, keys, and user roles to detect post-compromise tampering.
How to Mitigate CVE-2026-73292
Immediate Actions Required
- Upgrade all Semaphore UI instances to version 2.18.21 or later without delay.
- Force password resets for all Semaphore user accounts, prioritizing administrators, after upgrading.
- Invalidate existing sessions and rotate any credentials, SSH keys, or API tokens stored in Semaphore.
- Review recent password-change activity and audit logs for signs of prior exploitation.
Patch Information
The fix is available in Semaphore UI release v2.18.21. The patch sets the session cookie with SameSite=Lax and enforces the Secure attribute when Semaphore is served over HTTPS. Details are documented in GitHub Security Advisory GHSA-8cj9-r88m-8945 and applied in commits 2d6e2e3 and c59c3dc.
Workarounds
- Serve Semaphore only over HTTPS so that the Secure cookie flag applied by the patch is effective.
- Restrict access to the Semaphore UI to trusted networks or VPNs using firewall or reverse-proxy rules.
- Configure a reverse proxy to enforce strict Origin and Referer header checks on requests to /api/users/*/password.
- Instruct administrators to log out of Semaphore when not actively using it to shrink the CSRF exploitation window.
# Example: upgrade a Docker-based Semaphore deployment to the patched version
docker pull semaphoreui/semaphore:v2.18.21
docker stop semaphore && docker rm semaphore
docker run -d --name semaphore \
-p 443:3000 \
-e SEMAPHORE_WEB_ROOT="https://semaphore.example.com" \
semaphoreui/semaphore:v2.18.21
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

