Every workflow run is automatically provisioned with a GITHUB_TOKEN, which is used to authenticate with the GitHub API. The default scope of this token is read-only on most permissions, so any workflow that needs to write back to the repository or otherwise perform privileged actions must explicitly elevate its permissions. The permissions: key, usable at both workflow and job level, controls this; permissions: contents: read grants read-only repository content access, permissions: read-all grants read-only access across all available scopes, and job-level settings override workflow-level settings.
When a workflow needs to commit and push code as part of its automation, a common pattern is to set permissions: contents: write on the job, configure git with the recommended bot identity github-actions[bot] and the email 41898282+github-actions[bot]@users.noreply.github.com, and then use the GITHUB_TOKEN for authentication. The peter-evans/create-pull-request action is a popular tool for automating the creation of pull requests from a branch after commits are pushed.
Security considerations are especially important around pull_request events. The pull_request_target trigger runs in the base repository context with write permissions and is a frequent source of script injection attacks, so it should be used with extreme caution. Self-hosted runners on public repositories carry a similar risk: malicious pull requests from forks can run untrusted code on your own infrastructure. The standard mitigations are to require approval for first-time contributors, use fork-PR approval settings, and prefer ephemeral runners. GitHub-hosted runners, by contrast, start fresh for each job and have open egress to the public internet, so private networking requires a self-hosted runner.