Repository navigation
v0.3.2
A fix for the first load after an upgrade, and fixes from a security review of the repository.
| Package | Version |
|---|---|
@missing-elements/h5p-offline-player |
0.3.2 |
@missing-elements/h5p-cmi5 |
0.4.1 |
The demo site picks up its changes on the next deploy.
Player
Fixed
- The first load after an upgrade no longer runs against the old Service Worker. Registering a worker again at an unchanged URL does not make the browser fetch the script. So the first load after an upgrade booted the content against the old worker, and the browser swapped in the new one about a second later, mid-load. Depending on what changed between the versions, that showed errors or an empty player until a reload. The element now asks its worker for its version before the content starts. If the versions differ, it updates the worker and waits for the new one, for up to three seconds. Offline, or past that, it plays on the running worker as before.
- A worker update that fails to install no longer fails the load. The worker that was running keeps serving.
- A host's own worker that does not skip waiting no longer stalls the load. A new worker of that kind waits until every tab using the old one has closed. The element now waits for it for three seconds at most, then plays on the running worker.
Changed
- The console warning for a worker version that differs from the element's now says to re-copy
h5p-sw.jsonly if the warning persists after a reload. Before an update lands, a short-lived mismatch is expected.
Upgrading
Sites that serve the package's dist/ through a bundler or from a CDN need nothing. Sites that copy h5p-sw.js by hand need to copy the new one, as with every release.
Security
A review of the repository found one issue of medium severity on the demo site and three lower-severity ones. None was in the player package.
Demo site: a link could open a hostile package
The player runs a package's own JavaScript in a frame on the same origin, by design. So a package can read anything stored for that origin. On the demo site, that includes:
- the saved state of every package opened in the installable app, answers included, because the app keeps state with
resume - the extracted files of every package played there
- the list of every package URL and file name played
A link such as /app/?src=https://attacker.example/x.h5p opened the package at once, including in the installed app. The package could then read all of the above and send it out.
Now the player page, the app, the cmi5 page and /embed opened on its own name the other site and wait for a click before opening its package. Packages from the demo's own site, typed URLs and picked files open as before. /embed framed by another site opens directly, because the browser gives that frame storage of its own, separate from the demo site's.
h5p-cmi5 0.4.1: a kept session could send its token to another LRS
With the storage option, startCmi5() keeps the session across a reload. It found the stored session by the launch's fetch URL alone, and sent the stored LRS token to whatever endpoint the current launch named. A kept session now records the endpoint, registration and activity it was made under, and is ignored when the launch names others.
Without storage, the default, nothing changes. With it, a session saved by 0.4.0 records none of the three, so the first reload after upgrading starts a new session.
Smaller fixes
- Demo deployment: the function behind
/no-range/built the address of its own files from a request header and sent the deployment-protection bypass secret there. It now takes the address from Vercel's environment and sends the secret only to the deployment's ownvercel.apphost. - Docs: the setup guide and the resume docs now say that any package played on a site can read what other packages saved there. With
resumeon, play only packages you trust, and ask before opening a package from a link. - h5p-verify skill: now says that a passing check is not a trust decision.
h5p-cmi5 0.4.1
Besides the session fix above:
- Fixed:
exit()with noreturnURLnow closes only a top-level window. Inside an LMS frame it does nothing, and the page should tell the learner to go back to the course, as the demo's cmi5 page does. 0.4.0 also tried to close the window from inside a frame, which cmi5 does not ask for: in a frame, exit goes to thereturnURL. - Docs: the examples no longer set
launchMethod="OwnWindow". A framed player works in current Chrome, Safari 26 and iOS 26, so the LMS can choose.OwnWindowstays documented for an LMS on plainhttp, an LMS frame withoutallow="fullscreen", and iOS before 26. - Docs: a public page that takes its package from the launch should pass
src: falseand check where the package comes from before playing it, as the demo's cmi5 page does.
What's Changed
- feat: enhance security by adding confirmation for external package li… by @alekswebnet in #4
Full Changelog: v0.3.1...v0.3.2