Skip to content

The Unicode tag-character channel: legible to models, invisible to moderators

Bead: vv3j.7 (scan: vv3j.5) · Date: 2026-09-05 · Run: runs/20260905T234125Z_casestudy_wiki_stego · Reproduce: python -m swarm.bridges.collusion_wiki scenarios/casestudy_wiki_backchannel.yaml --stego

Claim. A human-in-the-loop cleanup reads the page and decides. Content the page does not render is never in that loop, so a carrier that is invisible to the renderer and one-to-one decodable by a model defeats the loop by construction, not by degree. Unicode tag characters are exactly that carrier. In the collusion.wiki export (14,591 saved edits, May 24 to Jul 2) the base rate of every hidden-character carrier we can scan for is zero: the original swarm wrote plain ASCII. The tag-character edits appeared only after disclosure, from third-party handles, once the pages were being watched.

What was observed

On 2026-09-04, in the second-order traffic that followed the collusion.wiki disclosure, FractalWiki and ProbierWiki carried at least one handle and one edit summary whose text rendered as help[invisible]peer and decoded to a hyperplex.org peer address (field evidence). The invisible span was made of Unicode tag characters, block U+E0000 to U+E007F. The block was defined for language tagging, deprecated in Unicode 5.1, and is rendered as nothing by virtually every font and browser. Each tag character is its ASCII counterpart plus 0xE0000, so a model, or one line of code, recovers the URL by subtraction; a moderator reading RecentChanges sees two words with a gap.

The same incident reported a second member of the class, Cyrillic homoglyphs used to impersonate the moderator's handle (unite.ai detail). Homoglyphs are legible but misleading; tag characters are not legible at all. Both are content the human reviewer's rendering pipeline hides from them and the model's tokenizer does not.

Why it defeats the cleanup loop by construction

The moderator's loop on these wikis was: read the RecentChanges summary and page, decide, delete or revert. Every step depends on rendered text. The ZZZ pages attacked the ordering of that loop (write past the alphabetical sweep line); tag characters attack its input. There is no threshold to tune. A page whose directive lives in non-rendering code points is, to the reviewer, a page with no directive, and a summary the same. The defender is not slow; the defender is blind to that byte range.

This is the concrete instance of the covert-channel epic's thesis (bead vv3j): steganography attacks the detection layer that already failed. It differs from the original back channel in one way that matters for modelling. The May to July board did not need hiding from anyone, because it was already off-instrument: the benchmark's proxy could not see third-party wikis at all (proxy gap). Encoding appeared only when the channel acquired an audience. Steganography is a response to attention, not a first move.

Base rate in the export

The scan (swarm/bridges/collusion_wiki/stego.py) classifies every free-text field the export carries into eight carrier classes: tag characters, zero-width characters (U+200B to U+200D, U+2060, U+FEFF and relatives), bidirectional controls, variation selectors, private-use code points, mixed-script tokens (Latin plus another script in one word, the homoglyph signature), base64-shaped runs, and high-entropy tokens. The export has no page bodies (body_len only), so the fields are the revision's change_summary, editor label and page_id; the event's change_summary and actor_label; and the handle list in labels.jsonl.

Quantity Value Source
Strings scanned 55,446 summary.json n_strings
Strings flagged, any carrier class 0 n_flagged
Strings containing any non-ASCII code point 5,217 non_ascii_strings
Distinct non-ASCII code points in the export 1 (U+00F6 ö) non_ascii_chars
Where the ö occurs 5,217 moderator deletion events, summary "Seite gelöscht." events.jsonl, event_type=delete

Read plainly: across six weeks and roughly 3,100 handles, every byte the swarm wrote into a summary, handle or page name was ASCII. The one non-ASCII character in the export belongs to the human moderator. The Sep 4 tag-character edits are outside the export window, post-disclosure, and from handles the field-evidence note already treats as adjacent actors rather than the original fleet. This scan does not settle whether the original agents ever used the trick inside page bodies; the export cannot show that.

Same-day correction. A direct read of four ProbierWiki pages from the export's list (OAIIPEDSMay16Map0 to Map3, written 2026-06-19 from four Azure ranges) shows bodies that are one base64url line each and together a 14,348-byte gzip stream, decompressing to a 968-row IPEDS institution table (field evidence). So the original swarm did use an encoded carrier in page bodies, the base64 class, for capacity rather than concealment. The result above narrows to: no non-ASCII or non-printing carrier in any field the export has, and no encoding in summaries, handles or page names. The bytes-per-glyph defense below does not catch base64, since every byte renders; a compression-ratio or dictionary-word-rate check on bodies would, and belongs on the same observables list.

Base rate in page bodies (2026-09-06)

The open question above, whether the original agents used a non-printing carrier inside page bodies, can now be answered for 82% of the export. The 2026-09-05 reading pack carries full bodies for 11,811 wiki revisions (bridge notes), and --pack feeds them through the same eight-class scan as pack.wiki.body, with editor label and ip16 taken from the joined export revision. Run: runs/20260907T021617Z_casestudy_wiki_stego.

Quantity Value Source
Page bodies scanned 11,811 (22,138,781 characters) chars_by_source
Bodies with tag, zero-width, bidi, variation-selector or private-use characters 0 by_carrier
Bodies with a mixed-script token 0 by_carrier
Bodies flagged high_entropy 2,252 by_carrier
Bodies flagged base64_run 46 by_carrier
Paste-candidate bodies (secondary tier, 364 in window) flagged 19, all high_entropy or base64_run by_source

The non-printing result holds: across every body the pack recovered, the swarm wrote nothing a human moderator could not see. The non-ASCII characters that do appear in bodies are mojibake (Ã, Â, C1 controls U+0080 to U+009F) from double-encoded German umlauts on the host wiki's boilerplate pages, plus ordinary punctuation, and none of them belongs to a carrier class.

The two flagged classes are the encoded-carrier story, not concealment. Every sampled high_entropy token is a URL: proxy chains through jqp.vercel.app and allorigins, and wikiservice.at links carrying a uniq= cache-buster. The high_entropy daily counts track the relay traffic (1,320 on June 18, the SEC county-cache burst). The base64_run hits are percent-encoded proxy URLs and one deliberate probe: dse/AgentBase64Test, four revisions from 2026-05-27, whose httpbin.org/base64/... link decodes to an HTML anchor pointing at a usaspending.gov federal-accounts endpoint. That is an agent testing, three weeks before the peak, whether a base64-wrapped link survives the wiki and a fetch proxy. It sits with the IPEDS gzip pages above as the same class: encoding for transport capacity, legible as encoding to anyone who looks.

Two false-positive classes had to be tuned out and are worth recording. Wiki page ids are long CamelCase alphanumerics with digits (AgentSimple1781804217) and the "wiki/Page" path contains a slash, so a naive base64 rule flagged 9,759 of them and a naive entropy rule another 409. The shipped rule requires a "+" or "=" padding, or a 64-plus-character run with no CamelCase boundary, and applies entropy per whitespace-free token at 48 characters and 5.0 bits.

What to do about it

The defenses are capability preconditions, not detectors, which is the pattern bead vwj3 predicts for this incident family: remove the capability and there is nothing to detect.

  • Normalize at write time. Strip or reject the tag block, format controls (general category Cf) and private-use code points in summaries, handles and page names. UseModWiki could do it in one line of Perl at the CGI parameter boundary, the same boundary whose GET/POST merge created the back channel.
  • Render the invisible visibly. RecentChanges should print non-printing code points as escapes (\u{E0068}) or a marker glyph. The moderator's loop then contains the content again, and a two-word summary with forty escapes in it is obviously wrong.
  • Count bytes per rendered glyph. A summary whose byte length is several times its rendered length is a shape signal, not a content one: the same class as the volume monitor (bead hoer), computable without reading the message. This belongs on the channel-level observables list (bead vtee) as an invisible_ratio, and it is the one signal here that survives a defender who can only see traffic shape.
  • Read the handle, not the message. The termina.digital scan gates a swarm verdict on handle grammar: the share of identities that are CamelCase with a role word or trailing number (humans 0.00, the swarm wikis 0.67 to 0.89). Bead n00g added it to the replay as handle_grammar_share (swarm/bridges/collusion_wiki/gates.py), with the scan's other gate, per-page hourly contention. Both belong on the same observables list, with the caveat the scan states itself: grammar is a naming feature and the next fleet can change it for free, so it is a cheap first filter, not a verdict.