Advanced URL Filtering for Matrix
Morpheus is a Maubot plugin that scans incoming messages in Matrix rooms for URLs and checks them against configurable blacklists and whitelists.
Feature Overview
Available Commands
Public Commands (for all users)
| Command | Description |
|---|---|
!urlstatus <domain> |
Shows whether a domain is whitelisted, blacklisted, or unknown â including wildcard and apex matches. Also accepts full URLs. |
!stats |
Outputs the number of loaded domains, wildcards, and open reviews. |
!hilfe |
Shows the full command overview â only via direct message (DM). In group rooms, the bot is completely silent. |
!status |
Shows current bot status including database connection, uptime, and version. |
Moderation Commands (require permission)
A user is considered a moderator if their power level in the moderation room is at least min_power_level (default: 50) or their user ID is listed in allowed_users.
| Command | Description |
|---|---|
!allow <domain> |
Immediately whitelist a domain. Supports wildcards: !allow *.trusted-site.de |
!unallow <domain> |
Remove a domain or wildcard entry from the whitelist. |
!block <domain> |
Immediately blacklist a domain. Supports wildcards: !block *.evil-site.com |
!unblock <domain> |
Remove a domain or wildcard entry from the blacklist. |
!reloadlists |
Reload all .txt files â no restart needed. |
!pending |
Shows all domains currently awaiting a moderation decision. |
!sendpending |
Resends all open review alerts to the mod room. |
!mute <@user:server> [-t min.] |
Manually mute a user (powerlevel -1). Optional -t parameter sets duration in minutes. |
!unmute <@user:server> |
Manually unmute a user. |
!ignore <domain> |
Add a domain to the preview ignore list. |
!unignore <domain> |
Remove a domain from the preview ignore list. |
Emoji Reactions in Moderation Room
When an unknown domain is detected, the bot posts an alert message in the moderation room with two reaction buttons:
- â â Add domain to whitelist and approve the original message.
- â â Add domain to blacklist.
Reactions from users without sufficient permission are silently ignored.
How the Bot Recognizes URLs
The bot uses four stages applied sequentially to each message:
All extracted domains are normalized before list comparison â full-width characters (like īŊīŊīŊīŊīŊīŊ .com) and Unicode domains are converted to their Punycode form via IDNA.
Wildcard Entries
With the *. prefix, entire domain families can be captured at once:
!block *.evil-site.com â blocks sub.evil-site.com, api.evil-site.com, ...
!allow *.trusted-site.de â whitelists all subdomains
| Checked Domain | Entry | Match? |
|---|---|---|
sub.banned.com |
*.banned.com |
â Yes â Wildcard |
api.banned.com |
*.banned.com |
â Yes â Wildcard |
banned.com |
*.banned.com |
â No â Wildcard only covers subdomains |
sub.banned.com |
banned.com (exact) |
â Yes â Apex Match |
a.b.banned.com |
banned.com (exact) |
â Yes â Apex Match |
To also block the main domain itself, banned.com and *.banned.com must be added as two separate entries.
Configuration Options
These options are defined in base-config.yaml and can be overridden per instance in the Maubot dashboard.
Basic Configuration
| Parameter | Default | Description |
|---|---|---|
blacklist_dir |
/data/blacklists/ |
Directory containing blacklist .txt files. |
whitelist_dir |
/data/whitelists/ |
Directory containing whitelist .txt files. |
mod_room_id |
(Required) | Matrix room ID of the moderation room (format: !xxx:homeserver). |
mod_permissions.min_power_level |
50 |
Minimum power level for moderation actions. 100 = admin only, 0 = everyone. |
mod_permissions.allowed_users |
[] |
YAML array of user IDs with fixed moderation permission. |
command_rooms |
[] |
List of room IDs where the bot responds to commands. |
Privacy / GDPR
| Parameter | Default | Description |
|---|---|---|
secret_salt |
(Required) | Random secret key for SHA-256 user hashing. Generate with: python3 -c "import secrets; print(secrets.token_hex(32))" |
Link Previews
| Parameter | Default | Description |
|---|---|---|
enable_link_previews |
true |
Enable link previews for whitelisted URLs. |
link_preview_timeout |
5 |
HTTP timeout in seconds for preview fetches. |
Spam Protection & Auto-Mute
| Parameter | Default | Description |
|---|---|---|
warn_cooldown |
60 |
Warning cooldown in seconds. |
mute_enabled |
false |
Enable automatic muting. |
mute_threshold |
5 |
Number of violations within the observation window. |
mute_window_minutes |
5 |
Observation window in minutes. |
mute_duration_minutes |
60 |
Duration of automatic mute (0 = unlimited). |
mute_commands_enabled |
true |
Enable manual !mute and !unmute commands. |
global_mute |
true |
Global muting across all bot rooms. |
Docker Installation
Prerequisites
- Maubot running in Docker (standard image:
dock.mau.dev/maubot/maubot) - Maubot runs as UID/GID 1337 in the container by default
Step 1 â Package Plugin
cd /path/to/plugin
zip -r url_filter.mbp \
maubot.yaml base-config.yaml main.py \
blacklists/custom.txt blacklists/ignore.txt whitelists/custom.txt
Step 2 â Upload Plugin
- Open Maubot dashboard:
https://your-server/_matrix/maubot/#/plugins - Click "Upload plugin" and upload the .mbp file
- Create new instance, assign bot client, and save
Step 3 â Create Directory Structure
mkdir -p ./data/blacklists ./data/whitelists
touch ./data/blacklists/custom.txt
touch ./data/whitelists/custom.txt
Step 4 â Place Blacklist Files
Place hostfile-formatted .txt files in ./data/blacklists/.
Suitable sources:
- oisd.nl â various categories
- StevenBlack/hosts â consolidated lists
- The Block List Project â sorted by category
./data/blacklists/
âââ malware.txt
âââ phishing.txt
âââ scam.txt
âââ custom.txt â managed by bot
Step 5 â Set Permissions â ī¸
Since Maubot in the container runs as UID 1337, the directories must be owned by this user. Without correct permissions, the bot cannot write to custom.txt.
chown -R 1337:1337 ./data/blacklists ./data/whitelists
Step 6 â Configure Instance
In the Maubot dashboard, set at least the following values:
blacklist_dir: /data/blacklists/
whitelist_dir: /data/whitelists/
mod_room_id: "!YOUR_MOD_ROOM_ID:homeserver.example"
secret_salt: "your-random-salt-here"
Step 7 â Invite Bot to Rooms
- Invite bot to all rooms to monitor
- Set bot to Powerlevel 50 (Moderator) in these rooms
- Invite bot to the moderation room and grant write permissions
- If using Auto-Mute: set bot to Powerlevel 100 (Admin)
Troubleshooting
chown -R 1337:1337 ./data/blacklists ./data/whitelistsdatabase: true and database_type: asyncpg are set in maubot.yaml.Packaging & Deployment
Repackage after source file changes:
zip -r url_filter.mbp \
maubot.yaml base-config.yaml main.py \
blacklists/custom.txt blacklists/ignore.txt whitelists/custom.txt
Upload the updated .mbp in the Maubot dashboard and restart the instance.
Place new .txt files in ./data/blacklists/, check permissions, then enter !reloadlists in the moderation room â no restart needed.
Requirements
| Component | Minimum Version |
|---|---|
| Maubot | >= 0.4.0 |
| mautrix-python | >= 0.20.0 |
| Python | >= 3.10 |