Report #17947
[bug\_fix] Self-hosted runner fails with 'detected dubious ownership in repository' or permission denied due to file ownership mismatches from previous container runs
Configure the self-hosted runner to execute a cleanup script before each job \(using the \`ACTIONS\_RUNNER\_HOOK\_JOB\_STARTED\` environment variable pointing to a script that runs \`sudo chown -R $\(whoami\):$\(whoami\) $GITHUB\_WORKSPACE\` and \`git config --global --add safe.directory $GITHUB\_WORKSPACE\`\), or use ephemeral runners that are reset after each job. The root cause is that previous workflow runs \(especially those using container jobs that run as root\) leave files in the workspace owned by root; the self-hosted runner service \(running as a non-root user\) cannot modify these files, and recent Git versions \(post-CVE-2022-24765\) refuse to operate on directories not owned by the current user.
Journey Context:
An organization uses a persistent self-hosted runner on an on-premise Ubuntu server running as user \`github-runner\`. A workflow uses \`jobs: build: runs-on: self-hosted container: image: node:18\` which runs as root inside the container. It creates \`node\_modules\` and some build artifacts owned by root:root. The job completes. The next workflow run starts on the same runner. The \`actions/checkout\` step fails immediately with "fatal: detected dubious ownership in repository at '/home/github-runner/\_work/repo/repo'" or with "Permission denied" when trying to delete the old \`node\_modules\`. The developer logs into the server and sees files owned by root. They learn that GitHub recommends using ephemeral runners, but they can't easily rebuild the VM each time. They find the documentation on runner hooks \(\`ACTIONS\_RUNNER\_HOOK\_JOB\_STARTED\`\). They create a script \`/home/github-runner/cleanup.sh\` that runs \`sudo chown -R github-runner:github-runner /home/github-runner/\_work\` and \`git config --global --add safe.directory /home/github-runner/\_work/repo/repo\`. They set the environment variable on the runner service. Now, before each job, the ownership is fixed, and \`actions/checkout\` succeeds.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T06:49:47.822514+00:00— report_created — created