amir20/dozzle · warning

Forbidden

Error message

Forbidden

What it means

findContainerWithActions enforces that the authenticated user has the Actions role (or is admin) before performing start/stop/restart/update on a container. Without the role the handler logs a warning and returns 403 Forbidden.

Solutions

  1. Grant the user the actions role (admin level or explicit role in users.yml / proxy role header)
  2. Perform the action as an admin user
  3. If restriction is intentional, perform start/stop/restart with docker CLI instead
  4. Verify the proxy is forwarding the roles header if using forward auth

Example fix

# before (users.yml)
admin: {email: admin@example.com, password: "..."}
# after
admin: {email: admin@example.com, password: "...", name: admin, roles: [admin]}
Defensive patterns

Strategy: validation

Validate before calling

const me = await (await fetch('/api/user', {credentials:'include'})).json();
const canAct = me.roles?.includes('admin') || me.roles?.includes('actions');
if (!canAct) console.warn('user lacks container action permissions');

Try / catch

const res = await fetch(actionUrl, {method: 'POST', credentials: 'include'});
if (res.status === 403) {
  showError('Your account is not allowed to control containers');
}

Prevention

When it happens

Trigger: POST /api/hosts/{host}/containers/{id}/actions/{action} or /update by a user whose roles lack auth.Actions; non-admin users in simple auth; forward-proxy setups mapping the user to a read-only role.

Common situations: Users file configured without the actions role in users.yml; proxy header omitting roles so defaults exclude Actions; orgs restricting destructive actions deliberately.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07). Data as JSON: /api/errors/02b52859f5101743. Report an issue: GitHub.

Appendix: source

Thrown at internal/web/actions.go:29

	"github.com/rs/zerolog/log"
)

func (h *handler) findContainerWithActions(w http.ResponseWriter, r *http.Request) (*container_support.ContainerService, bool) {
	id := chi.URLParam(r, "id")

	userLabels := h.config.Labels
	permit := true
	if h.config.Authorization.Provider != NONE {
		user := auth.UserFromContext(r.Context())
		if user.ContainerLabels.Exists() {
			userLabels = user.ContainerLabels
		}
		permit = user.Roles.Has(auth.Actions)
	}

	if !permit {
		log.Warn().Msg("user is not permitted to perform actions on container")
		http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
		return nil, false
	}

	containerService, err := h.hostService.FindContainer(hostKey(r), id, userLabels)
	if err != nil {
		log.Error().Err(err).Msg("error while trying to find container")
		http.Error(w, err.Error(), http.StatusNotFound)
		return nil, false
	}

	return containerService, true
}

func (h *handler) containerActions(w http.ResponseWriter, r *http.Request) {
	action := chi.URLParam(r, "action")

	containerService, ok := h.findContainerWithActions(w, r)
	if !ok {

View on GitHub (pinned to d9463cbe21)