mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	docs: Extract security-model.md.
This commit is contained in:
		@@ -60,10 +60,8 @@ be a user of multiple Zulip realms. The administrators of a realm can
 | 
				
			|||||||
choose whether to allow anyone to register an account and join, or
 | 
					choose whether to allow anyone to register an account and join, or
 | 
				
			||||||
only allow people who have been invited, or restrict registrations to
 | 
					only allow people who have been invited, or restrict registrations to
 | 
				
			||||||
members of particular groups (using email domain names or corporate
 | 
					members of particular groups (using email domain names or corporate
 | 
				
			||||||
single-sign-on login for verification). For more on scalability and
 | 
					single-sign-on login for verification). For more on security
 | 
				
			||||||
security considerations, see [the security section of the production
 | 
					considerations, see [the security model section](security-model.html).
 | 
				
			||||||
maintenance
 | 
					 | 
				
			||||||
instructions](prod-maintain-secure-upgrade.html#security-model).
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
The default Zulip home screen is like a chronologically ordered inbox;
 | 
					The default Zulip home screen is like a chronologically ordered inbox;
 | 
				
			||||||
it displays messages, starting at the oldest message that the user
 | 
					it displays messages, starting at the oldest message that the user
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,6 +54,7 @@ Contents:
 | 
				
			|||||||
   prod-troubleshooting
 | 
					   prod-troubleshooting
 | 
				
			||||||
   prod-customize
 | 
					   prod-customize
 | 
				
			||||||
   prod-maintain-secure-upgrade
 | 
					   prod-maintain-secure-upgrade
 | 
				
			||||||
 | 
					   security-model
 | 
				
			||||||
   prod-authentication-methods
 | 
					   prod-authentication-methods
 | 
				
			||||||
   prod-postgres
 | 
					   prod-postgres
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,9 +8,12 @@ secure Zulip installation, including:
 | 
				
			|||||||
- [Backups](#backups)
 | 
					- [Backups](#backups)
 | 
				
			||||||
- [Monitoring](#monitoring)
 | 
					- [Monitoring](#monitoring)
 | 
				
			||||||
- [Scalability](#scalability)
 | 
					- [Scalability](#scalability)
 | 
				
			||||||
- [Security Model](#security-model)
 | 
					 | 
				
			||||||
- [Management commands](#management-commands)
 | 
					- [Management commands](#management-commands)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You may also want to read this related content:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- [Security Model](security-model.html)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Upgrading
 | 
					## Upgrading
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**We recommend reading this entire section before doing your first
 | 
					**We recommend reading this entire section before doing your first
 | 
				
			||||||
@@ -353,196 +356,10 @@ running Zulip with a large team (>1000 users).
 | 
				
			|||||||
Questions, concerns, and bug reports about this area of Zulip are very
 | 
					Questions, concerns, and bug reports about this area of Zulip are very
 | 
				
			||||||
welcome!  This is an area we are hoping to improve.
 | 
					welcome!  This is an area we are hoping to improve.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Security Model
 | 
					## Securing your Zulip server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This section attempts to document the Zulip security model.  Since
 | 
					Zulip's security model is discussed in
 | 
				
			||||||
this is new documentation, it likely does not cover every issue; if
 | 
					[a separate document](security-model.html).
 | 
				
			||||||
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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* It's reasonable to think about security for a Zulip server like you
 | 
					 | 
				
			||||||
  do security for a team email server -- only trusted administrators
 | 
					 | 
				
			||||||
  within an organization should have shell access to the 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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Traffic between clients (web, desktop and mobile) and the Zulip is
 | 
					 | 
				
			||||||
  encrypted using HTTPS.  By default, all Zulip services talk to each
 | 
					 | 
				
			||||||
  other either via a localhost connection or using an encrypted SSL
 | 
					 | 
				
			||||||
  connection.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* The preferred way to login to Zulip is using an SSO solution like
 | 
					 | 
				
			||||||
  Google Auth, LDAP, or similar.  Zulip stores user passwords using
 | 
					 | 
				
			||||||
  the standard PBKDF2 algorithm.  Password strength is checked and
 | 
					 | 
				
			||||||
  weak passwords are visually discouraged using the `zxcvbn` library,
 | 
					 | 
				
			||||||
  but Zulip does not by default have strong requirements on user
 | 
					 | 
				
			||||||
  password strength.  Modify the settings to adjust the password
 | 
					 | 
				
			||||||
  strength requirements (length and `zxcvbn` minimum quality).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Zulip requires CSRF tokens in all interactions with the web API to
 | 
					 | 
				
			||||||
  prevent CSRF attacks.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### Messages and History
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Zulip message content is rendered using a specialized Markdown
 | 
					 | 
				
			||||||
  parser which escapes content to protect against cross-site scripting
 | 
					 | 
				
			||||||
  attacks.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Zulip supports both public streams and private ("invite-only")
 | 
					 | 
				
			||||||
  streams.  Any Zulip user can join any public stream in the realm,
 | 
					 | 
				
			||||||
  and can view the complete message history of any public stream
 | 
					 | 
				
			||||||
  without joining the stream.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* A private ("invite-only") stream is hidden from users who are not
 | 
					 | 
				
			||||||
  subscribed to the stream.  Users who are not members of a private
 | 
					 | 
				
			||||||
  stream cannot read messages on the stream, send messages to the
 | 
					 | 
				
			||||||
  stream, or join the stream, even if they are a Zulip realm
 | 
					 | 
				
			||||||
  administrator.  Users can join private streams only when they are
 | 
					 | 
				
			||||||
  invited.  However, any member of a private stream can invite other
 | 
					 | 
				
			||||||
  users to the stream.  When a new user joins a private stream, they
 | 
					 | 
				
			||||||
  can see future messages sent to the stream, but they do not receive
 | 
					 | 
				
			||||||
  access to the stream's message history.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Zulip supports editing the content and topics of messages that have
 | 
					 | 
				
			||||||
  already been sent. As a general philosophy, our policies provide
 | 
					 | 
				
			||||||
  hard limits on the ways in which message content can be changed or
 | 
					 | 
				
			||||||
  undone. In contrast, our policies around message topics favor
 | 
					 | 
				
			||||||
  usefulness (e.g. for conversational organization) over faithfulness
 | 
					 | 
				
			||||||
  to the original.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* There are three types of users in a Zulip realm: Administrators,
 | 
					 | 
				
			||||||
  normal users, and bots.  Administrators have the ability to
 | 
					 | 
				
			||||||
  deactivate and reactivate other human and bot users, delete streams,
 | 
					 | 
				
			||||||
  add/remove administrator privileges, as well as change configuration
 | 
					 | 
				
			||||||
  for the overall realm (e.g. whether an invitation is required to
 | 
					 | 
				
			||||||
  join the realm).  Being a Zulip administrator does not provide the
 | 
					 | 
				
			||||||
  ability to interact with other users' private messages or the
 | 
					 | 
				
			||||||
  messages sent to private streams to which the administrator is not
 | 
					 | 
				
			||||||
  subscribed.  However, a Zulip administrator subscribed to a stream
 | 
					 | 
				
			||||||
  can toggle whether that stream is public or private.  Also, Zulip
 | 
					 | 
				
			||||||
  realm administrators have administrative access to the API keys of
 | 
					 | 
				
			||||||
  all bots in the realm, so a Zulip administrator may be able to
 | 
					 | 
				
			||||||
  access messages sent to private streams that have bots subscribed,
 | 
					 | 
				
			||||||
  by using the bot's credentials.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  In the future, Zulip's security model may change to allow realm
 | 
					 | 
				
			||||||
  administrators to access private messages (e.g. to support auditing
 | 
					 | 
				
			||||||
  functionality).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Every Zulip user has an API key, available on the settings page.
 | 
					 | 
				
			||||||
  This API key can be used to do essentially everything the user can
 | 
					 | 
				
			||||||
  do; for that reason, users should keep their API key safe.  Users
 | 
					 | 
				
			||||||
  can rotate their own API key if it is accidentally compromised.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* To properly remove a user's access to a Zulip team, it does not
 | 
					 | 
				
			||||||
  suffice to change their password or deactivate their account in the
 | 
					 | 
				
			||||||
  SSO system, since neither of those prevents authenticating with the
 | 
					 | 
				
			||||||
  user's API key or those of bots the user has created.  Instead, you
 | 
					 | 
				
			||||||
  should deactivate the user's account in the Zulip administration
 | 
					 | 
				
			||||||
  interface (`/#administration`); this will automatically also
 | 
					 | 
				
			||||||
  deactivate any bots the user had created.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* The Zulip mobile apps authenticate to the server by sending the
 | 
					 | 
				
			||||||
  user's password and retrieving the user's API key; the apps then use
 | 
					 | 
				
			||||||
  the API key to authenticate all future interactions with the site.
 | 
					 | 
				
			||||||
  Thus, if a user's phone is lost, in addition to changing passwords,
 | 
					 | 
				
			||||||
  you should rotate the user's Zulip API key.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Zulip bots are used for integrations.  A Zulip bot can do everything
 | 
					 | 
				
			||||||
  a normal user in the realm can do including reading other, with a
 | 
					 | 
				
			||||||
  few exceptions (e.g. a bot cannot login to the web application or
 | 
					 | 
				
			||||||
  create other bots).  In particular, with the API key for a Zulip
 | 
					 | 
				
			||||||
  bot, one can read any message sent to a public stream in that bot's
 | 
					 | 
				
			||||||
  realm.  A likely future feature for Zulip is [limited bots that can
 | 
					 | 
				
			||||||
  only send messages](https://github.com/zulip/zulip/issues/373).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Certain Zulip bots can be marked as "API super users"; these special
 | 
					 | 
				
			||||||
  bots have the ability to send messages that appear to have been sent
 | 
					 | 
				
			||||||
  by another user (an important feature for implementing integrations
 | 
					 | 
				
			||||||
  like the Jabber, IRC, and Zephyr mirrors).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### User-uploaded content
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Zulip supports user-uploaded files; ideally they should be hosted
 | 
					 | 
				
			||||||
  from a separate domain from the main Zulip server to protect against
 | 
					 | 
				
			||||||
  various same-domain attacks (e.g. zulip-user-content.example.com)
 | 
					 | 
				
			||||||
  using the S3 integration.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  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](https://github.com/zulip/zulip/issues/320)).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Zulip supports using the Camo image proxy to proxy content like
 | 
					 | 
				
			||||||
  inline image previews that can be inserted into the Zulip message
 | 
					 | 
				
			||||||
  feed by other users over HTTPS.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* By default, Zulip will provide image previews inline in the body of
 | 
					 | 
				
			||||||
  messages when a message contains a link to an image.  You can
 | 
					 | 
				
			||||||
  control this using the `INLINE_IMAGE_PREVIEW` setting.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
### 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.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Management commands
 | 
					## Management commands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										194
									
								
								docs/security-model.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								docs/security-model.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,194 @@
 | 
				
			|||||||
 | 
					# 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* It's reasonable to think about security for a Zulip server like you
 | 
				
			||||||
 | 
					  do security for a team email server -- only trusted administrators
 | 
				
			||||||
 | 
					  within an organization should have shell access to the 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Traffic between clients (web, desktop and mobile) and the Zulip is
 | 
				
			||||||
 | 
					  encrypted using HTTPS.  By default, all Zulip services talk to each
 | 
				
			||||||
 | 
					  other either via a localhost connection or using an encrypted SSL
 | 
				
			||||||
 | 
					  connection.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The preferred way to login to Zulip is using an SSO solution like
 | 
				
			||||||
 | 
					  Google Auth, LDAP, or similar.  Zulip stores user passwords using
 | 
				
			||||||
 | 
					  the standard PBKDF2 algorithm.  Password strength is checked and
 | 
				
			||||||
 | 
					  weak passwords are visually discouraged using the `zxcvbn` library,
 | 
				
			||||||
 | 
					  but Zulip does not by default have strong requirements on user
 | 
				
			||||||
 | 
					  password strength.  Modify the settings to adjust the password
 | 
				
			||||||
 | 
					  strength requirements (length and `zxcvbn` minimum quality).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Zulip requires CSRF tokens in all interactions with the web API to
 | 
				
			||||||
 | 
					  prevent CSRF attacks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* See
 | 
				
			||||||
 | 
					  [the authentication methods documentation](prod-authentication-methods.html)
 | 
				
			||||||
 | 
					  for details on Zulip's available authentication methods.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Messages and History
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Zulip message content is rendered using a specialized Markdown
 | 
				
			||||||
 | 
					  parser which escapes content to protect against cross-site scripting
 | 
				
			||||||
 | 
					  attacks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Zulip supports both public streams and private ("invite-only")
 | 
				
			||||||
 | 
					  streams.  Any Zulip user can join any public stream in the realm,
 | 
				
			||||||
 | 
					  and can view the complete message history of any public stream
 | 
				
			||||||
 | 
					  without joining the stream.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* A private ("invite-only") stream is hidden from users who are not
 | 
				
			||||||
 | 
					  subscribed to the stream.  Users who are not members of a private
 | 
				
			||||||
 | 
					  stream cannot read messages on the stream, send messages to the
 | 
				
			||||||
 | 
					  stream, or join the stream, even if they are a Zulip realm
 | 
				
			||||||
 | 
					  administrator.  Users can join private streams only when they are
 | 
				
			||||||
 | 
					  invited.  However, any member of a private stream can invite other
 | 
				
			||||||
 | 
					  users to the stream.  When a new user joins a private stream, they
 | 
				
			||||||
 | 
					  can see future messages sent to the stream, but they do not receive
 | 
				
			||||||
 | 
					  access to the stream's message history.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Zulip supports editing the content and topics of messages that have
 | 
				
			||||||
 | 
					  already been sent. As a general philosophy, our policies provide
 | 
				
			||||||
 | 
					  hard limits on the ways in which message content can be changed or
 | 
				
			||||||
 | 
					  undone. In contrast, our policies around message topics favor
 | 
				
			||||||
 | 
					  usefulness (e.g. for conversational organization) over faithfulness
 | 
				
			||||||
 | 
					  to the original.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* There are three types of users in a Zulip realm: Administrators,
 | 
				
			||||||
 | 
					  normal users, and bots.  Administrators have the ability to
 | 
				
			||||||
 | 
					  deactivate and reactivate other human and bot users, delete streams,
 | 
				
			||||||
 | 
					  add/remove administrator privileges, as well as change configuration
 | 
				
			||||||
 | 
					  for the overall realm (e.g. whether an invitation is required to
 | 
				
			||||||
 | 
					  join the realm).  Being a Zulip administrator does not provide the
 | 
				
			||||||
 | 
					  ability to interact with other users' private messages or the
 | 
				
			||||||
 | 
					  messages sent to private streams to which the administrator is not
 | 
				
			||||||
 | 
					  subscribed.  However, a Zulip administrator subscribed to a stream
 | 
				
			||||||
 | 
					  can toggle whether that stream is public or private.  Also, Zulip
 | 
				
			||||||
 | 
					  realm administrators have administrative access to the API keys of
 | 
				
			||||||
 | 
					  all bots in the realm, so a Zulip administrator may be able to
 | 
				
			||||||
 | 
					  access messages sent to private streams that have bots subscribed,
 | 
				
			||||||
 | 
					  by using the bot's credentials.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  In the future, Zulip's security model may change to allow realm
 | 
				
			||||||
 | 
					  administrators to access private messages (e.g. to support auditing
 | 
				
			||||||
 | 
					  functionality).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Every Zulip user has an API key, available on the settings page.
 | 
				
			||||||
 | 
					  This API key can be used to do essentially everything the user can
 | 
				
			||||||
 | 
					  do; for that reason, users should keep their API key safe.  Users
 | 
				
			||||||
 | 
					  can rotate their own API key if it is accidentally compromised.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* To properly remove a user's access to a Zulip team, it does not
 | 
				
			||||||
 | 
					  suffice to change their password or deactivate their account in the
 | 
				
			||||||
 | 
					  SSO system, since neither of those prevents authenticating with the
 | 
				
			||||||
 | 
					  user's API key or those of bots the user has created.  Instead, you
 | 
				
			||||||
 | 
					  should deactivate the user's account in the Zulip administration
 | 
				
			||||||
 | 
					  interface (`/#administration`); this will automatically also
 | 
				
			||||||
 | 
					  deactivate any bots the user had created.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* The Zulip mobile apps authenticate to the server by sending the
 | 
				
			||||||
 | 
					  user's password and retrieving the user's API key; the apps then use
 | 
				
			||||||
 | 
					  the API key to authenticate all future interactions with the site.
 | 
				
			||||||
 | 
					  Thus, if a user's phone is lost, in addition to changing passwords,
 | 
				
			||||||
 | 
					  you should rotate the user's Zulip API key.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Zulip bots are used for integrations.  A Zulip bot can do everything
 | 
				
			||||||
 | 
					  a normal user in the realm can do including reading other, with a
 | 
				
			||||||
 | 
					  few exceptions (e.g. a bot cannot login to the web application or
 | 
				
			||||||
 | 
					  create other bots).  In particular, with the API key for a Zulip
 | 
				
			||||||
 | 
					  bot, one can read any message sent to a public stream in that bot's
 | 
				
			||||||
 | 
					  realm.  A likely future feature for Zulip is [limited bots that can
 | 
				
			||||||
 | 
					  only send messages](https://github.com/zulip/zulip/issues/373).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Certain Zulip bots can be marked as "API super users"; these special
 | 
				
			||||||
 | 
					  bots have the ability to send messages that appear to have been sent
 | 
				
			||||||
 | 
					  by another user (an important feature for implementing integrations
 | 
				
			||||||
 | 
					  like the Jabber, IRC, and Zephyr mirrors).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## User-uploaded content
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Zulip supports user-uploaded files; ideally they should be hosted
 | 
				
			||||||
 | 
					  from a separate domain from the main Zulip server to protect against
 | 
				
			||||||
 | 
					  various same-domain attacks (e.g. zulip-user-content.example.com)
 | 
				
			||||||
 | 
					  using the S3 integration.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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](https://github.com/zulip/zulip/issues/320)).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Zulip supports using the Camo image proxy to proxy content like
 | 
				
			||||||
 | 
					  inline image previews that can be inserted into the Zulip message
 | 
				
			||||||
 | 
					  feed by other users over HTTPS.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* By default, Zulip will provide image previews inline in the body of
 | 
				
			||||||
 | 
					  messages when a message contains a link to an image.  You can
 | 
				
			||||||
 | 
					  control this using the `INLINE_IMAGE_PREVIEW` setting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 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.
 | 
				
			||||||
		Reference in New Issue
	
	Block a user