Skip to main content
Back to Blog
Open Source5 min read

Aelira Core v0.11.0: four fixes in the Microsoft 365 integration and review pages

Aelira Core v0.11.0 fixes four security issues, one of them high severity, in the Microsoft 365 integration and the LMS review pages. Self-hosters who connect Microsoft 365 should upgrade and create their Microsoft webhook subscriptions again.

RD (Reg) Crampton•
Share:LinkedInX

Aelira Core v0.11.0 fixes four security issues. One is high severity: a user of a department with a connected Microsoft 365 account could have that department's Microsoft access token sent to a server of their choosing. The other three are low severity, and each of the four has a published advisory.

If you self-host Aelira Core and connect Microsoft 365, upgrade. If you don't use the Microsoft 365 integration, only the review-page fix applies to you. The release adds one database migration, and Microsoft webhook subscriptions created before it must be created again. The steps are below.

A page token that was really a URL

When Aelira lists the files in a OneDrive folder, Microsoft returns them a page at a time, with a link to the next page. Our API handed that link to the dashboard as a page token, and when the dashboard asked for the next page, the API requested whatever URL the token contained. Every one of those requests carried the department's Microsoft Graph access token.

Nothing checked where the URL pointed. An authenticated user of the department could replace the token with the address of their own server and receive the access token, which opens the department's connected OneDrive or SharePoint content until it expires. Deployments with no connected Microsoft 365 account had no token to expose.

In v0.11.0, paging and delta links are followed only when they are https URLs on graph.microsoft.com under /v1.0/, with no other port, no user information, no fragment and no dot segments. Anything else is refused before a request is sent, and the route answers 400 Invalid page token.

Advisory: GHSA-cxmg-mrg8-j7r6 (high).

Three lower-severity fixes

Graph request paths (GHSA-cpcw-3584-j8q4). Requests to Microsoft Graph were built from item, folder, drive, site and subscription IDs, folder paths and file names exactly as given. An ID containing /, .., ?, # or % could change which Graph resource was requested. Those requests still used the connected account and stayed within its permissions. Now an ID must be a single Graph ID, folder paths refuse dot segments and control characters, and every path segment, file name and search term is encoded.

Webhook notifications (GHSA-5prr-c8m5-63r7). When Aelira creates a Microsoft subscription, it gives Microsoft a value to send back with every change notification, so the API can tell real notifications from forged ones. We had used the department's ID, which isn't a secret. Someone who knew a department ID and a subscription ID could make the API queue unwanted sync work. Each subscription now gets its own random secret. The API stores only a hash of it and compares in constant time.

LMS review pane (GHSA-724p-6r8m-h85x). The Canvas and Brightspace review pages cleaned the original course HTML with DOMPurify, then parsed and rebuilt it once more to add a notice to images with no alt text. That second pass meant the markup shown was not the markup DOMPurify had checked. No working attack is known. The notice is now added inside DOMPurify's own pass, and its output is shown exactly as returned.

What operators need to do

The full procedure is in the release notes. In short:

  1. Before upgrading, record your Microsoft webhook subscriptions. For each department that connects Microsoft 365, call GET /microsoft/subscriptions and note each resource. Microsoft can't change the secret on an existing subscription, so the old ones stop being accepted after the upgrade.
  2. Back up, then upgrade. Take a coordinated backup, run alembic upgrade head with the new API image, confirm the head is 20261028_webhook_secret, and deploy the API, worker and dashboard together. The migration adds one nullable column and drops nothing.
  3. Check PUBLIC_API_URL. Notifications now always go to that address followed by /webhooks/microsoft, so it must be the public https address Microsoft can reach.
  4. Create each subscription again with POST /microsoft/subscriptions and the body {"resource": "<recorded resource>"}. Until you do, Microsoft changes in that drive don't trigger a sync.

Two API changes may affect scripts. POST /microsoft/subscriptions no longer needs notification_url and refuses any address other than the API's own receiver. Microsoft sync folders must be added by their Graph item ID.

Why this is 0.11.0

We follow semantic versioning strictly from v0.10.0 on. This release changes API behaviour and adds a database migration, so it is a minor release, even though most of it is security fixes.

Builds that survive an upstream outage

Two changes make our own CI and release builds harder to knock over. Every pinned download in the API image build now goes through one verifier with bounded retries, and CI reads those files from a cache keyed by their SHA-256, checking each file exactly as it would a download (#687). The native LaTeXML jobs depend on snapshot.ubuntu.com. When it refuses all three attempts as unavailable, they now build from a cached input that is checked against a reviewed lock and its signed package index (#840). Integrity and TLS failures never fall back to the cache.

Caught at the release gate

The first release run for v0.11.0 stopped before anything was published. The dashboard image inherits curl from its pinned nginx:alpine base, and a fix for CVE-2026-92392 (high) had become available in Alpine. Our normal CI scans only the API image, so the release workflow's scan of the dashboard image was the first to see it. We added the fix (#846), and the release was built again from the corrected commit.

What remains open

The open items disclosed with v0.10.0 are unchanged, and the release notes list each one with its issue. The Microsoft fixes are covered by unit and route tests with Graph mocked, and the migration by a test against PostgreSQL. We have not tested this release against a live Microsoft 365 tenant, and the release notes say so.

The whole self-hosted product remains free and open source. The release, its signed images and the CLI are on GitHub and npm.

RD (Reg) Crampton

RD (Reg) Crampton

•Founder & CEO

Founder, CEO & lead developer of Aelira. Building beta tools to help faculty and accessibility teams check materials and evaluate suggested fixes, with human review required.

Explore accessibility remediation with Aelira

Join the pilot to evaluate Aelira's beta workflows. Support varies by format; outputs can be partial and need human review.