Skip to content
Security architecture

Security architecture

General considerations

Zen’s security is of critical importance. Since it’s designed to handle all HTTP/HTTPS egress traffic from a user’s computer, any potential vulnerability could seriously compromise privacy and security. We therefore try our best to secure both the application itself and its surrounding infrastructure. This document outlines the specific security measures we take to protect the application and its users.

Zen is open-source and developed in public. One of the key strengths of open-source software is that it allows for public scrutiny and peer review. I personally appreciate the way Meredith Whittaker, the president of Signal, articulates this in the context of Signal: YouTube link (14:34), and I believe her argument applies just as strongly to our project.

Security is always a work in progress, and we encourage informed and good-faith discussions and suggestions. If you have an idea or expertise you’d like to share - reach out to us in public or in private and we’ll be happy to discuss it. Please note that this invitation does not apply to vulnerability reports. If you believe you’ve found a vulnerability in Zen, please follow the responsible disclosure process outlined in SECURITY.md.

Application-level security

In addition to standard security practices - writing Zen in a memory-safe language, using static analysis tools, vetting project dependencies, and more - we take the following specific steps to ensure application security:

Protection against CA compromise

To enable its content blocking and privacy protection features, Zen generates and installs a root CA certificate on the user’s computer. We, the project developers, wish there were a less intrusive way to achieve this, but there unfortunately isn’t one. That said, here’s what we do to protect users against potential CA compromise:

  • The CA public/private key pair is generated locally on the user’s computer.
  • The private key is never sent to any remote server.
  • By default, the private key is stored in a file with minimal permissions (0600) to reduce (though not eliminate) the risk of it being compromised by malicious processes running on the same computer.

You can verify these claims by reviewing the relevant code in keybackend.go.

On macOS and Windows, you can instead keep the private key in your computer’s security hardware, where it can’t be extracted. See About the hardware-backed CA key.

No proxying for sensitive hostnames

Zen configures the system proxy using a PAC script (see the implementation). It lets Zen specify a list of hostnames it shouldn’t proxy traffic to. There’s a list common to all platforms, as well as platform-specific lists for Windows and macOS. The common list includes the following categories:

  • Sensitive
  • Login (auth gateways)
  • Government and eGov websites
  • Password managers
  • Banks and financial institutions
  • Payment processors
  • Messaging services
  • Digital infrastructure providers (e.g. AWS, Azure, Google Cloud)

We encourage users to suggest additional entries for this list - both within the current categories and potentially new ones. You can also exclude hosts yourself with the Ignored hosts setting.

Platform-specific lists include hosts identified by OS vendors as ones that should not be proxied. See the Windows list and the macOS list for details.

Infrastructure-level security

GitHub repository

Zen’s source code is hosted on GitHub. We apply the following security measures:

  • Two-factor authentication (2FA) is required for all organisation members.
  • Changes to the main branch go through pull requests, which must pass lint checks before being merged.
  • Only project leads can create and modify release tags and releases.
  • CI actions follow best practices, such as minimal privileges and pinned action versions.

Immutable releases

Zen’s releases are immutable. Once a release is published, it - and the associated Git tag - cannot be modified. This ensures that a potential attacker cannot silently inject malicious binaries into an existing release.

To verify that a release is immutable, check for the “Immutable” label below the title on the release page.

To learn more about immutable releases, see GitHub’s documentation.

Artifact attestations

Zen’s artifacts, including release assets listed in our GitHub README and on the project website, are built via GitHub CI. The CI uses artifact attestations to provide cryptographically verifiable proof of their provenance and integrity. In particular, the attestations allow you to verify that:

  1. The artifact was indeed built by GitHub CI.
  2. The artifact was built from the source code at the listed commit.
  3. The artifact was not tampered with after the build or release.

To verify an attestation, install the GitHub CLI and run:

gh attestation verify PATH/TO/YOUR/BUILD/ARTIFACT-BINARY -R irbis-sh/zen-desktop

Note: If you’ve downloaded an archived artifact, the attestation will verify only the archive itself - not the individual files inside it.

Code signing

Windows builds are signed with a certificate provided by SignPath Foundation. macOS builds are signed with the project’s Apple developer certificate and notarised by Apple. Linux builds aren’t signed; use artifact attestations to verify them.

Update delivery (work in progress)

Zen checks for updates by downloading a small manifest from a private Cloudflare R2 bucket. The manifest holds the latest version number, the download URL of the matching GitHub release asset, and that asset’s SHA-256 hash. Zen downloads the asset, checks the hash, and installs the update. Because updates come from GitHub releases, they are covered by the immutable releases and attestations described above.

Zen doesn’t verify the attestation itself before installing, though. The hash only protects against a corrupted download, not against someone who could gain write access to the bucket and point Zen at a malicious update. We take care to safeguard access to the bucket, but we recognise that this is not a sufficient guarantee of security or integrity.

To address this, we plan to adopt a more robust and verifiable update mechanism in the future. Specifically, we will:

  • Sign all update binaries with a project-owned key.
  • Verify the signatures at runtime before installing updates.

As always, if you have experience in secure update delivery or would like to help us improve this system, please reach out - we welcome any kind of help and collaboration.