Portainer supports restoring an instance from a backup archive via the /api/restore endpoint. This endpoint is intentionally unauthenticated to allow restoring before the first admin account is created, and remains accessible for the five-minute initialization window that opens each time Portainer starts. Any unauthenticated attacker with network access to a Portainer instance that has not yet been initialised can exploit this window to replace the Portainer database with a crafted …
Portainer proxies requests to Kubernetes clusters through a middleware layer (kubeClientMiddleware) that validates the requesting user's token before forwarding traffic to the cluster. When security.RetrieveTokenData returned an error, the middleware wrote an HTTP 403 response but was missing a return statement — execution continued into the handler with a nil tokenData value. The Kubernetes endpoints sit behind Portainer's outer AuthenticatedAccess bouncer, so an attacker requires a valid Portainer session. However, …
Portainer's authentication middleware accepts JWT bearer tokens passed as the ?token=<JWT> URL query parameter on any authenticated API endpoint, in addition to the standard Authorization: Bearer header. URLs are recorded in reverse-proxy access logs, browser history, and HTTP Referer headers on outbound navigation, so any JWT passed this way can be harvested by anyone with access to those logs or by an external site the user subsequently visits. A leaked …
Portainer enforces Role-Based Access Control (RBAC) on top of the Docker API. The proxy layer routes incoming Docker API requests to per-resource handlers (containers, images, services, volumes, etc.) that apply authorization checks. The Docker plugin management endpoints (/plugins/*) were not registered with a handler, so standard users with endpoint access could call privileged plugin operations — including installing and enabling plugins — directly against the underlying Docker daemon. The vulnerability …
A missing authorization vulnerability in the Custom Template file endpoint (GET /api/custom_templates/{id}/file) allows any authenticated user to read the file content of any custom template by enumerating sequential integer IDs, bypassing Resource Control access restrictions. Template files may contain environment-specific values such as connection strings, API tokens, or registry credentials that administrators would not expect standard users to read.
Portainer enforces seven EndpointSecuritySettings restrictions that administrators configure to restrict the container configurations non-admin users can launch: privileged mode, host PID namespace, device mapping, capabilities, sysctls, security-opt (Seccomp / AppArmor), and bind mounts. The vulnerability is exposed when a non-admin Portainer user (Standard User role, or any role granted endpoint-level access) has been given access to a Docker Swarm endpoint via Portainer RBAC. Admins and users without Swarm endpoint access …
Portainer supports deploying stacks from Git repositories. When a Git-backed stack is created or updated, Portainer clones the repository using go-git v5, which translates Git blob entries with mode 0o120000 (symlink) into real OS symlinks on the host filesystem via os.Symlink. The only entry blocked from becoming a symlink is .gitmodules; every other path — including docker-compose.yml, which Portainer treats as the stack entry point — is created as a …
Portainer's backup restore feature accepts a .tar.gz archive and extracts it to a target directory on the server. The extraction function (ExtractTarGz in api/archive/targz.go) constructed output paths using filepath.Clean(filepath.Join(outputDirPath, header.Name)). This combination does not prevent directory traversal — a tar entry named ../../etc/cron.d/evil resolves to a path outside the extraction root, so a crafted archive can write files to arbitrary locations on the server filesystem.
Portainer offers an environment-level Disable bind mounts for non-administrators security setting that blocks regular users from binding host paths into containers they create through the Portainer-mediated Docker API. The check that enforces this setting only inspected the legacy HostConfig.Binds array on the container-create proxy and never looked at the equivalent HostConfig.Mounts array. Any authenticated user with rights to create containers on a Docker environment where the restriction is enabled could …