Self-hosted multi-platform broadcast newsroom for activist collectives: publishing pipeline with group approval and DST-proof scheduling, TweetDeck-style column wall with hostile-content-safe rendering, live control room with Auto Director, bridged chat governance with polls and quorum, distributed sandboxed transcode workers, encrypted content-addressed archive, monthly analytics. MIT licensed. See README.md and docs/.
2.1 KiB
Safe content
The only sanctioned way to render provider content (posts, bios, comments, messages, link previews, display names) in the web UI. Proposal §4.5.
Provider text becomes a closed rich-text AST (text, linebreak, emoji,
link, mention, hashtag inside paragraphs) before it reaches React. No
node can hold HTML, attributes or styles.
parsePlainTexthandles plain provider text.parseProviderHtmlhandles the Mastodon/PeerTube HTML subset. Neither renders HTML.script,style,iframe,svg,math,form,templateand similar elements are dropped along with their content. Other tags are unwrapped to text.- Links must be absolute http(s) URLs with no credentials, checked by
parseSafeHttpUrl. Anything else stays as plain text that can't be clicked. Hosts are shown in punycode, and the real host is shown when a link's label doesn't start with it. - All media (
emoji, preview images) goes throughtoProxiedMediaUrl(default/api/media-proxy?url=…). The renderer drops anysrcthat isn't a canonical proxy URL. - Bidi override/isolate characters are stripped from all text. Display names
also lose zero-width characters, and
DisplayNameflags mixed-script names that use look-alike letters. - Limits: 20k input chars, 2,000 nodes, nesting depth 32, 2,048-char URLs. The tokenizer makes one forward pass, so its run time grows linearly with input size.
@tactical-media-broadcast-hub/safe-content/react exports RichText, LinkPreviewCard,
DisplayName and SafeLink. They re-validate every prop with
coerceRichTextDocument/parseLinkPreview, so an AST loaded from the DB or
the network is as safe as a freshly parsed one.
@tactical-media-broadcast-hub/safe-content/eslint exports noRawHtmlSinks, a flat-config
block that bans dangerouslySetInnerHTML, innerHTML/outerHTML,
insertAdjacentHTML, document.write, DOMParser.parseFromString, eval
and new Function outside this package. Spread it into the root
eslint.config.mjs.
@tactical-media-broadcast-hub/safe-content/corpus exports the malicious-content corpus for
packages/testing and the Playwright suites.