Skip to content

fix: remove prefix.cc spam and stop refreshing prefix.cc by default - #86

Merged
kevinschaper merged 3 commits into
linkml:mainfrom
ASCS-eV:fix/prefixcc-spam
Nov 6, 2026
Merged

kevinschaper merged 3 commits into
linkml:mainfrom
ASCS-eV:fix/prefixcc-spam

Conversation

@jdsika

@jdsika jdsika commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Closes #61.

Problem

prefix.cc has no curation, and anyone can register a prefix there.

  • Every tagged release since v0.1.1 has shipped 7 to 13 spam or broken prefix.cc rows.
  • The spam removed by hand in Feb 2024 (d202004) came back with later refreshes.
  • main now has 15 such rows in prefixcc.csv and in each merged* context. Almost all are canonical, so for example load_converter("merged") compresses https://onlyfans.com/sammuwuu/x to fugas:x.
  • prefix.cc keeps changing. A refresh today would bring in more, such as leaks pointing at a different spam site.

The same problem has been reported to prefix.cc itself (cygri/prefix.cc#42). But prefix.cc's code hasn't changed since 2021, so we can't rely on it being fixed there.

Change

The PR has two commits, so the freeze can be dropped independently if you prefer.

  1. fix: remove the spam and block it from coming back

    • Adds src/prefixmaps/data/prefixcc.excluded.yaml, which lists excluded hosts (subdomains included) and prefixes, each with a reason.

    • from_prefixcc() drops matching entries before building the context.

    • The loader rejects unknown sections, so a typo can't silently disable exclusions.

    • Removes the 15 rows from prefixcc.csv, merged.csv, merged.monarch.csv and merged.oak.csv:

      Rows Why
      fugas, leaks, przecieki, veelana onlyfans profiles
      onlyfans cutt.ly short link
      faptica, check, dick adult sites
      rankrage, seokoeln SEO agency site
      fs, qualityze software product pages; qualityze is the spammer reported on Blacklisting spam sites cygri/prefix.cc#42
      type, ljkl teste.com junk
      bgcat prefix.cc serves this namespace with its Cyrillic replaced by ?
    • No other row shares a prefix or namespace with these, so no other row's status changes.

    • A new test (tests/test_core/test_prefixcc_exclusions.py) fails if any bundled context contains an excluded host, or an excluded prefix from prefix.cc. Run against main's data, it fails for prefixcc and all three merged contexts.

  2. feat: stop refreshing prefix.cc by default, as asked in freeze prefix.cc refreshes #61

    • The ETL uses the bundled prefixcc.csv snapshot, minus exclusions, so adding an exclusion takes effect on the next run.
    • Canonical rows are loaded first, because merging depends on the order in which rows arrive. In plain sorted-CSV order, 73 prefix.cc rows in merged would change. With canonical rows first, prefixcc.csv and all three merged CSVs rebuild byte for byte from the snapshot. So make etl causes no churn, and the CSV edits in this PR are exactly what the ETL now produces.
    • slurp-prefixmaps --refresh-prefixcc still downloads prefix.cc, and prints every added or removed prefix.cc row for review.
    • load_context(..., refresh=True) also uses the snapshot for prefix.cc. This is documented.
    • Semweb prefix fixes now belong in linked_data.curated.yaml, which already takes precedence over prefix.cc in the merged contexts. README and docs say so.

Not included

These look like junk rather than spam, so they're left for a maintainer to decide:

Prefix Namespace
sirext http://t.me/sirextt/247:
hello a YouTube channel
beth http://www.google.com/
twitter http://stocktwits.com/
leak http://maco.com/
da a wowman.org query URL
vwdms, vwgw intranet hosts
test, test2, meat example.com / .invalid placeholders

Each would be one line in prefixcc.excluded.yaml.

The pgo link rot mentioned in #61 needs no change. A namespace IRI doesn't have to resolve, and PGO is a real vocabulary.

Verification

  • An independent adversarial review re-checked:
    • the row removal (byte level, CRLF intact)
    • the rebuild identity, including order-independence on a fresh prefix.cc download and 20 random permutations
    • the host matching
    • the refresh=True behaviour
    • an end-to-end --refresh-prefixcc run into a temporary directory
    • the tox -e refresh path
  • Tests: mutation checks confirm the new tests fail if the ingest filter or the snapshot filter is removed, or with main's data.
  • Lint and suite: flake8 with the tox -e flake8 plugin set passes. The suite passes locally on Python 3.12 and 3.8, except test_w3id, which also fails on main and is fixed in fix: read w3id namespaces from ids/ after upstream move #84. CI will show that one failure until fix: read w3id namespaces from ids/ after upstream move #84 is merged.

prefix.cc has no curation. Every tagged release since v0.1.1 has
shipped 7 to 13 spam or broken prefix.cc rows. The spam removed by hand
in Feb 2024 came back with later refreshes. main has 15 such rows in
prefixcc and in each merged context:
- onlyfans profiles (fugas, leaks, przecieki, veelana)
- a cutt.ly short link (onlyfans)
- adult sites (faptica; check and dick on pornhub.com)
- commercial spam (rankrage and seokoeln on an SEO agency site; fs and
  qualityze on software product pages, qualityze also reported on
  prefix.cc)
- junk teste.com entries (type, ljkl)
- a namespace that prefix.cc serves corrupted (bgcat)

List them in prefixcc.excluded.yaml, by host (subdomains included) or
by prefix, with a reason for each. Drop matching entries when ingesting
prefix.cc, and remove the rows from the bundled data. No other row
shares a prefix or namespace with them, so no other row's status
changes. A namespace whose host cannot be parsed is not excluded, so a
malformed upstream entry cannot break the ingest. The loader rejects
unknown keys, so a misspelled section cannot silently disable
exclusions.

A new test fails if any bundled context contains an excluded host, or
an excluded prefix that came from prefix.cc.

Refs linkml#61

Signed-off-by: jdsika <carlo.van-driesten@vdl.digital>
prefix.cc has no curation, so every refresh can bring in new spam
unreviewed, as the June 2026 refresh did. linkml#61 asks to freeze it.

The ETL now uses the bundled prefixcc.csv snapshot. Entries listed in
prefixcc.excluded.yaml are still dropped from it, so a new exclusion
takes effect on the next run. Canonical rows are loaded first, because
merging depends on the order in which rows arrive. In sorted CSV order,
73 prefix.cc rows in merged would change: 70 would lose their canonical
status (for example awol and commerce) and 3 prefix aliases would
disappear. With canonical rows first, the snapshot and the merged
contexts rebuild byte for byte. This relies on prefix.cc having no
prefix aliases, which a test checks.

slurp-prefixmaps --refresh-prefixcc still downloads prefix.cc, and
prints every added or removed prefix.cc row so the change can be
reviewed before committing. load_context(..., refresh=True) also uses
the snapshot for prefix.cc.

Semweb prefix fixes now belong in linked_data.curated.yaml, which
already takes precedence over prefix.cc in the merged contexts. Before
this change, fixes like the recent gx one came in through a prefix.cc
refresh. README and docs explain this.

Closes linkml#61

Signed-off-by: jdsika <carlo.van-driesten@vdl.digital>
@kevinschaper
kevinschaper merged commit ff050de into linkml:main Nov 6, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

freeze prefix.cc refreshes

3 participants