Overview

This PR introduces granular permission controls for Gitea Actions tokens (GITEA_TOKEN), aligning Gitea’s security model with GitHub Actions standards while maintaining compatibility with Gitea’s unique repository unit system.

It addresses the need for finer access control by allowing administrators and repository owners to define default token permissions, set maximum permission ceilings, and control cross-repository access within organizations.

Key Features

1. Granular Token Permissions
  • Standard Keyword Support: Implements support for the permissions: keyword in workflow and job YAML files (e.g., contents: read, issues: write).
  • Permission Modes:
    • Permissive: Default write access for most units (backwards compatible).
    • Restricted: Default read-only access for contents and packages, with no access to other units.
    • Custom: Allows defining specific default levels for each unit type (Code, Issues, PRs, Packages, etc.).
  • Clamping Logic: Workflow-defined permissions are automatically “clamped” by repository or organization-level maximum settings. Workflows cannot escalate their own permissions beyond these limits.
2. Organization & Repository Settings
  • Settings UI: Added new settings pages at both Organization and Repository levels to manage Actions token defaults and maximums.
  • Inheritance: Repositories can be configured to “Follow organization-level configuration,” simplifying management across large organizations.
  • Cross-Repository Access: Added a policy to control whether Actions workflows can access other repositories or packages within the same organization. This can be set to “None,” “All,” or restricted to a “Selected” list of repositories.
3. Security Hardening
  • Fork Pull Request Protection: Tokens for workflows triggered by pull requests from forks are strictly enforced as read-only, regardless of repository settings.
  • Package Access: Actions tokens can now only access packages explicitly linked to a repository, with cross-repo access governed by the organization’s security policy.
  • Git Hook Integration: Propagates Actions Task IDs to git hooks to ensure that pushes performed by Actions tokens respect the specific permissions granted at runtime.
4. Technical Implementation
  • Permission Persistence: Parsed permissions are calculated at job creation and stored in the action_run_job table. This ensures the token’s authority is deterministic throughout the job’s lifecycle.
  • Parsing Priority: Implemented a priority system in the YAML parser where the broad contents scope is applied first, allowing granular scopes like code or releases to override it for precise control.
  • Re-runs: Permissions are re-evaluated during a job re-run to incorporate any changes made to repository settings in the interim.

How to Test

  1. Unit Tests: Run go test ./services/actions/... and go test ./models/repo/... to verify parsing logic and permission clamping.
  2. Integration Tests: Comprehensive tests have been added to tests/integration/actions_job_token_test.go covering:
    • Permissive vs. Restricted mode behavior.
    • YAML permissions: keyword evaluation.
    • Organization cross-repo access policies.
    • Resource access (Git, API, and Packages) under various permission configs.
  3. Manual Verification:
    • Navigate to Site/Org/Repo Settings -> Actions -> General.
    • Change “Default Token Permissions” and verify that newly triggered workflows reflect these changes in their GITEA_TOKEN capabilities.
    • Attempt a cross-repo API call from an Action and verify the Org policy is enforced.

Documentation

Added a PR in gitea’s docs for this : https://gitea.com/gitea/docs/pulls/318

UI:

Screenshot 2026-01-24 174112 Screenshot 2026-01-24 174048

/fixes #24635 /claim #24635

Claim

Total prize pool $590
Total paid $0
Status Pending
Submitted December 17, 2025
Last updated January 07, 2026

Contributors

EX

Excellencedev

@Excellencedev

100%

Sponsors

FR

Frank

@Frankkkkk

$200
JI

jibeddari

@jibeddari

$20
MI

Michael Aldridge

@the-maldridge

$200
AL

Alexandre Magno

@alexanmtz

$100
MA

Markus Fenes

@mafen

$70