Skip to content

Upgrade FPT UAT baseline to Open edX Ulmo.4 - #2

Merged
thaipro23 merged 6 commits into
fpt-indigo-uifrom
upstream-ulmo4-sync-20260813
Aug 13, 2026
Merged

Upgrade FPT UAT baseline to Open edX Ulmo.4#2
thaipro23 merged 6 commits into
fpt-indigo-uifrom
upstream-ulmo4-sync-20260813

Conversation

@thaipro23

Copy link
Copy Markdown
Owner

Sync the UAT feature branch with the official Open edX release/ulmo.4 tag (46c5435). This targets the latest Ulmo baseline used by Tutor 21.0.9. Stable ulmo.3-feid-login is not touched.

feanil and others added 6 commits July 7, 2026 10:33
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.
@thaipro23
thaipro23 merged commit 7b05f90 into fpt-indigo-ui Aug 13, 2026
31 of 48 checks passed
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.

4 participants