Upgrade FPT UAT baseline to Open edX Ulmo.4 - #2
Merged
Conversation
The previous vendored pdf.js was 1.0.907 (May 2013), four major versions behind upstream and within the range covered by Mozilla's GHSA-wgrm-67xf-hhpq (arbitrary JavaScript execution upon opening a malicious PDF). 5.7.284 is well past the >= 4.2.67 fix line. The replacement comes from Mozilla's prebuilt `pdfjs-5.7.284-legacy-dist.zip` GitHub Release artifact rather than the `pdfjs-dist` npm package because the npm package is library-only -- it ships `pdf.mjs` plus a bare `PDFViewer` component class, but no `viewer.html` / `viewer.mjs` / `viewer.css` / locale files. A full npm integration would mean rewriting the viewer page against the bare component, which is appropriate as a non-security follow-up but not as the fix here. The viewer page (`lms/templates/pdf_viewer.html`) is rewritten as a Mako adaptation of upstream `web/viewer.html`. A `<base href>` makes the viewer's relative asset URLs resolve against the vendored copy. The analytics shim (`lms/static/js/pdf-analytics.js`) is rewritten in vanilla JS against `PDFViewerApplication.eventBus`. Four analytics events (`textbook.pdf.thumbnails.toggled`, `textbook.pdf.thumbnail.navigated`, `textbook.pdf.outline.toggled`, `textbook.pdf.page.scrolled`) no longer fire because the corresponding UI elements were refactored away in pdf.js 4.x's Views Manager redesign. A new `scripts/refresh-pdfjs-vendor.sh` is the tool for future bumps: update PDFJS_VERSION + PDFJS_LEGACY_ZIP_SHA256, re-run, commit. Closes GHSA-mj74-gfq3-2v9f. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…openedx#38880) Replace course_version in the sidebar cache key with a block_structure_version derived from BlockStructureModel.data_version. course_version changes eagerly on publish, causing a cache miss before the block structure is rebuilt — poisoning the cache with stale data for 1 hour. block_structure_version only changes after the async rebuild completes, so cache misses only occur when fresh data is available. This is a backport of openedx#38785. (cherry picked from commit 929815f) Co-authored-by: Taylor Payne <wgu.taylor.payne@gmail.com>
Discussion thread titles (and other user-controlled context fields — replier_name, author_name, username) were interpolated raw into notification.content via `str.format(**context)`. That output is rendered with Django's `|safe` filter in digest_content.html, which is included by both the email_digest and batched_email body templates, so a `<style>` block in a thread title survived into recipient inboxes as executable CSS on email open — enabling open-tracking, content spoofing, and phishing. Escape at the source: in `get_notification_content`, wrap every context value with `django.utils.html.escape` before `template.format(**context)`, exempting the two structural keys (`p`, `strong`) that content_templates use as HTML tag names. This defends every renderer of `notification.content` in one place. This is the incomplete-patch companion of GHSA-4xv3-5j4x-q8g4 (CVE-2026-42857), which sanitized the post body via `clean_thread_html_body()` but did not cover the title path. Fixes GHSA-rv5w-f4r5-h77g. (cherry picked from commit 08b719ce41bb369fa0cabbe8d0547124e64c8566)
`startswith` is the wrong primitive for "is target inside directory base": once a trailing separator drops anywhere along the way, sibling directories whose names extend base match. We could spot-fix by re-appending the separator before the check, but `commonpath` makes the directory-boundary intent explicit and removes the failure mode entirely. Fixes GHSA-6cmm-8875-5pcw. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CourseTeamManageAPIView at lms/djangoapps/support/rest_api/v1/views.py declared only `permission_classes = (IsAuthenticated,)`, so any authenticated user — including a plain enrolled learner — could invoke GET and use the 404-vs-200 response for user enumeration against arbitrary email/username/user_id values, confirming which accounts exist and are active. Callers holding any course/org `instructor` role additionally received the target user's `staff`/`instructor` role map across the caller's scope. Gate `get()` on `_caller_can_manage_course_team()`, a new helper that returns True only for: - is_staff (GlobalStaff), or - is_superuser, or - SupportStaffRole, or - any user with a CourseAccessRole of role="instructor" This is the union of PUT's current authorization set (admin/staff/ superuser/instructor) and the global SupportStaffRole. Read access must match write access — a user who can PUT role changes must be able to see the current state before making them — and the endpoint lives in the support module, so support staff belong in the set too. Also extend `get_accessible_courses_for_user` so that SupportStaffRole users get the same all-courses view as admin/ staff, otherwise they'd fall through to the instructor branch and receive an empty result set. Anonymous callers still get 401 from DRF's IsAuthenticated; plain learners now get 403 before the target lookup runs, so the 404-vs- 200 enumeration discrepancy (CWE-204) is no longer reachable by unauthorized callers. Course instructors retain their scoped view. `put()` retains its existing authorization for now; it lacks SupportStaffRole in the set — a separate design gap best handled in a public follow-up after publication (cross-linked to GHSA-95xv-3c54-c3pw), where the `_caller_can_manage_course_team` helper can also become the shared PUT check. Fixes GHSA-95xv-3c54-c3pw. Credit: 5ud0 / Tarmo Technologies.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sync the UAT feature branch with the official Open edX
release/ulmo.4tag (46c5435). This targets the latest Ulmo baseline used by Tutor 21.0.9. Stableulmo.3-feid-loginis not touched.