JuliusBrussee/caveman · error

githubapp: permission %q=%q exceeds the least-agency allowli

Error message

githubapp: permission %q=%q exceeds the least-agency allowlist

What it means

Least-privilege enforcement in MintInstallationToken(): a requested permission name or level is outside the allowlist (only known names with level read/write are accepted). This blocks minting tokens with broad or dangerous permissions (e.g. admin, delete) before any network call.

Source

Thrown at shared/platform/githubapp/githubapp.go:202

// `repos` and `perms`, returning a ~1h token. Defaults (perms nil) are
// contents:write + pull_requests:write — enough to push a branch and open a draft
// PR, never to merge.
func (a *App) MintInstallationToken(ctx context.Context, installationID int64, repos []string, perms map[string]string) (InstallationToken, error) {
	if installationID <= 0 {
		return InstallationToken{}, fmt.Errorf("githubapp: installation id must be positive")
	}
	if len(repos) != 1 || strings.TrimSpace(repos[0]) == "" {
		return InstallationToken{}, fmt.Errorf("githubapp: exactly one repository is required")
	}
	repository := strings.TrimSpace(repos[0])
	if perms == nil {
		perms = map[string]string{"contents": "write", "pull_requests": "write"}
	}
	allowedPermissions := map[string]bool{"contents": true, "pull_requests": true}
	scopedPermissions := make(map[string]string, len(perms))
	for name, level := range perms {
		if !allowedPermissions[name] || (level != "read" && level != "write") {
			return InstallationToken{}, fmt.Errorf("githubapp: permission %q=%q exceeds the least-agency allowlist", name, level)
		}
		scopedPermissions[name] = level
	}
	jwt, err := a.AppJWT()
	if err != nil {
		return InstallationToken{}, err
	}
	body := map[string]any{"permissions": scopedPermissions, "repositories": []string{repository}}
	status, raw, err := a.do(ctx, "Bearer "+jwt, http.MethodPost,
		"/app/installations/"+strconv.FormatInt(installationID, 10)+"/access_tokens", body)
	if err != nil {
		return InstallationToken{}, err
	}
	if status != http.StatusCreated {
		return InstallationToken{}, fmt.Errorf("githubapp: mint token: HTTP %d: %s", status, snippet(raw))
	}
	var out InstallationToken
	if err := json.Unmarshal(raw, &out); err != nil {

View on GitHub (pinned to 766dce6b13)

Solutions

  1. Request only allowlisted permissions (e.g. contents, pull_requests) at read/write levels
  2. Pass nil perms to accept the safe defaults (contents:write + pull_requests:write)
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at shared/platform/githubapp/githubapp.go:202 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of JuliusBrussee/caveman@766dce6b13 (2026-08-18). Data as JSON: /api/errors/188bcabfd9f664f2. Report an issue: GitHub.