{"id":13618845,"url":"https://github.com/quarkslab/mattermost-plugin-e2ee","last_synced_at":"2026-02-03T10:38:35.404Z","repository":{"id":39993306,"uuid":"411810922","full_name":"quarkslab/mattermost-plugin-e2ee","owner":"quarkslab","description":"End-to-end encryption plugin for Mattermost","archived":false,"fork":false,"pushed_at":"2024-07-19T12:24:07.000Z","size":1332,"stargazers_count":69,"open_issues_count":29,"forks_count":10,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-04-14T15:48:58.207Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quarkslab.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-29T19:53:31.000Z","updated_at":"2025-03-08T19:06:26.000Z","dependencies_parsed_at":"2024-11-08T05:31:42.686Z","dependency_job_id":"4d4a005f-b1dc-41ca-9706-7555783ed6f5","html_url":"https://github.com/quarkslab/mattermost-plugin-e2ee","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/quarkslab/mattermost-plugin-e2ee","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarkslab%2Fmattermost-plugin-e2ee","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarkslab%2Fmattermost-plugin-e2ee/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarkslab%2Fmattermost-plugin-e2ee/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarkslab%2Fmattermost-plugin-e2ee/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quarkslab","download_url":"https://codeload.github.com/quarkslab/mattermost-plugin-e2ee/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quarkslab%2Fmattermost-plugin-e2ee/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29041862,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T10:09:22.136Z","status":"ssl_error","status_checked_at":"2026-02-03T10:09:16.814Z","response_time":96,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T21:00:31.281Z","updated_at":"2026-02-03T10:38:35.387Z","avatar_url":"https://github.com/quarkslab.png","language":"TypeScript","funding_links":[],"categories":["Communication and Collaboration Tools","TypeScript"],"sub_categories":[],"readme":"\u003cdiv align=\"center\" width=\"100%\"\u003e\n  \u003cimg width=\"20%\" src=\"assets/logo.svg\" /\u003e\n\u003c/div\u003e\n\n# Mattermost E2EE plugin (by [Quarkslab](https://quarkslab.com))\n\nThis plugin brings end-to-end encryption (E2EE) to Mattermost. It uses the\n[WebCrypto\nAPI](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API), and [non\nextractable private\nkeys](https://www.w3.org/TR/WebCryptoAPI/#dfn-CryptoKey-extractable). See [the\ndesign document](docs/design.md) for more details on the attack models\nconsidered and the cryptographic schemes used.\n\nPlease **carefully read** the [known limitations](#known-limitations) before\nusing of this plugin. \n\nThis document describes how to [install](#installation) the plugin, it contains\nthe [end user documentation](#quick-start) and [instructions to setup a\ndeveloper environment](#development).\n\n\u003cdiv align=\"center\" width=\"100%\"\u003e\n  \u003cimg width=\"40%\" src=\"docs/screenshot.png\"\u003e\n\u003c/div\u003e\n\n## Installation\n\nYou can download the [latest release\narchive](https://github.com/quarkslab/mattermost-plugin-e2ee/releases) and\nupload it in Mattermost's system console: open `Main Menu \u003e System Console \u003e\nPlugins (BETA) \u003e Plugin Management \u003e Upload Plugin` to upload the archive.\nUpgrades can be performed by importing the latest release and confirming the\noverwriting of the duplicate plugin ID.\n\n### Plugin configuration\n\nThe plugin has a few configuration entries:\n\n### URL of the GPG key server\n\nIt contains the URL of a GPG key server used to gather a GPG public key that\nbelongs to the user. It uses the [HKP\nprotocol](https://datatracker.ietf.org/doc/html/draft-shaw-openpgp-hkp-00) to\nsearch for a valid key for the user's email address. This public GPG key is\nthen used to encrypt the user's [E2EE private key on\nkey initialisation](#private-key-generation--backup). Leave empty if you don't\nwant GPG encrypted backup of users' private keys.\n\n### Allow Bots to always post\n\nWe prevent unencrypted messages to be posted on encrypted channels. This allows\nbot users to override this rule.\n\n### Custom messages types to always allow\n\nWe prevent unencrypted messages to be posted on encrypted channels. This\nsetting allows some custom message types to override this rule. The list should\nbe comma separated. For instance, if you want the [Jitsi\nplugin](https://github.com/mattermost/mattermost-plugin-jitsi) to work even on\nencrypted channels, you can set `custom_jitsi` here.\n\n## Quick start\n\n`/e2ee init` generates your private key and displays a backup you can save in a\nsecure location. If it manages to do so, it will also send a GPG encrypted\nbackup of that private key. In that case, you will be asked to verify the GPG\nkey server used and the public key ID retrieved are legit.\n\n`/e2ee start` sets the current channel in encryption mode. This means that\nevery message sent on that channel must be encrypted. `/e2ee stop` puts the\nchannel back in clear text mode.\n\n`/e2ee help` shows a help message with the available commands.\n\n## Persistent storage on Firefox\n\nWe use [persistent storage on\nFirefox](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Browser_storage_limits_and_eviction_criteria#different_types_of_data_storage),\nso that your private key doesn't get deleted by Firefox, forcing you to\nreimport it on a recurrent basis. Firefox will ask you to accept for the\nMattermost instance to do so. Click on `Accept` if that's something you wish.\n\n## Detailed usage instructions\n\n### Private key generation \u0026 backup\n\nThe `/e2ee init` command generates your private key:\n\n\u003cdiv align=\"center\" width=\"100%\"\u003e\n  \u003cimg width=\"70%\" src=\"docs/keygen.png\" /\u003e\n\u003c/div\u003e\n\nAs we can see in the screenshot above, the plugin dumps a **clear text**\nversion of your private key, that you can backup in a secure password storage,\nlike [KeePass](https://keepass.info/). Make sure that you have the full text\nbetween `----BEGIN MM E2EE PRIVATE KEY----` and `----END MM E2EE PRIVATE\nKEY-----`, with these headers included.\n\nMoreover, if a GPG server key has been configured, and a public key associated\nwith your Mattermost account's email exists, you will be asked to verify that\nthe GPG key server used to get that key and the public key ID retrieved itself\nare legit. If you confirm, you will receive a GPG encrypted backup of your\nprivate key.\n\n\u003cdiv align=\"center\" width=\"100%\"\u003e\n  \u003cimg width=\"70%\" src=\"docs/gpgbackup.png\" /\u003e\n\u003c/div\u003e\n\nThis backup can then be used to reimport your private key in another browser.\n\n### Private key import\n\nThe `/e2ee import` command shows a dialog box where you can paste your private\nkey backup:\n\n\u003cdiv align=\"center\" width=\"100%\"\u003e\n  \u003cimg width=\"60%\" src=\"docs/import.png\" /\u003e\n\u003c/div\u003e\n\nIf you try to import a key that has a public counterpart different from the one\nknown by the server, a message will ask you to confirm this action. Indeed,\nchanging your public key will have the consequence that no one will be able to\nauthenticate your **old** messages anymore. The plugin will refuse to show\nthem, and show an `integrity check failed` error.\n \n### Channel encryption\n\nThe choice whether messages are encrypted or not is done on a per-channel\nbasis. The `/e2ee start` command activates encryption on the current channel:\n\n\u003cdiv align=\"center\" width=\"100%\"\u003e\n  \u003cimg width=\"50%\" src=\"docs/start.png\" /\u003e\n\u003c/div\u003e\n\nWhen encryption is activated for a channel, but some people still haven't\n[setup a private key](#private-key-generation-backup), a message shows you who\nwill not be able to read the messages on the channel:\n\n\u003cdiv align=\"center\" width=\"100%\"\u003e\n  \u003cimg width=\"70%\" src=\"docs/start_missing_keys.png\" /\u003e\n\u003c/div\u003e\n\n`/e2ee stop` deactivates encryption for the current channel. If encryption\nhasn't been deactivated by *you* on a channel, you will be prompted by a\nmessage asking you to confirm you want to send unencrypted messages on this\nchannel the next time you send a post.\n\nPrivate messages work like the other channels, and the same commands can be used.\n\n## Known limitations\n\n### Files/attachments not encrypted\n\nFor now, files \u0026 attachments are **not encrypted**. This will be done in future\nreleases (if possible).\n\nProgress on this issue is tracked in [#7](https://github.com/quarkslab/mattermost-plugin-e2ee/issues/7).\n\n### Webapp integrity\n\nIn the attack model where the server is considered as compromised, nothing\nprevents the server from serving malicious Javascript code that could send clear\ntext messages alongside their encrypted counterpart. Moreover, code could also be injected to\ndecrypt old messages. This problem is described in detail\n[here](https://www.pageintegrity.net/browsercrypto.php#thebrowsercryptochickenandeggproblem).\n\nNote that, as the private key is kept as *non extractable* in the browser, even\nmalicious Javascript code can't just extract and dump your private key. It\nwould need to exploit a vulnerability in the browser itself (but you might have\nbigger issues at this moment).\n\nThe Firefox [Page Integrity](https://www.pageintegrity.net/) plugin could help\nsolve this problem, by checking that the shipped Mattermost web application is\nknown against a list of known hashes. Unfortunately (in this case), Mattermost\nplugins' Javascript code is \"dynamically\" loaded by the main Mattermost\napplication, so bypassing this check in some ways.\n\nFixing this is work-in-progress, and any help or suggestions would be\nappreciated! Please refer to ticket\n[#6](https://github.com/quarkslab/mattermost-plugin-e2ee/issues/6).\n\n### Initial support for notifications from mentions\n\nMentions (like `@all`) in encrypted messages would display a notification, but\nwith these limitations:\n\n* the notification sound might not be played, depending on the OS \u0026 platform\n* \"activating\" the notification would display the Mattermost application/tab,\n  but won't switch to the team/channel were the notification occured\n\nFixing these issues could be done by being able to use the [notifyMe function\nfrom\nmattermost-webapp](https://github.com/mattermost/mattermost-webapp/blob/53abea64747ffaf4937a65e26b697d4703bfc22b/actions/notification_actions.jsx#L192),\nwhich could be [exposed to\nplugins](https://github.com/mattermost/mattermost-webapp/blob/ce2962001c11d7a55cbd6bf146f94ab0b98496e4/plugins/export.js).\n\nProgress on this issue is tracked in [#1](https://github.com/quarkslab/mattermost-plugin-e2ee/issues/1).\n\n### Unable to update messages (Mattermost \u003c 6.1 \u0026\u0026 \u003e= 6.4)\n\n**Note**: this limitation only exists if you use Mattermost \u003c 6.1 or \u003e= 6.4\n\nDue to a [limitation in\nMattermost \u003c 6.1](https://github.com/mattermost/mattermost-server/issues/18320), it\nis not possible in these versions for a webapp plugin to intercept message modifications.\nThus, we are not able to encrypt the modified message before it is transmitted\nto the server.\n\nFor Mattermost versions \u003e= 6.4, there are two problems. The first one is for\nversions 6.4 \u0026 6.5. Indeed, [this\ncommit](https://github.com/mattermost/mattermost-webapp/commit/8a925e8f95f9a8e9b81512de8203c7163c5d1eea)\nintroduces a \"regression\" (whether this is a regression or not depends on the\nsemantics of [this plugin\ninterface](https://developers.mattermost.com/integrate/plugins/webapp/reference/#registerMessageWillBeUpdatedHook),\nwhich isn't clear), and removes posts \"properties\" while updating messages,\nwhich we use to store the actual encrypted message. That's why modifying a\nmessage won't work for these two versions. That being said, it won't leak the\ndecrypted message to the server, so we keep it this way not to break\nthreads/replies (see below). The second one is for versions \u003e= 6.6. The editing\npost widget has been fully rewritten with an \"inline\" mode. Unfortunately, this\nrewrite completely forgot to call update hooks, so we are back to the pre-6.1\nbehavior :(\n\nSo, for versions \u003c 6.1 and \u003e= 6.6, if you try to modify a message, you will be\nprompted with a warning message instead of the original one. We've done this to\nprevent accidental leakage of decrypted messages to the server. Indeed, when\nyou click on the `Save` button, the content of the modified message is sent in\nplain text to the server.\n\n### Broken thread/reply UI (Mattermost \u003c 6.1 \u0026\u0026 \u003e= 6.6)\n\n**Note**: this limitation only exists if you use Mattermost \u003c 6.1 or \u003e= 6.6\n(see above for explanation about this regression).\n\nDue to the previous limitation, when you reply to an encrypted message, the\nwarning message discussed above will be shown instead of the decrypted one:\n\n\u003cdiv align=\"center\" width=\"100%\"\u003e\n  \u003cimg width=\"60%\" src=\"docs/thread_reply.png\" /\u003e\n\u003c/div\u003e\n\n## Development\n\nThis section describes how to setup a development environment.\n\n### Environment\n\nWe make a build environment based on Mattermost's [local node docker](https://docs.mattermost.com/install/setting-up-local-machine-using-docker.html).\n\nWe adapt the `mattermost/mattermost-preview` image to add various things:\n\n* enable the creation of tokens\n* enable the creation of accounts without invitations\n\nThe provided `docker/Dockerfile` will create a new docker image with these modifications.\n\nFirst, build the image:\n\n```\n$ cd docker \u0026\u0026 docker build -t matterdev .\n```\n\nThen, run the Mattermost instance. We need to mount `/var/tmp` as an external\nvolume to get a Mattermost unix socket that will help to easily deploy our plugin:\n\n```\n$ cd /path/to/project\n$ docker run --name mminstance -d --publish 8065:8065 --add-host dockerhost:127.0.0.1 matterdev\n```\n\nIt takes a few minutes to boot. You can then access the instance at `http://127.0.0.1:8065`. Create a user and a team.\n\nThe next step is to create a user token. Go to `Account Settings`, `Security` and\nadd a new personal token. This is needed to deploy the plugin (see below).\n\nTo rerun the docker container (if stopped), just do `docker start mminstance`. To\nrun a shell within this container, you can do `docker exec -it mminstance\n/bin/bash`.\n\n### Deploying\n\nBased on [these instructions](https://github.com/mattermost/mattermost-plugin-starter-template#deploying-with-local-mode).\n\nFirst, copy `dev.env.example` into `dev.example`, and setup the user token you\njust created above. Then:\n\n```\n$ source dev.env\n$ make watch\n```\n\nThis will do two things:\n\n* build the server plugin and upload it on the mattermost instance\n* build the webapp, watch for changes and rebuild it when a file changes\n\nNote that changing the server-side code requires at least doing `make deploy`\nto build \u0026 deploy the changes.\n\n### Build the plugin (release)\n\nBuild your plugin:\n```\nmake\n```\n\nThis will produce a single plugin file (with support for multiple\narchitectures) to upload to your Mattermost server:\n\n```\ndist/com.quarkslab.mm-e2ee.tar.gz\n```\n\n## Q\u0026A\n\n### How do I build the plugin with unminified JavaScript?\nSetting the `MM_DEBUG` environment variable will invoke the debug builds. The easiest way to do this is to simply include this variable in your calls to `make` (e.g. `make dist MM_DEBUG=1`).\n\n## Contributors\n\n* Adrien Guinet\n* Pierre Veber\n* Angèle Bossuat\n* Charlie Boulo\n* Guillaume Valadon\n\n## Acknowledgment\n\nSpecial thanks to the people who battle tested this on some underground\nMattermost instances!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquarkslab%2Fmattermost-plugin-e2ee","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquarkslab%2Fmattermost-plugin-e2ee","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquarkslab%2Fmattermost-plugin-e2ee/lists"}