CVE-2026-48053
Kolibri has Unauthenticated Server-Side Request Forgery (SSRF) in RemoteFacilityUserViewset
Kolibri is an offline-first education platform. Prior to version 0.19.4, several Kolibri API endpoints accept an unvalidated baseurl parameter and fetch attacker-controlled URLs from the Kolibri server, reflecting the response body back to the caller. The original report identified two endpoints on the RemoteFacilityUser* viewsets; remediation review found two further reflection points on the same pattern. The GET endpoint was unauthenticated. Version 0.19.4 fixes the vulnerability.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- Low
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
5.8
Kolibri has Unauthenticated Server-Side Request Forgery (SSRF) in RemoteFacilityUserViewset
Kolibri is an offline-first education platform. Prior to version 0.19.4, several Kolibri API endpoints accept an unvalidated baseurl parameter and fetch attacker-controlled URLs from the Kolibri server, reflecting the response body back to the caller. The original report identified two endpoints on the RemoteFacilityUser* viewsets; remediation review found two further reflection points on the same pattern. The GET endpoint was unauthenticated. Version 0.19.4 fixes the vulnerability.
- Record
CVE-2026-48053- CVSS 3.1
- 5.8 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
EUVDEUVD-2026-60319
5.8
Kolibri is an offline-first education platform. Prior to version 0.19.4, several Kolibri API endpoints accept an unvalidated baseurl parameter and fetch attacker-controlled URLs from the Kolibri server, reflecting the response body back to the caller. The original report identified two endpoints on the RemoteFacilityUser* viewsets; remediation review found two further reflection points on the same pattern. The GET endpoint was unauthenticated. Version 0.19.4 fixes the vulnerability.
- Record
EUVD-2026-60319- CVSS 3.1
- 5.8 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-4mj9-pf4r-cqrc
5.8
Kolibri has Unauthenticated Server-Side Request Forgery (SSRF) in RemoteFacilityUserViewset
Summary
Several Kolibri API endpoints accept an unvalidated baseurl parameter and fetch attacker-controlled URLs from the Kolibri server, reflecting the response body back to the caller. The original report identified two endpoints on the RemoteFacilityUser* viewsets; remediation review found two further reflection points on the same pattern. The GET endpoint was unauthenticated.
Affected endpoints
Reported:
GET /api/auth/remotefacilityuser→RemoteFacilityUserViewset(kolibri/core/auth/api.py:1570). No authentication required.POST /api/auth/remotefacilityauthenticateduserinfo→RemoteFacilityUserAuthenticatedViewset(kolibri/core/auth/api.py:1594). Authentication is checked against the remote server rather than the local Kolibri.
Found during remediation:
POST /api/public/setupwizard/loddata→ setup wizard's remote-signup proxy (kolibri/plugins/setup_wizard/api.py). Reachable on unprovisioned devices.GET /api/public/networklocation/<id>/facilities/→NetworkLocationFacilitiesView(kolibri/core/discovery/api.py). Authenticated but with the sameResponse(remote_payload)pattern.
Root cause
Two compounding issues:
- Response reflection — these endpoints returned the remote server's JSON body more or less verbatim to the caller (
Response(response.json()),Response(facility_info["users"]), etc.). - No restriction on the remote target —
baseurlwas validated only byURLValidator(schemes=["http", "https"]).NetworkClient.build_for_address()would connect to any host with a valid Kolibri-shaped/api/public/info/response, andrequestsfollowed 30x redirects by default, so a hostile peer could pivot the fetch to an arbitrary host (cloud metadata, internal services) before reflection.
Two reflection vectors
GET vector (RemoteFacilityUserViewset):
The viewset fetched <baseurl>/api/public/facilitysearchuser/ and returned Response(response.json()). An attacker-controlled baseurl returned a 302 to an arbitrary internal URL; requests followed the redirect, and the redirected response body was returned to the attacker.
POST vector (RemoteFacilityUserAuthenticatedViewset):
get_remote_users_info() fetched <baseurl>/api/public/facilityuser/ with Basic Auth and the viewset returned Response(facility_info["users"]). A malicious baseurl returned crafted user-shaped JSON; arbitrary smuggled fields were reflected back to the caller. The setup wizard and NetworkLocationFacilitiesView endpoints had the same shape on different remote URLs.
Reproduction
The vulnerability can be reproduced by pointing baseurl at an attacker-controlled HTTP server that:
- Responds to
GET /api/public/info/with a valid Kolibri info payload (soNetworkClient.build_for_address()succeeds). - GET vector: responds to
GET /api/public/facilitysearchuser/with a 302 redirect to the target URL. The redirected response body is reflected viaResponse(response.json()). - POST vector: responds to the relevant remote URL with crafted JSON containing additional fields. The full JSON is reflected.
A working PoC has been retained internally and is not published with this advisory.
Demonstrated impact (pre-fix)
- Unauthenticated outbound requests from the Kolibri server to any HTTP(S) URL the attacker chose (GET endpoint only; the others required auth or an unprovisioned device).
- Reflected data exfiltration for any HTTP endpoint that responded to a plain
GETwith JSON and no special request headers. - Cloud metadata reachability was realistic but service-specific:
- AWS IMDSv1 — reachable
- DigitalOcean (
/metadata/v1.json) — reachable - GCP, Azure, AWS IMDSv2 — not reachable via this vector (require
Metadata-Flavor/Metadata/ token headers that the attacker could not inject)
- Reachability of internal HTTP services on the same network as the Kolibri server, with their JSON responses…
- Record
GHSA-4mj9-pf4r-cqrc- CVSS 3.1
- 5.8 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
NVD
5.8
Kolibri is an offline-first education platform. Prior to version 0.19.4, several Kolibri API endpoints accept an unvalidated baseurl parameter and fetch attacker-controlled URLs from the Kolibri server, reflecting the response body back to the caller. The original report identified two endpoints on the RemoteFacilityUser* viewsets; remediation review found two further reflection points on the same pattern. The GET endpoint was unauthenticated. Version 0.19.4 fixes the vulnerability.
- Record
CVE-2026-48053- CVSS 3.1
- 5.8 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
OSV
5.8
Kolibri has Unauthenticated Server-Side Request Forgery (SSRF) in RemoteFacilityUserViewset
Kolibri is an offline-first education platform. Prior to version 0.19.4, several Kolibri API endpoints accept an unvalidated baseurl parameter and fetch attacker-controlled URLs from the Kolibri server, reflecting the response body back to the caller. The original report identified two endpoints on the RemoteFacilityUser* viewsets; remediation review found two further reflection points on the same pattern. The GET endpoint was unauthenticated. Version 0.19.4 fixes the vulnerability.
- Record
CVE-2026-48053- CVSS 3.1
- 5.8 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
OSVGHSA-4mj9-pf4r-cqrc
5.8
Kolibri has Unauthenticated Server-Side Request Forgery (SSRF) in RemoteFacilityUserViewset
Summary
Several Kolibri API endpoints accept an unvalidated baseurl parameter and fetch attacker-controlled URLs from the Kolibri server, reflecting the response body back to the caller. The original report identified two endpoints on the RemoteFacilityUser* viewsets; remediation review found two further reflection points on the same pattern. The GET endpoint was unauthenticated.
Affected endpoints
Reported:
GET /api/auth/remotefacilityuser→RemoteFacilityUserViewset(kolibri/core/auth/api.py:1570). No authentication required.POST /api/auth/remotefacilityauthenticateduserinfo→RemoteFacilityUserAuthenticatedViewset(kolibri/core/auth/api.py:1594). Authentication is checked against the remote server rather than the local Kolibri.
Found during remediation:
POST /api/public/setupwizard/loddata→ setup wizard's remote-signup proxy (kolibri/plugins/setup_wizard/api.py). Reachable on unprovisioned devices.GET /api/public/networklocation/<id>/facilities/→NetworkLocationFacilitiesView(kolibri/core/discovery/api.py). Authenticated but with the sameResponse(remote_payload)pattern.
Root cause
Two compounding issues:
- Response reflection — these endpoints returned the remote server's JSON body more or less verbatim to the caller (
Response(response.json()),Response(facility_info["users"]), etc.). - No restriction on the remote target —
baseurlwas validated only byURLValidator(schemes=["http", "https"]).NetworkClient.build_for_address()would connect to any host with a valid Kolibri-shaped/api/public/info/response, andrequestsfollowed 30x redirects by default, so a hostile peer could pivot the fetch to an arbitrary host (cloud metadata, internal services) before reflection.
Two reflection vectors
GET vector (RemoteFacilityUserViewset):
The viewset fetched <baseurl>/api/public/facilitysearchuser/ and returned Response(response.json()). An attacker-controlled baseurl returned a 302 to an arbitrary internal URL; requests followed the redirect, and the redirected response body was returned to the attacker.
POST vector (RemoteFacilityUserAuthenticatedViewset):
get_remote_users_info() fetched <baseurl>/api/public/facilityuser/ with Basic Auth and the viewset returned Response(facility_info["users"]). A malicious baseurl returned crafted user-shaped JSON; arbitrary smuggled fields were reflected back to the caller. The setup wizard and NetworkLocationFacilitiesView endpoints had the same shape on different remote URLs.
Reproduction
The vulnerability can be reproduced by pointing baseurl at an attacker-controlled HTTP server that:
- Responds to
GET /api/public/info/with a valid Kolibri info payload (soNetworkClient.build_for_address()succeeds). - GET vector: responds to
GET /api/public/facilitysearchuser/with a 302 redirect to the target URL. The redirected response body is reflected viaResponse(response.json()). - POST vector: responds to the relevant remote URL with crafted JSON containing additional fields. The full JSON is reflected.
A working PoC has been retained internally and is not published with this advisory.
Demonstrated impact (pre-fix)
- Unauthenticated outbound requests from the Kolibri server to any HTTP(S) URL the attacker chose (GET endpoint only; the others required auth or an unprovisioned device).
- Reflected data exfiltration for any HTTP endpoint that responded to a plain
GETwith JSON and no special request headers. - Cloud metadata reachability was realistic but service-specific:
- AWS IMDSv1 — reachable
- DigitalOcean (
/metadata/v1.json) — reachable - GCP, Azure, AWS IMDSv2 — not reachable via this vector (require
Metadata-Flavor/Metadata/ token headers that the attacker could not inject)
- Reachability of internal HTTP services on the same network as the Kolibri server, with their JSON responses…
- Record
GHSA-4mj9-pf4r-cqrc- CVSS 3.1
- 5.8 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N - Weakness
- CWE-918
- Updated
- 2026-11-02
OSVPYSEC-2026-2554
5.8
Kolibri has Unauthenticated Server-Side Request Forgery (SSRF) in RemoteFacilityUserViewset
Summary
Several Kolibri API endpoints accept an unvalidated baseurl parameter and fetch attacker-controlled URLs from the Kolibri server, reflecting the response body back to the caller. The original report identified two endpoints on the RemoteFacilityUser* viewsets; remediation review found two further reflection points on the same pattern. The GET endpoint was unauthenticated.
Affected endpoints
Reported:
GET /api/auth/remotefacilityuser→RemoteFacilityUserViewset(kolibri/core/auth/api.py:1570). No authentication required.POST /api/auth/remotefacilityauthenticateduserinfo→RemoteFacilityUserAuthenticatedViewset(kolibri/core/auth/api.py:1594). Authentication is checked against the remote server rather than the local Kolibri.
Found during remediation:
POST /api/public/setupwizard/loddata→ setup wizard's remote-signup proxy (kolibri/plugins/setup_wizard/api.py). Reachable on unprovisioned devices.GET /api/public/networklocation/<id>/facilities/→NetworkLocationFacilitiesView(kolibri/core/discovery/api.py). Authenticated but with the sameResponse(remote_payload)pattern.
Root cause
Two compounding issues:
- Response reflection — these endpoints returned the remote server's JSON body more or less verbatim to the caller (
Response(response.json()),Response(facility_info["users"]), etc.). - No restriction on the remote target —
baseurlwas validated only byURLValidator(schemes=["http", "https"]).NetworkClient.build_for_address()would connect to any host with a valid Kolibri-shaped/api/public/info/response, andrequestsfollowed 30x redirects by default, so a hostile peer could pivot the fetch to an arbitrary host (cloud metadata, internal services) before reflection.
Two reflection vectors
GET vector (RemoteFacilityUserViewset):
The viewset fetched <baseurl>/api/public/facilitysearchuser/ and returned Response(response.json()). An attacker-controlled baseurl returned a 302 to an arbitrary internal URL; requests followed the redirect, and the redirected response body was returned to the attacker.
POST vector (RemoteFacilityUserAuthenticatedViewset):
get_remote_users_info() fetched <baseurl>/api/public/facilityuser/ with Basic Auth and the viewset returned Response(facility_info["users"]). A malicious baseurl returned crafted user-shaped JSON; arbitrary smuggled fields were reflected back to the caller. The setup wizard and NetworkLocationFacilitiesView endpoints had the same shape on different remote URLs.
Reproduction
The vulnerability can be reproduced by pointing baseurl at an attacker-controlled HTTP server that:
- Responds to
GET /api/public/info/with a valid Kolibri info payload (soNetworkClient.build_for_address()succeeds). - GET vector: responds to
GET /api/public/facilitysearchuser/with a 302 redirect to the target URL. The redirected response body is reflected viaResponse(response.json()). - POST vector: responds to the relevant remote URL with crafted JSON containing additional fields. The full JSON is reflected.
A working PoC has been retained internally and is not published with this advisory.
Demonstrated impact (pre-fix)
- Unauthenticated outbound requests from the Kolibri server to any HTTP(S) URL the attacker chose (GET endpoint only; the others required auth or an unprovisioned device).
- Reflected data exfiltration for any HTTP endpoint that responded to a plain
GETwith JSON and no special request headers. - Cloud metadata reachability was realistic but service-specific:
- AWS IMDSv1 — reachable
- DigitalOcean (
/metadata/v1.json) — reachable - GCP, Azure, AWS IMDSv2 — not reachable via this vector (require
Metadata-Flavor/Metadata/ token headers that the attacker could not inject)
- Reachability of internal HTTP services on the same network as the Kolibri server, with their JSON responses…
- Record
PYSEC-2026-2554- CVSS 3.1
- 5.8 Medium
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:N/A:N - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
kolibriPyPI |
through 0.19.3 | 0.19.4 |
kolibriPyPI |
before 0.19.4, plus listed versions 0.0.1.dev201605311128590.1.1rc20.1.1rc30.10.00.10.1 Show 45 moreShow less0.10.20.10.30.10.3b20.10.3b30.11.00.11.0b20.11.10.12.00.12.0b50.12.0b60.12.0b70.12.0b80.12.0b90.12.10.12.10b30.12.20.12.30.12.3b10.12.40.12.4b20.12.4b30.12.4b50.12.4b60.12.4b70.12.4b80.12.50.12.5b10.12.5b20.12.60.12.6b10.12.6b20.12.6rc10.12.70.12.80.12.8rc10.12.90.12.9rc10.13.00.13.0b20.13.0b30.13.0b40.13.0b50.13.0b60.13.0b70.13.0b8 |
0.19.4 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-48053 is a medium vulnerability (CVSS 5.8) in Learningequality Kolibri, published June 11, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.38%, the 32nd percentile. Fixed in kolibri 0.19.4.
References
github.com/learningequality/kolibri/security/advisories/GHSA-4mj9-pf4r-cqrc
github.com/learningequality/kolibri/releases/tag/v0.19.4
github.com/pypa/advisory-database/tree/main/vulns/kolibri/PYSEC-2026-2554.yaml
github.com/advisories/GHSA-4mj9-pf4r-cqrc
github.com/CVEProject/cvelistV5/tree/main/cves/2026/48xxx/CVE-2026-48053.json
nvd.nist.gov/vuln/detail/CVE-2026-48053
github.com/learningequality/kolibri
pypi.org/project/kolibri
Left out here: 76 versions and the rest of 3 source descriptions. The JSON record has them.