Security Model

This section attempts to document the Zulip security model. Since this is new documentation, it likely does not cover every issue; if there are details you're curious about, please feel free to ask questions on the Zulip development mailing list (or if you think you've found a security bug, please report it to zulip-security@googlegroups.com so we can do a responsible security announcement).

Secure your Zulip server like your email server

In particular, anyone with root access to a Zulip application server or Zulip database server, or with access to the zulip user on a Zulip application server, has complete control over the Zulip installation and all of its data (so they can read messages, modify history, etc.). It would be difficult or impossible to avoid this, because the server needs access to the data to support features expected of a group chat system like the ability to search the entire message history, and thus someone with control over the server has access to that data as well.

Encryption and Authentication

Passwords

Zulip stores user passwords using the standard PBKDF2 algorithm. Password strength is checked and weak passwords are visually discouraged using the popular zxcvbn library. The minimum password strength allowed is controlled by two settings in /etc/zulip/settings.py; PASSWORD_MIN_LENGTH and PASSWORD_MIN_ZXCVBN_QUALITY. The former is self-explanatory; we will explain the latter.

Password strength estimation is a complicated topic that we can't go into great detail on here; we recommend reading the zxvcbn website for details if you are not familiar with password strength analysis.

In Zulip's configuration, a password has quality X if zxcvbn estimates that it would take e^(X * 22) seconds to crack the password with a specific attack scenario. The scenario Zulip uses is one where an the attacker breaks into the Zulip server and steals the hashed passwords; in that case, with a slow hash, the attacker would be able to make roughly 10,000 attempts per second. E.g. a password with quality 0.5 (the default), it would take an attacker about 16 hours to crack such a password in this sort of offline attack.

Another important attack scenario is the online attacks (i.e. an attacker sending tons of login requests guessing different passwords to a Zulip server over the web). Those attacks are much slower (more like 10/second without rate limiting), and you should estimate the time to guess a password as correspondingly longer.

As a server administrators, you must balance the security risks associated with attackers guessing weak passwords against the usability challenges associated with requiring strong passwords in your organization.

Messages and History

The message editing policy can be configured on the realm administration page. There are three configurations provided out of the box: (i) users cannot edit messages at all, (ii) users can edit any message they have sent, and (iii) users can edit the content of any message they have sent in the last N minutes, and the topic of any message they have sent. In (ii) and (iii), topic edits can also be propagated to other messages with the same original topic, even if those messages were sent by other users. The default setting is (iii), with N = 10.

In addition, and regardless of the configuration above, messages with no topic can always be edited to have a topic, by anyone in the organization, and the topic of any message can also always be edited by a realm administrator.

Also note that while edited messages are synced immediately to open browser windows, editing messages is not a safe way to redact secret content (e.g. a password) shared unintentionally. Other users may have seen and saved the content of the original message, or have an integration (e.g. push notifications) forwarding all messages they receive to another service. Zulip also stores and sends to clients the content of every historical version of a message.

Users and Bots

In the future, Zulip's security model may change to allow realm administrators to access private messages (e.g. to support auditing functionality).

User-uploaded content

The URLs of user-uploaded files are secret; if you are using the "local file upload" integration, anyone with the URL of an uploaded file can access the file. This means the local uploads integration is vulnerable to a subtle attack where if a user clicks on a link in a secret .PDF or .HTML file that had been uploaded to Zulip, access to the file might be leaked to the other server via the Referrer header (see the "Uploads world readable" issue on GitHub).

The Zulip S3 file upload integration is relatively safe against that attack, because the URLs of files presented to users don't host the content. Instead, the S3 integration checks the user has a valid Zulip session in the relevant realm, and if so then redirects the browser to a one-time S3 URL that expires a short time later. Keeping the URL secret is still important to avoid other users in the Zulip realm from being able to access the file.

Final notes and security response

If you find some aspect of Zulip that seems inconsistent with this security model, please report it to zulip-security@googlegroups.com so that we can investigate and coordinate an appropriate security release if needed.

Zulip security announcements will be sent to zulip-announce@googlegroups.com, so you should subscribe if you are running Zulip in production.