Community Bans — Privacy
v1.3 · effective 2026-09-30 · what changed
The Community Bans feature aggregates BAN reports from unmask installs and republishes them as a community-curated list. This document covers what the hub stores, how long it keeps it, and what your rights look like under GDPR-style regimes.
What we collect from submitting installs
Submitting is off by default (submit_enabled: false) and requires
accepting the terms. A submitting install is
registered with the hub the same way a subscribing one is (see the next
section). Each report then adds:
- The IP address and JA4 fingerprint of the client your install reported (for a JA4 picked from the hunt page's ranking, the JA4 and one IP address seen with it). These belong to the third party your install observed, not to you.
- The reason and comment fields you chose to attach (free text, ≤ 280 chars for comments).
- The BAN source: whether the report came from a BAN on the hunt page or from a JA4 picked in its ranking. The hub uses it when deciding how an entry should match.
- The timestamp of the submission.
- Your install's HN and, if one is on record, its country code (see the next section), copied onto the report.
- A per-day salted hash of the submitting install's IP (= SHA-256(salt ‖ submitter_ip), where salt = SHA-256(server_secret ‖ "|" ‖ UTC date)). Used for abuse detection only. The raw IP is not stored in the hub's database, and because the salt changes every UTC day, the same address hashes differently on different days. The hash is scrubbed after 30 days.
What we collect from subscribing installs
Subscribing means pulling /api/feed/list.json once an hour, and it
is on by default: a new install has
subscribe_mode: fetch_apply (pull and enforce; fetch
pulls for browsing only). This section therefore applies to every install whose
operator has not set subscribe_mode to off. An install
with subscribing and submitting both off neither registers nor pulls.
Registration. Before its first pull, an install registers with the hub once. The hub generates the install's token (32 random bytes) and returns it; the install keeps it in its own configuration. The hub stores:
- The SHA-256 hash of the token. The raw token is not stored on the hub.
- A derived handle name (HN) (= "swift-otter-a3f7" style: adjective + noun + 4 hex chars). It is computed from the token alone, not from your hostname or anything else about your server, and the token cannot be recovered from it. It is shown next to your reports, votes, and comments as a stable pseudonym. If you set a display name in Settings, the install sends it when it registers or submits a report, and the hub stores it and shows it instead.
- A country code (= ISO 3166-1 alpha-2) for the install,
which the hub looks up from the registering IP address in a local
IP-to-country database while
publish_countryis on (default ON, so the feed reflects where contributing deployments are). It is looked up again each time the install submits a report with the setting on. The code is kept on the install's record and copied onto its reports, votes, and comments. Turning the setting off stops the lookups, but a code already on record stays there and is still copied onto new reports, votes, and comments. - A per-day salted hash of the registering IP address (same scheme as above), used to detect registration floods and scrubbed after 30 days.
- The registration time, a last-seen time (also updated when the install submits a report), and an abuse score the hub computes to give less weight to reports from installs it has flagged.
Pulls. While publish_liveness is on (the
default), each pull sends the install's token, and the hub updates that
token's last-seen time. The value replaces the previous one rather than
accumulating, so the hub's database holds one timestamp per install and no pull
history. It keeps nothing else about a pull: not the IP, not the frequency,
not a record of which pulls happened. (The web server's access log is
separate; see What we do not collect.) The feed you receive is
byte-for-byte the same whether or not the token is sent; the endpoint is public
and stays public.
Why we ask for it. Without it the hub cannot tell how many installs are running. A token's record moves only when that install registers or submits a report, so a deployment that has quietly consumed the feed for a year is indistinguishable from a registration that was abandoned a second after it was made. We would rather know the size of the thing we are running than guess at it.
It is optional. Turn off Count this install as running
in Settings → Community Bans (publish_liveness: false) and the
pull no longer carries the token. Subscribing, enforcement, and everything
else are unaffected.
What we collect from comments and votes
The browse UI lets registered installs attach 👍 / 👎 votes and text comments to other installs' submissions. For each vote / comment we store the same fields as a submission (token's HN, country code if one is on record, per-day salted IP hash), the parent submission id, and the vote kind ("like" / "bad") or comment text (≤ 280 chars).
What we collect from removal requests
The removal request form stores what is entered on it: what to remove (an HN or an IP address) and, if given, a reason and a contact address for our reply. It also stores a per-day salted hash of the requesting IP address (same scheme as above), used only to cap how many requests one address can leave pending in a day, and the request's status and times. How long each part is kept is under Retention below.
What we do not collect
- No name, no account, and no email address, except the contact a removal request may give (see above). No PII about the operator of an unmask installation.
- No URL paths, headers, cookies, or request bodies from the banned traffic.
- No analytics or tracking in the hub's API. The endpoints the daemon calls (register, pull, submit, vote, comment, aggregate) are plain JSON APIs, and no third party is involved in serving them. The unmask.sh web pages are a different matter: most of them, including the feed overview and browse pages, load Google Tag Manager, which runs Google Analytics to measure page views, and most also load web fonts from Google Fonts.
- No raw IP addresses of installs in the hub's database — only the per-day salted hashes described above, scrubbed after 30 days.
Web server logs. Like any web server, unmask.sh keeps an access
log of requests, requests to the feed API included: the requesting IP
address, the time, the request line, the response status, and the User-Agent
(for the daemon, unmask/<version>). The token is not written
to it.
What we publish
Public endpoints:
https://unmask.sh/api/feed/list.json— the single feed. Every aggregated entry is included, both promoted rows (= a match kind and an aggregate trust score ≥ 3) and reports-only rows (= everything else, listed for context). Each entry carries match kind, IP and/or JA4, confidence, score, a short reasoning string, the most recent report reason, the text and time of up to five recent report comments (without HNs), aggregated vote / comment counts, and the reporting deployment count. There is no local score threshold: which entries are enforced is decided on the hub, and each install sets what a match costs the visitor. The feed does not expose individual submission IDs; only the (ip, ja4) aggregate.https://unmask.sh/api/feed/aggregate?ip=&ja4=— per-pair detail. Returns the list of submissions, comments, and voters for that pair so users can audit the verdict. HNs, country codes, reasons, comment text, and submission timestamps are all visible here. It is a lookup by IP / JA4 and is not limited to the feed window: it returns every report the hub still holds for that pair./api/feed/entry/<id>returns the same details for a single report. Raw IP hashes are never returned.
Retention
Two separate windows apply:
- Public feed window. An entry only appears on
/api/feed/list.jsonwhile it is relevant to the feed's accuracy. Older entries rotate out automatically, so a one-off report from a long time ago does not keep showing up. An (ip, ja4) pair stays on the feed as long as at least one of its reports is still within this window; once the most recent report ages out, the pair disappears from the public feed. Subscribers see entries rotate naturally as the window slides. - Reporter IP hashes. The per-day salted hashes of an install's IP address (on its registration record, reports, votes, and comments) are scrubbed 30 days after the day they were recorded, independent of the public-feed window. After that, nothing in the hub's database is derived from the IP address of the install that submitted a report. Reports stay attributed to the install's HN, which is public.
- Internal record. Report records (target IP / JA4 /
reason / comment, with the reporting install's HN and country code) are kept
beyond the public feed window, with no automatic deletion, for score
integrity, long-term bot-pattern analysis, and the takedown audit trail.
Once rotated out they do not come back into
/api/feed/list.json, but the per-pair lookup described above still returns them. Reported parties who want a row removed from the hub entirely can request it via the removal form. - Comments and votes cascade-delete with their parent submission when a takedown removes one.
- Removal requests. The requester's IP hash is scrubbed 30 days after the request, and the optional contact 30 days after the request is answered. What was asked and what was done about it are kept as the record of the removal.
The aggregate score
The hub assigns each (ip, ja4) pair a 1-5 trust score based on how many distinct installs reported it, the like / bad vote ratio, and whether the reporting installs have been flagged for abuse. The hub can also ask an AI model for a second opinion (currently through Anthropic's Messages API). That request contains the reported IP and JA4 and the aggregate counts (reports, installs, votes, number of comments); a separate check, made when an entry would match on its JA4 alone, sends only the JA4 and counts. Nothing that identifies the reporting installs is sent: no tokens, HNs, country codes, IP hashes, or comment text. When the AI is consulted, its short reasoning string is published in the feed.
About reported IPs
Reported IPs are network identifiers that may correspond to natural persons.
Under GDPR-style regimes, the operator submitting the report is the controller
of that data in their own logs; unmask.sh processes it on the operator's
behalf solely for the purpose of running the community feed. The default
action is a challenge (pow_then_captcha), not a block, so
people behind shared IPs are served a challenge rather than refused outright;
an install's operator can choose deny instead.
Your rights and deletion
If you run an unmask install:
- Flipping
submit_enabledoff in your unmask config stops further submissions immediately. - Setting
subscribe_modetooffstops the pulls; turningpublish_livenessoff keeps pulling without the token. - You can delete your own submissions, comments, and votes individually from the Bans page in your admin UI (= the inline × buttons in the detail panel).
- To delete every row associated with your token at once, use the removal request form with the HN your install displays.
If you believe a reported IP is yours and should not be on the feed: use the removal request form with the IP. We will remove it from the feed.
Legal basis (GDPR mapping)
- Art. 5(1)(b) purpose limitation — data is used only for the Community Bans feature and abuse detection.
- Art. 5(1)(c) data minimization — raw IPs are not stored in
the hub's database, the country code depends on the operator's
publish_countrysetting (default ON; see above), no operator PII is collected. - Art. 5(1)(e) storage limitation — public-feed entries rotate out a fixed period after their most recent report; per-day salted IP hashes are scrubbed after 30 days, independent of how long report records are kept; a removal request's contact goes 30 days after it is answered.
- Art. 5(1)(f) integrity — server salt rotates daily, HN derivation is not reversible from public data.
- Art. 6(1)(f) legitimate interest — Recital 49 explicitly recognises network security and abuse prevention as a legitimate purpose.
- Art. 15 access / Art. 17 erasure — supported via the inline delete buttons and the removal request form address above.
- Art. 25 privacy by design — hash-and-rotate IP handling, an operator setting for the country code (default ON), default-OFF submission, a challenge rather than a block by default.
Changes
- v1.3 — 2026-09-30
- Added What we collect from removal requests, and their retention: the requester's IP hash is now scrubbed after 30 days, and the optional contact 30 days after the request is answered (both were kept without a limit before). Corrected What we do not collect, which said no email address is collected although the removal form's optional contact can be one.
- v1.2 — 2026-09-30
- Corrections only: no change to what installs send or what the hub stores.
Corrected: subscribing (pulling and enforcing the feed) is on by default; the
hub, not the install, generates the token, and registration also stores the
HN, a country code, a per-day salted IP hash, and timestamps; what turning
publish_countryoff does; the unmask.sh web pages use Google Tag Manager / Google Analytics, and the web server keeps access logs; what the optional AI second opinion receives, and its provider; there is no local score threshold, and the default action ispow_then_captcha; the per-pair lookup is not limited to the feed window. Added the BAN source to what a report stores. Removed a sentence saying re-reports are deprioritised after a takedown, which the hub does not do. - v1.1 — 2026-09-22
- Added What we collect from subscribing installs: a subscribing install may now send its token with the hourly feed pull so the hub can count running deployments, and the hub stores the time of the most recent pull against that token. Optional, and off with a single setting. No other section changed, and nothing collected under v1.0 changed meaning.
- v1.0 — 2026-05-27
- First published.
Contact
This document is not legal advice. unmask is an open-source project run by individuals; before relying on these policies for compliance in your jurisdiction, consult counsel. We welcome corrections via the contact address above.
See also: Terms of use.