Skip to content

warn when running as root/Administrator to prevent daemon.lock issues#1431

Merged
svarlamov merged 20 commits into
mainfrom
fix/1287-1779581297
Jun 5, 2026
Merged

warn when running as root/Administrator to prevent daemon.lock issues#1431
svarlamov merged 20 commits into
mainfrom
fix/1287-1779581297

Conversation

@svarlamov

@svarlamov svarlamov commented May 24, 2026

Copy link
Copy Markdown
Member

Summary

Fixes #1287

  • Adds a superuser guard that detects elevated privileges (root on Unix, Administrator on Windows) and blocks git-ai commands with a clear error message explaining the issue and how to fix it
  • Automatically bypasses the guard in CI/agent sandbox environments (CI, GITHUB_ACTIONS, GITLAB_CI, JENKINS_URL, BUILDKITE, CIRCLECI, CODEBUILD_BUILD_ID, AGENT_OS, KUBERNETES_SERVICE_HOST)
  • Allows explicit opt-in via GIT_AI_ALLOW_SUPERUSER=1 env var (with a runtime warning)
  • Exempts commands that must always work: version, help, upgrade, debug, uninstall-hooks, and daemon run/status/shutdown (for self-update flows)
  • Does NOT guard the git proxy path — when invoked as git, behavior remains transparent

Root Cause

Installing git-ai as root/Administrator creates daemon.lock and other files owned by root. When the normal user account subsequently runs git-ai, it cannot acquire the lock, causing persistent "daemon startup blocked: lock held" errors. The fix prevents this footgun at the source.

Test plan

  • Unit tests for is_running_as_superuser(), superuser_is_allowed(), is_superuser_expected_environment()
  • Integration tests verifying exempt commands work, env var override works, and non-root invocations aren't affected
  • Verified manually with sudo: blocked without opt-in, allowed with GIT_AI_ALLOW_SUPERUSER=1, allowed with CI=true
  • Verified upgrade and daemon run are exempt (auto-update flow)
  • Verified git proxy mode (GIT_AI=git) is not guarded
  • Full test suite passes (3032/3032, 1 pre-existing flaky test)

🤖 Generated with Claude Code


Open in Devin Review

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@svarlamov svarlamov force-pushed the fix/1287-1779581297 branch from dff8ec1 to dec42da Compare May 30, 2026 16:34
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

svarlamov and others added 14 commits June 5, 2026 17:29
…n.lock issues

When git-ai is installed or run as root/Administrator, it creates files
(daemon.lock, sockets, config) owned by root that become inaccessible
to the normal user account. This causes persistent "daemon startup
blocked: lock held" errors that require manual cleanup.

This adds a superuser guard that detects elevated privileges and refuses
to run with a clear error message explaining how to fix the issue.

The guard is automatically bypassed in CI/agent sandbox environments
(detected via CI, GITHUB_ACTIONS, GITLAB_CI, etc. env vars) and can
be explicitly overridden with GIT_AI_ALLOW_SUPERUSER=1 (with a warning).

Exempt commands that must always work: version, help, upgrade, debug,
uninstall-hooks, and daemon run/status/shutdown (for self-update flows).
The git proxy path is not guarded to remain transparent.

Fixes #1287

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…n declarations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ed import

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… paths

Address Devin review feedback: the opt-in and CI environment tests were
using `version` (an exempt command), so they never exercised the actual
superuser guard logic. Changed to use `status` and verify the warning
message (opt-in) or absence of blocking (CI).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Block installation as root/Administrator at the install script level,
before any files are created. This prevents the root cause of #1287
at the earliest possible point.

Auto-allows in:
- CI environments (CI, GITHUB_ACTIONS, GITLAB_CI, etc.)
- MDM deployments (INSTALL_USER set by JAMF detection)
- Daemon-triggered self-updates (GIT_AI_RELEASE_TAG or
  GIT_AI_RESTART_DAEMON_AFTER_INSTALL set by upgrade command)

Override with: GIT_AI_ALLOW_SUPERUSER=1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…oot-guard bypass

Replace GIT_AI_RELEASE_TAG (user-facing version pinning var) with a
private GIT_AI_DAEMON_UPGRADE env var that is only set internally by
the upgrade command during daemon self-updates. This prevents users
from inadvertently bypassing the root/sudo guard by setting
GIT_AI_RELEASE_TAG for manual version pinning.

Also adds allow_superuser config flag to ~/.git-ai/config.json as an
alternative to the GIT_AI_ALLOW_SUPERUSER env var.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The install scripts invoke git-ai subcommands (install-hooks,
exchange-nonce) as child processes that inherit the env var. Without
this check, those post-install commands would be blocked by the
superuser guard during daemon self-upgrades running as root.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…install scripts

When the install script decides root is acceptable (CI, MDM, daemon
upgrade), export GIT_AI_ALLOW_SUPERUSER=1 so that post-install
commands (install-hooks, exchange-nonce, login) also pass the binary's
superuser guard.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of refusing to run as root/Administrator, emit a deprecation
warning that a future version will block. This makes initial rollout
less disruptive while still surfacing the issue to users.

The warning is suppressed in CI, MDM, and daemon-upgrade environments.
Users can also suppress it by setting GIT_AI_ALLOW_SUPERUSER=1 or
adding "allow_superuser": true to ~/.git-ai/config.json.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The tests mutate process-global env vars (CI, GIT_AI_ALLOW_SUPERUSER)
and must not run concurrently with other env-var-sensitive tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Detect container environments via the `container` env var (set by
podman, systemd-nspawn, and other runtimes) and `/.dockerenv` (created
by Docker in every container). This prevents the deprecation warning
from firing inside containers where running as root is the norm.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@svarlamov svarlamov force-pushed the fix/1287-1779581297 branch from c0a2c00 to cb72921 Compare June 5, 2026 17:31
svarlamov and others added 2 commits June 5, 2026 17:33
Clearer verbiage: running as root isn't deprecated (implies removal on a
timeline), it's simply not recommended due to file ownership issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@svarlamov svarlamov changed the title fix: block running as root/Administrator to prevent daemon.lock issues warn when running as root/Administrator to prevent daemon.lock issues Jun 5, 2026
svarlamov and others added 4 commits June 5, 2026 19:04
…rship

The previous check used IsInRole(Administrator) which returns true for
any user in the Administrators group — the default for most Windows
users, even in non-elevated terminals. This caused false warnings during
normal installs.

Now checks token ownership: when UAC-elevated, the token owner is
BUILTIN\Administrators (S-1-5-32-544); when non-elevated, it's the
user's own SID. This matches what the Rust binary does via
TokenElevation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Owner-based check still returns true for admin-group users in
non-elevated terminals (Owner is BUILTIN\Administrators regardless of
elevation on many Windows configurations).

Instead check for the High Mandatory Level SID (S-1-16-12288) in the
token's groups — this is only present when the process is actually
UAC-elevated ("Run as Administrator"). Non-elevated admin users have
Medium integrity (S-1-16-8192) and won't trigger the warning.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Neither the Owner-based check nor the integrity level SID approach
works reliably across Windows configurations. Use the same Win32
TokenElevation API that the Rust binary uses — this is the definitive
way to detect "Run as Administrator" vs normal admin-group user.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
always-admin accounts

TokenElevation (class 20) returns true for users with UAC disabled or
the built-in Administrator account, causing false warnings. These users
always run elevated so there's no file-ownership mismatch.

Switch to TokenElevationType (class 18) which returns:
- Type 1 (Default): no split token, always-admin → don't warn
- Type 2 (Full): explicitly elevated via "Run as Administrator" → warn
- Type 3 (Limited): non-elevated terminal → don't warn

Only type 2 creates the permission mismatch from issue #1287.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@svarlamov svarlamov merged commit 0746d43 into main Jun 5, 2026
23 checks passed
@svarlamov svarlamov deleted the fix/1287-1779581297 branch June 5, 2026 21:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows daemon startup is blocked by daemon.lock when installed as Administrator/Root

1 participant