Skip to content

feat: expand Message Center posts inline instead of linking to the admin centre - #5

Merged
craigthackerx merged 1 commit into
masterfrom
feat/message-center-expand
Aug 8, 2026
Merged

feat: expand Message Center posts inline instead of linking to the admin centre#5
craigthackerx merged 1 commit into
masterfrom
feat/message-center-expand

Conversation

@craigthackerx

Copy link
Copy Markdown

Answering the question directly: no separate tab. A tab would split the timeline and cut these posts off from the search, date, sort and bookmark filters that already work across every source. Message Center posts are news like everything else, they just happen to be the only ones with a body worth reading in place.

What this does

A Microsoft Message Center tag. Added as a product, which the existing machinery turns into both a card tag and a filter pill for free, so "just the Message Center" is one click and nothing leaves the main stream.

It is assigned by source, not by text matching. An unreachable weight threshold stops the classifier ever awarding it on wording, so the tag means "this came from the Message Center" rather than "this mentions it".

An expand button, opening a popout. Only on articles that actually carry a body. Every RSS source has nothing beyond a 300 character summary, so an expand button there would promise more than it could deliver.

Why it is worth doing at all

A Message Center permalink is admin.microsoft.com/#/MessageCenter/..., which only opens for someone with admin access to the tenant it was published to. For a public reader on security.libredevops.org those 12 cards were a headline, a summary and a dead link. Now the full post is readable in place, and the outbound link is labelled honestly as admin-only rather than looking like a normal article link.

Security

This is the part that mattered most, given the site aggregates untrusted upstream content and SECURITY.md names stored XSS through a title or summary as the plausible finding.

  • Bodies are stored and rendered as plain text, never HTML. The pipeline strips markup before it is written to feeds.json, and the dialog builds every node with textContent.
  • Links are extracted from the original markup separately and re-rendered as real anchors, scheme-checked at both ends: http(s) only in the Python, then re-validated through isSafeUrl in sanitiseArticle rather than trusted from the feed.
  • sanitiseArticle still whitelists fields, so body and links are passed through explicitly with their own caps rather than arriving by accident.
  • The dialog is a native <dialog>, so focus trapping, Escape and the backdrop come from the platform instead of hand-rolled JS.
  • No new inline script, so the hashed CSP entry is untouched. The workflow recomputes the app.js SRI on deploy as usual.

Verification

Driven under jsdom against the real index.html and app.js, with hostile markup (<img src=x onerror=...>) planted in the title, the body and a link label, plus a javascript: URL in the links array. All 14 checks pass:

PASS two cards rendered
PASS expand button only on the article with a body
PASS Microsoft Message Center filter pill exists
PASS Microsoft Message Center tag rendered on the card
PASS dialog opened
PASS body split into 3 paragraphs
PASS javascript: link dropped, 2 of 3 kept
PASS no javascript: href survived
PASS source link labelled as admin-only
PASS no <img> element created from hostile body/label
PASS hostile markup rendered as literal text
PASS no onerror attribute anywhere in the document
PASS dialog closes
PASS dialog content cleared on close

The bodies themselves could not be generated locally: the Azure CLI delegated token still 403s, because consent was granted to the application's service principal rather than to the CLI client for the signed-in user. The pipeline's federated identity is unaffected, so real bodies land on the next feed run.

…min centre

A Message Center permalink only opens for someone with tenant admin access, so
for a public reader those cards were a headline and a dead link. The post body
now travels with the article and the site shows it inline.

No separate tab: a tab would split the timeline and hide these posts from the
search, date and bookmark filters that already work across every source.
Instead they carry a Microsoft Message Center product tag, which the existing
machinery turns into both a card tag and a filter pill for free, so "just the
Message Center" is one click and everything stays in one stream.

The tag is assigned by source rather than by text matching (an unreachable
weight threshold keeps the classifier from ever awarding it on wording), so it
means "this came from the Message Center" rather than "this mentions it".

The expand button appears only on articles that actually carry a body, so it
never promises more than the RSS sources can deliver.

Bodies are stored and rendered as PLAIN TEXT, never HTML. Links are extracted
from the original markup and re-rendered as anchors after a scheme check at
both ends. That keeps the front end's existing rule intact: everything reaches
the DOM through textContent, so hostile upstream feed content has no route in.

Verified under jsdom against the real index.html and app.js: 14 checks covering
the tag, the pill, the expand button only where a body exists, paragraph
splitting, the dialog lifecycle, and hostile markup in the title, body and link
labels rendering as literal text with no element or attribute created.
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@craigthackerx
craigthackerx merged commit 199d79e into master Aug 8, 2026
5 checks passed
@craigthackerx
craigthackerx deleted the feat/message-center-expand branch August 8, 2026 16:43
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.

1 participant