Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix scorm xblock x frame options #35080

Closed
wants to merge 23 commits into from

Conversation

jesperhodge
Copy link
Member

@jesperhodge jesperhodge commented Jul 2, 2024

TL;DR

This adds support for the SCORM xblock at its latest version. Via that xblock, this allows to use SCORM blocks in courses.
This is done via a Content-Security-Policy (CSP) but only for specific endpoints.

Description

To support SCORM Connect, we need to update The SCORM xblock to the latest version (> 18) because that fixes a bug where the SCORM API does not provide learner_id.

When we initially tried to update this xblock, we learned that SCORM does not work on edx-platform with the default config of setting the X-Frame-Options response header to "DENY", because the SCORM xblock uses an iframe and that header disallows framing content.

To prevent clickjacking, either a Content-Security-Policy header with the frame-ancestors key must be in place, or X-Frame-Options must be set to "DENY" or "SAMEORIGIN".

X-Frame-Options: "SAMEORIGIN" is insufficient because we need to allow framing content by our Microfrontends, which have different-origin URLs.

So here we add a Content-Security-Policy header, but only to specific endpoints, because we don't want to make sweeping changes to edx-platform responses unless necessary.

To achieve this, we copied the Content-Security-Policy middleware from edx-django-utils and then modified the copy so that it allows adding different CSPs to specific endpoints via url regex matching.

Supporting information

Testing instructions

  • SCORM Connect Test file:
    edx-test-course-scorm-connect--scorm-test-pano--edXSCORMcourses--scorm-2004 (1).zip
  • Sample default SCORM test file:
    ContentPackagingSingleSCO_SCORM12.zip
  • in devstack, do these steps each for CMS and LMS in this order:
  • make dev.shell.lms (or cms)
  • make requirements
  • pip install openedx-scorm-xblock -> check that this is version > 18
  • exit shell
  • make dev.restart-container.lms (or cms)
  • after this is done, go to studio, go to a course and to advanced settings, and in the "advanced modules" field right in the top, add "scorm" to the array.
  • Go to a Unit and create an advanced block -> select SCORM (option should be visible if all above steps were performed correctly; if not visible you can retry those steps or reach out to @jesperhodge )
  • edit the block and upload the SCORM Connect Test file
  • repeat this for the Sample default SCORM test file
  • now both blocks should display content
  • click on Preview
  • you should see both block contents
  • open in LMS
  • you should also see both block contents

Deadline

We'd like to deploy this to stage if possible Monday morning.

Other information

There's plenty of background info about SCORM Connect and why we're trying to support it if needed, just reach out to @jesperhodge .

@rayzhou-bit rayzhou-bit force-pushed the fix--scorm-xblock-x-frame-options branch from 6f832a1 to a2c3ac7 Compare August 13, 2024 08:51
@jesperhodge jesperhodge marked this pull request as ready for review August 20, 2024 21:22
@jesperhodge jesperhodge force-pushed the fix--scorm-xblock-x-frame-options branch from c63c2fa to 99b0af5 Compare August 20, 2024 21:25
@timmc-edx
Copy link
Contributor

timmc-edx commented Aug 22, 2024

Unfortunately I just don't have time to do a proper review, but here are some assorted notes after a quick skim:

  • In the most abstract sense, the idea of loosening framing protection on certain endpoints seems like a good approach.
  • I'm not sure if we actually need per-endpoint protection for this feature, though. If the SCORM endpoints only need to be framed by one of our own MFEs, can we just make a site-wide CSP policy that allows framing of all endpoints by that MFE? A tighter policy would be great, but doesn't seem critical to me. If that works, it could be a no-code solution. I haven't verified that this is appropriate, though!
  • Note that any X-Frame-Options header is ignored when the CSP frame-ancestors directive is present in the response. We can keep the site-wide DENY and still set frame-ancestors on specific responses as needed, and it will override the DENY.
  • I think there's some danger in matching endpoints via regex in an "external" list. While I love regex, they're a common source of security issues (because of failure to anchor, etc.) -- and there's also a risk that these will diverge from our views' actual urlpatterns. If we need to target specific views, I think it would be much safer to set decorators on them that flag them as frameable in a certain way, and then have a middleware adjust response headers based on that flag. This allows us to use Django's built-in URL-matching, avoid duplication of effort, and ensure that the exemption is always exactly matched with the view.
  • I'm really not a fan of copying the edx-django-utils CSP middleware in here and then modifying it. That divergence means we can't upstream improvements very readily, and it's hard to tell how the two middlewares diverge. Duplication of security-sensitive code is something I want to avoid because of the degree of extra scrutiny each copy needs. (Note: The original CSP middleware is also accompanied by an ADR, some of which may be relevant. In particular, note that the django-csp package is almost what we want, but doesn't have good enforce vs. report-only support—something we may want to consider here in order to have a safer rollout.)
  • I also want to avoid introducing any overly broad solution that might interfere with a rollout of a more comprehensive solution later. Bear in mind that when multiple CSP headers are combined, they always add restrictions and can never remove them. We also want the ability to roll out restrictions to the Report-Only version of the header first, and only then "graduate" them to the enforced version. I haven't had time to check whether that's an issue here, but I wanted to mention it as a general issue for you or any other reviewers to consider.

robrap
robrap previously requested changes Aug 22, 2024
Copy link
Contributor

@robrap robrap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Temporarily adding a request changes review simply so it is clear that this should not merge as-is. We can discuss next steps as needed. Thank you.

@rayzhou-bit rayzhou-bit self-requested a review August 22, 2024 16:09
@robrap robrap dismissed their stale review August 22, 2024 16:56

To not be a blocker.

@jesperhodge
Copy link
Member Author

@timmc-edx timmc-edx deleted the fix--scorm-xblock-x-frame-options branch August 29, 2024 19:52
@timmc-edx
Copy link
Contributor

Bookkeeping note: That edx-internal branch corresponds to PR https://github.com/edx/edx-internal/pull/11477 (branch was deleted after merge)

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