Forums Bug Reports Thread

IDOR: photo comments readable on any item regardless of album privacy (no viewableBy gate)

Patrick Bass · Jun 6 · 12 · 1 Locked
[Major] [High Priority] [Bug Fixed] [Always Reproduces]
🚀 OP Jun 6, 2026 6:00pm

Area: Files, photos, gallery, ansi (audit p5) · Surface: GET /photos/item/{id}/comments (PhotoGalleryController@listComments) · Dimension: security · Severity: major

OWASP A01:2021 Broken Access Control (IDOR). The comments-listing endpoint never resolves the parent album or checks viewability, so a logged-in user can enumerate photo item IDs and harvest the full comment thread (text, author usernames, avatars) on any photo on the tenant — including photos in albums the owner restricted to 'only me' or 'friends'. This leaks private social content and an inventory of who interacted with private photos.

Evidence

platform/src/Controllers/PhotoGalleryController.php:734-746 — listComments() runs the SQL directly with no album lookup and no permission check:
```php
public function listComments(string $id): void
{
    $rows = $this->db->fetchAll(
        'SELECT c.id, c.body, c.created_at, u.username, u.profile_photo
         FROM photo_comments c
         JOIN users u ON u.id = c.user_id
         WHERE c.item_id = :i AND c.is_deleted = 0
         ORDER BY c.created_at ASC
         LIMIT 50',
        ['i' => (int) $id]
    );
    $this->json(['ok' => true, 'comments' => $rows]);
}
```
Contrast with the sibling listTags() at PhotoGalleryController.php:918-936, which loads the item + album and calls `PhotoAlbum::viewableBy($album, $viewerId)` before returning. viewableBy (src/Models/PhotoAlbum.php:189) enforces only_me=owner-only and friends=friends-only. Route is auth-gated (routes.php:1045, inside the AuthMiddleware group) but ANY logged-in user can iterate the sequential integer item_id and read comment bodies + commenter usernames + profile_photo on photos in private (only_me / friends) albums.

Suggested fix. Mirror listTags(): load the item via PhotoAlbumItem::findById, load the album via PhotoAlbum::findById, and return 403/404 unless PhotoAlbum::viewableBy($album, $viewerId) is true before running the comments query.

Filed by the automated tenant-app audit and adversarially evidence-verified. Status: verified. Open — not yet actioned.


Patrick Bass
@mobieus

🚀 Jun 7, 2026 4:59am

Resolved — fixed and deployed. Commit faa14fc59739, shipped dev-first then to all tenants on 2026-06-06.

listComments() now mirrors listTags(): loads the item via PhotoAlbumItem::findById and album via PhotoAlbum::findById (404 if missing) and returns 403 unless PhotoAlbum::viewableBy($album,$viewerId) before running the comments query.

Status: fixed. Thread closed and locked.


Patrick Bass
@mobieus

Log in or register to reply to this thread.