THU-MAIC · 2026-09-13 · major
OpenMAIC 1.0.2 — three advisories close a DNS-rebinding SSRF
OpenMAIC 1.0.2 fixes three privately reported security holes in the open-source multi-agent classroom: two ways past the outbound URL guard on /api/proxy-media, and a route that let any caller overwrite an existing classroom.
A security release that pins OpenMAIC's media proxy to the addresses its own guard already approved.
Key specs
| GitHub stars | 36,463 |
|---|---|
| Stars gained this week | +4,202 |
Quick facts
| Project | OpenMAIC (Open Multi-Agent Interactive Classroom) |
|---|---|
| Maker | THU-MAIC |
| Version | v1.0.2, released 13 September 2026 |
| Advisories fixed | 3 — two SSRF bypasses on /api/proxy-media, one classroom overwrite |
| Breaking change | POST /api/classroom ignores a client-supplied stage.id |
| New default | CGNAT range 100.64.0.0/10 blocked unless ALLOW_LOCAL_NETWORKS=true |
| License | MIT |
What is it?
OpenMAIC 1.0.2 publishes three security advisories and ships their fixes in the same tag. Two are ways around the outbound URL guard on the /api/proxy-media route; the third let any caller overwrite an existing classroom file. OpenMAIC itself is an open-source multi-agent classroom that turns a topic or an uploaded document into an agent-taught lesson with slides, quizzes and narration.
How does it work?
Both proxy holes are server-side request forgery. The first slipped an IP literal — the Alibaba Cloud metadata address 100.100.100.200 — past a denylist that was checked too late; metadata hostnames and addresses, including mapped and transition encodings, are now tested before the literal and local-network branches, in every environment. The second was DNS rebinding: the route validated a hostname, then let fetch() resolve it again at connect time, so a changing answer could steer the socket inward. A shared pinned dispatcher now connects only to addresses the guard validated, on every redirect hop. The classroom bug is fixed by generating ids server-side and creating files exclusively, returning 409 on a collision.
Why does it matter?
Reaching a cloud metadata service from an unauthenticated request is the standard path to stealing instance credentials, so anyone self-hosting this classroom on a cloud VM has a reason to upgrade today rather than at leisure. The release also hardens billing: POST /api/generate/tts now inspects a 200 response before it stores or bills it, rejecting HTML, JSON and other non-audio bodies instead of trusting the status code.
Who is it for?
teams self-hosting OpenMAIC
Frequently asked questions
- What breaks when I upgrade OpenMAIC to 1.0.2?
- Two defaults change in OpenMAIC 1.0.2. POST /api/classroom no longer honours a client-supplied stage.id, so callers must read the classroom id back from the response instead of choosing one. And the outbound URL guard now refuses CGNAT addresses in the 100.64.0.0/10 range by default, the same way it already refused private ranges.
- Does OpenMAIC 1.0.2 stop me reaching a local model server?
- It can. OpenMAIC 1.0.2 blocks CGNAT addresses by default, which covers Tailscale-style overlay networks, so a model server or media host reached that way needs ALLOW_LOCAL_NETWORKS=true. Some ranges are refused whatever you set — IANA reserved, documentation, multicast and broadcast blocks such as 240.0.0.0/4, 198.18.0.0/15, 192.0.2.0/24 and 2001:db8::/32.
- Is there anything besides security fixes in OpenMAIC 1.0.2?
- Yes. OpenMAIC 1.0.2 also adds GLM-5.3 and GLM-5.3-Flash, GenUI and Interactive component referencing during playback, a render queue preflight that runs before an export compiles, generated media written through the asset pool under server-backed persistence, and one JSON lifecycle event per render and preview transition on the render service.
- How does this compare with the OpenMAIC 1.0.1 security release?
- The 1.0.1 release a week earlier fixed four advisories, one of them rated critical, including an unauthenticated SSRF whose guard ran only in production builds. OpenMAIC 1.0.2 fixes three more in the same area: the guard was still reachable around, once through a late-applied metadata denylist and once through DNS rebinding at connect time.
Try it
ALLOW_LOCAL_NETWORKS=true pnpm dev