Incident Report - September 1, 2026
Vishnu Narayanan
Published on
2 minute read
Our blog was compromised between May and September 2026. An attacker obtained an API key for the Ghost instance that hosts the blog and used it to insert spam links into published posts. We identified the activity on September 1, revoked the key, and removed the links.
We regret that this happened. While we patched the underlying Ghost vulnerability, we failed to rotate credentials that may already have been exposed.
We have since addressed that gap and made additional changes to how we handle credential exposure, logging, and access to our internet-facing systems.
No customer data was involved
The affected Ghost instance is a public-facing content server used only to serve our blog and changelog. It sits outside the network that runs Chatwoot Cloud and is not connected to our application or customer-data infrastructure.
It does not share databases, networks, or credentials with Chatwoot Cloud or any other production systems. The compromised key was scoped to Ghost and could only be used to access and modify blog content.
- Chatwoot Cloud and the Chatwoot application
- Customer accounts, conversations, contacts, and messages
- Self-hosted Chatwoot installations
- Payment data, which the blog has never held
No action is needed from customers or from self-hosted users.
Timeline
All times are in Coordinated Universal Time (UTC)
- May 5, 2026: We upgraded our Ghost instance to patch CVE-2026-26980, a critical SQL injection vulnerability in its public Content API. At the time, we were not aware that an API key had already been exposed through the vulnerability, so we did not rotate it.
- June 10, 2026: A couple of blog posts was modified, which appears to have been a test of the compromised key.
- July 7, 2026, 13:46–14:09 UTC: The attacker modified 143 posts and added a marker.
- August 29, 2026: The attacker used the compromised key to insert spam links into published posts.
- September 1, 2026: We identified the unauthorized activity, removed the injected content, and rotated the compromised key, ending the attacker’s access.
What happened
CVE-2026-26980 allowed an unauthenticated attacker to read data from the database behind Ghost’s public Content API. We upgraded to a patched version on May 5, which closed the vulnerability. At the time, we were not aware that a credential had already been exposed, so we did not rotate it.
The exposed key belonged to a Zapier integration that had been created when we first deployed Ghost. It was never used, but it remained enabled and had permission to manage blog content.
Because patching the vulnerability did not invalidate an already exposed credential, the attacker was able to use the key intermittently over the following months to modify posts and insert spam links. In August, they also attempted to create a staff account, which was never successful.
We revoked the key on September 1, ending their access. We found no evidence of host or shell access, and no activity extended beyond the blog.
Further steps
- We now rotate credentials whenever a vulnerability may have exposed data containing secrets, in addition to applying the patch.
- We removed unused Ghost integrations, including the Zapier integration, and restricted the Ghost admin interface from the public internet.
- We are reviewing our other internet-facing systems to ensure they have defined patching and alerting for critical vulnerabilities.