Report it privately through GitHub: Security → Report a vulnerability on this repository. Do not open a public issue. Only the latest release is supported; fixes go into a new release.
The service forwards notifications; it holds no data of its own. What it posts comes from GitHub, ClickUp or a script, and goes to the rooms that asked for it. The worst a forged delivery can do is a false message in a room; nothing it receives runs, changes a room's settings or reaches another system.
- GitHub and ClickUp: a delivery counts only with a valid signature of the body (HMAC-SHA256 with the secret of the webhook, compared in constant time). Without a secret, before an admin enables the integration, the endpoint answers 503.
- Scripts: a message counts only with the token of a hook. The bot keeps the SHA-256 of the token, never the
token, and sends the URL only to who created the hook, in a new direct room: the other members of the room, guests
included, never see it. A leaked token lets whoever has it post as that hook, in its room only, until
!hooks revoke. The reverse proxy keeps no access log of/send/, where the token is in the path. - The homeserver: the appservice paths (
/_matrix/app/) count only with thehs_tokenof the registration. The reverse proxy does not forward them; the homeserver reaches the service directly. - Commands: the integrations are enabled and disabled only by the users in
admins, in a room whose only members are the admin and the bot (checked before answering), created without encryption since the bot refuses encrypted rooms: the replies carry the secrets. Subscriptions and hooks are created and removed only by the moderators of the room (the power level needed to changem.room.power_levels, or above).
| Secret | Where | Who can read it |
|---|---|---|
as_token, hs_token |
the settings file (mode 0640) |
root and the user of the service |
| secret of the GitHub webhook | account data of @github on the homeserver |
the bot; the admins of the homeserver (!admin query account-data) and root on its machine |
| ClickUp API token and webhook secret | account data of @clickup |
as above |
| tokens of the hooks | nowhere: only their SHA-256, in the account data of @hooks for the room |
nobody, the hash as above |
Subscriptions are in the account data of the bot for each room, not in the state of the room: a bot joins without the
power to write state, and the members do not need to see them (!github list shows them). The account data of the
bots is kept and backed up by the homeserver, like the messages: old backups keep a rotated
secret until they expire, so a leaked ClickUp token is revoked in ClickUp, not only replaced in the bot. The message
with the ClickUp token is redacted as soon as it is read, when the bot has the power to; otherwise the bot asks the
admin to delete it. Until the homeserver prunes it, it is readable like any other message of that direct room.
The ClickUp token is personal: the bot reads with it the tasks of the deliveries, so it sees what that person sees, and its messages go only to the rooms that subscribed to a list, folder or space.
- No encrypted rooms: a bot declines invitations to them, and every bot leaves a room that turns encrypted. This follows the cryptography policy of optionfactory's ISO 27001 documents: bots never sit in end-to-end encrypted rooms, and notifications about a client go only to that client's room.
- Notices: messages go out as
m.notice, except failures.
The service logs, to the journal, the rejected deliveries with the address of the sender (from X-Forwarded-For only
when the connection comes from trusted_proxy, otherwise the address of the connection) and the failures to reach
the homeserver. Accepted deliveries are logged with their kind only; their content goes to the rooms, not to the logs.
A single static binary (musl), released on GitHub with SHA256SUMS, and packaged in the signed APT repository
linux-packages. The dependencies are few: axum and tokio for
the service, ureq with rustls for the calls to the homeserver and to ClickUp, ring for the signatures and the
hashes, hex, serde, serde_json, toml and clap.