High severityNVD Advisory· Published May 5, 2022· Updated Aug 3, 2024
Server-Side Request Forgery in scout in clinical-genomics/scout
CVE-2022-1592
Description
Server-Side Request Forgery in scout in GitHub repository clinical-genomics/scout prior to v4.42. An attacker could make the application perform arbitrary requests to fishing steal cookie, request to private area, or lead to xss...
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
scout-browserPyPI | < 4.52 | 4.52 |
Affected products
1- Range: unspecified
Patches
1b0ef15f4737dProtect remote_cors from Server-Side Request Forgery (#3326)
4 files changed · +55 −10
CHANGELOG.md+1 −0 modified@@ -29,6 +29,7 @@ About changelog [here](https://keepachangelog.com/en/1.0.0/) - Removed stream argument deprecation warning in tests - Handle `no intervals found` warning in load_region test - Beacon remove variants +- Protect remote_cors function in alignviewers view from Server-Side Request Forgery (SSRF) ## [4.51] ### Added
scout/server/blueprints/alignviewers/controllers.py+20 −1 modified@@ -14,6 +14,25 @@ CUSTOM_TRACK_NAMES = ["Genes", "ClinVar", "ClinVar CNVs"] +def check_session_tracks(resource): + """Make sure that a user requesting a resource is authenticated and resource is in session IGV tracks + + Args: + resource(str): a resource on the server or on a remote URL + + Returns + True is user has access to resource else False + """ + # Check that user is logged in or that file extension is valid + if current_user.is_authenticated is False: + LOG.warning("Unauthenticated user requesting resource via remote_static") + return False + if resource not in session.get("igv_tracks", []): + LOG.warning(f"{resource} not in {session.get('igv_tracks', [])}") + return False + return True + + def set_session_tracks(display_obj): """Save igv tracks as a session object. This way it's easy to verify that a user is requesting one of these files from remote_static view endpoint @@ -22,7 +41,7 @@ def set_session_tracks(display_obj): """ session_tracks = list(display_obj.get("reference_track", {}).values()) for key, track_items in display_obj.items(): - if key not in ["tracks", "custom_tracks", "sample_tracks"]: + if key not in ["tracks", "custom_tracks", "sample_tracks", "cloud_public_tracks"]: continue for track_item in track_items: session_tracks += list(track_item.values())
scout/server/blueprints/alignviewers/views.py+5 −2 modified@@ -39,6 +39,10 @@ def remote_cors(remote_url): Based on code from answers to this thread: https://stackoverflow.com/questions/6656363/proxying-to-another-web-service-with-flask/ """ + # Check that user is logged in or that file extension is valid + if controllers.check_session_tracks(remote_url) is False: + return abort(403) + resp = requests.request( method=request.method, url=remote_url, @@ -70,8 +74,7 @@ def remote_static(): file_path = request.args.get("file") or "." # Check that user is logged in or that file extension is valid - if current_user.is_authenticated is False or file_path not in session.get("igv_tracks", []): - LOG.warning(f"{file_path} not in {session.get('igv_tracks', [])}") + if controllers.check_session_tracks(file_path) is False: return abort(403) range_header = request.headers.get("Range", None)
tests/server/blueprints/alignviewers/test_alignviewers_views.py+29 −7 modified@@ -47,8 +47,9 @@ def test_remote_static(app): with app.test_client() as client: # GIVEN that user is logged in client.get(url_for("auto_login")) + + # GIVEN that resource file exists in user session with client.session_transaction() as session: - # GIVEN that resource file exists in user session session["igv_tracks"] = [file] # THEN the resource should be available to the user @@ -61,20 +62,41 @@ def test_remote_static(app): assert resp.status_code == 200 -def test_remote_cors(app): +def test_remote_cors_wrong_resource(app): """Test endpoint that serves as a proxy to the actual remote track on the cloud""" - cloud_track_url = "http://google.com" + # GIVEN a resource not present in session["igv_tracks"] + an_url = "http://google.com" - # GIVEN an initialized app - # GIVEN a valid user and institute + # GIVEN a running demo app with app.test_client() as client: # GIVEN that the user could be logged in resp = client.get(url_for("auto_login")) - assert resp.status_code == 200 # WHEN the remote cors endpoint is invoked with an url + resp = client.get(url_for("alignviewers.remote_cors", remote_url=an_url)) + + # THEN it should return forbidden (403) + assert resp.status_code == 403 + + +def test_remote_cors(app): + """Test endpoint that serves as a proxy to the actual remote track on the cloud""" + # GIVEN an igv track on the cloud + cloud_track_url = "https://s3-eu-west-1.amazonaws.com/pfigshare-u-files/25777460/GRCh37.variant_call.clinical.pathogenic_or_likely_pathogenic.vcf.gz.tbi" + + # GIVEN a running demo app + with app.test_client() as client: + # GIVEN that the user could be logged in + resp = client.get(url_for("auto_login")) + + # GIVEN that resource url exists in user session + with client.session_transaction() as session: + session["igv_tracks"] = [cloud_track_url] + + # WHEN the remote cors endpoint is invoked with cloud_track_url resp = client.get(url_for("alignviewers.remote_cors", remote_url=cloud_track_url)) - # THEN it should return success response + + # THEN response should be successful assert resp.status_code == 200
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-g53g-q539-93cvghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2022-1592ghsaADVISORY
- github.com/Clinical-Genomics/scout/issues/3325ghsaWEB
- github.com/Clinical-Genomics/scout/pull/3326ghsaWEB
- github.com/clinical-genomics/scout/commit/b0ef15f4737d0c801154c1991b52ff5cab4f5c83ghsax_refsource_MISCWEB
- huntr.dev/bounties/352b39da-0f2e-415a-9793-5480cae8bd27ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.