# Portainer has Unauthenticated Restore Endpoint that Allows Admin Takeover on Uninitialized Instances

Unauthenticated /api/restore on uninitialized Portainer accepts a crafted backup archive, letting an attacker replace the DB with their own admin credentials.

- Payout: Research
- Severity: high
- Program: Portainer
- Found by: um3b0shi
- Disclosed: 2026-08-28
- CVE: CVE-2026-55761
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-x626-fcwx-f5pc
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-x626-fcwx-f5pc
- Tags: area:cloud domain:infra domain:web impact:ato impact:internal-access impact:privesc kind:research platform:ghsa sev:high tech:docker technique:race-window vuln:access-control vuln:auth-bypass vuln:race-condition

**Target:** /api/restore and /api/users/admin/init HTTP endpoints on Portainer server
**Root cause:** Restore and admin-init handlers are registered with bouncer.PublicAccess and only check WasInitialized(), so during the five-minute post-boot setup window any unauthenticated caller can restore an arbitrary archive or create the first admin.
**Steps:**
1. Deploy/restart Portainer without a pre-set admin password so it is uninitialized.
2. Within the five-minute setup window, POST a crafted backup archive to `/api/restore` (no auth headers).
3. Handler sees WasInitialized()==false, calls adminMonitor.Stop() and restores the archive unconditionally.
4. Log in with the attacker-controlled admin credentials embedded in the restored database.
5. Alternatively POST to `/api/users/admin/init` to create the first administrator directly.
**How found:** Reporter noticed the restore endpoint is deliberately unauthenticated to support pre-init restores and that its only guard is WasInitialized(), making the boot-time setup window a raceable auth bypass; team extended coverage to the companion /api/users/admin/init endpoint.
**Exploitation:** Attacker with network reach to a fresh/restarted Portainer instance races the five-minute setup window, uploads a backup archive containing their own admin user to /api/restore, then authenticates as full admin. From there they use the Docker socket access to mount the host filesystem and run commands as root, and inherit credentials for all registered Docker/K8s/edge environments.
**Escalation:** Portainer admin -> Docker socket (/var/run/docker.sock) -> host root via container creation mounting host FS; plus access to all managed clusters and stored registry/env secrets; persistence by re-inserting admin rows in the attacker-controlled DB.
**Insight:** Endpoints intentionally left public for bootstrap/first-run flows (restore, admin init, setup wizards) are gated only by an 'is initialized' flag — enumerate such pre-auth setup routes and race the boot window rather than attacking the authenticated surface.

