# OS protection gate (/docs/agents/os-protection-gate)

Why agent tools refuse to run while UAC, SIP, Gatekeeper or a screen lock is off, every check per OS, overrides, org policy and the CLI flags.

Agent tools act on your system: they run shell commands, edit files, control apps and, on Android, operate the phone. Before any of that runs, every codai surface checks that the operating system's **minimum protections** are on. While a required protection is off, agent tools are disabled and the agent tells you what is off and how to fix it. Chat keeps working; only tools stop.

Each check has a level:

- **BLOCK** (shown as _Required_) — while it fails, agent tools are refused unless you override that specific check.
- **WARN** (shown as _Recommended_) — only a banner; tools keep running.

The surface is in one of four states: **ok** (nothing fails), **warn** (only WARN checks fail), **overridden** (every failing BLOCK check has a valid override — tools run under a permanent banner) or **block** (at least one failing BLOCK check without a valid override — tools are disabled).

## Checks [#checks]

### Windows [#windows]

| Check                  | Level | What it means                                       | How it is detected                                                                                                     |
| ---------------------- | ----- | --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `win.uac_off`          | BLOCK | User Account Control is turned off                  | `EnableLUA == 0` under `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System` (a missing value counts as on) |
| `win.uac_no_prompt`    | BLOCK | Administrator actions are approved without a prompt | `ConsentPromptBehaviorAdmin == 0` while UAC is on and the user is an administrator                                     |
| `win.elevated`         | WARN  | codai is running as administrator                   | The process token is elevated while UAC is on                                                                          |
| `win.defender_rtp_off` | WARN  | Microsoft Defender real-time protection is off      | `DisableRealtimeMonitoring == 1` in the Defender policy or settings registry key                                       |

### macOS [#macos]

| Check                | Level | What it means                      | How it is detected                              |
| -------------------- | ----- | ---------------------------------- | ----------------------------------------------- |
| `mac.sip_off`        | BLOCK | System Integrity Protection is off | `csrutil status` reports `status: disabled`     |
| `mac.gatekeeper_off` | BLOCK | Gatekeeper is off                  | `spctl --status` reports `assessments disabled` |
| `mac.filevault_off`  | WARN  | FileVault disk encryption is off   | `fdesetup status` reports `FileVault is Off`    |

### Linux [#linux]

| Check                  | Level | What it means                             | How it is detected                                                                                                |
| ---------------------- | ----- | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `linux.root`           | BLOCK | Agent tools would run as root on the host | Effective uid 0 outside a container (codaid per-user mode with a verified privilege drop is exempt)               |
| `linux.root_container` | WARN  | Running as root inside a container        | Effective uid 0 with container markers (`/.dockerenv`, `/run/.containerenv`, container cgroups or Kubernetes env) |
| `linux.sudo_nopasswd`  | WARN  | `sudo` works without a password           | `sudo -n -k true` exits 0 for a non-root user                                                                     |
| `linux.no_screen_lock` | WARN  | The screen does not lock                  | Desktop sessions only: GNOME `lock-enabled` is `false`                                                            |

### Android and Wear OS [#android-and-wear-os]

| Check                    | Level | What it means                             | How it is detected                                                                  |
| ------------------------ | ----- | ----------------------------------------- | ----------------------------------------------------------------------------------- |
| `android.no_secure_lock` | BLOCK | The phone has no secure screen lock       | `KeyguardManager.isDeviceSecure()` is `false`                                       |
| `android.lock_unknown`   | WARN  | The screen-lock state is unknown          | mobile-agent in Termux cannot read the lock state without the app                   |
| `android.adb_enabled`    | WARN  | USB debugging or developer options are on | `ADB_ENABLED` or `DEVELOPMENT_SETTINGS_ENABLED` is `1`                              |
| `android.rooted`         | WARN  | The device appears to be rooted           | Best effort: an `su` binary in the usual paths or `test-keys` build tags            |
| `wear.no_secure_lock`    | BLOCK | The watch has no screen lock              | `KeyguardManager.isDeviceSecure()` is `false` on the watch (banner only, see below) |

A probe that errors reports nothing and the check is listed as _Could not be checked_: a detection bug never locks you out. Results are cached for five minutes; **Check again** in Settings re-runs them at once.

## Overriding a check [#overriding-a-check]

If you understand the risk, open **Settings > Security** and choose **Allow agent tools anyway** on the failing check. The override:

- covers **only that check** — a different protection that turns off later blocks tools again;
- lasts **30 days**, after which the check blocks again until you fix it or override it again;
- keeps a **permanent warning banner** visible on every screen while it is active;
- is written to the **audit log** (locally, and to your account when you are signed in);
- can be revoked at any time with **Revoke override**.

## Organization policy [#organization-policy]

Organization admins can forbid overrides in the hub under **Team > Security**. The strictest rule wins: if **any** organization you belong to forbids overrides, you cannot grant one and existing overrides stop counting. Clients read the policy from [`GET /v1/policy`](../api/gateway/os-gate.mdx), cache the last value and keep using it offline; before the first fetch the default is to allow overrides. The CLI flags below cannot bypass an organization ban.

## Command line [#command-line]

| Command                                          | Effect                                                                                                           |
| ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| `codaid run --allow-insecure-host`               | Overrides every failing BLOCK check for this process only (still audited, still subject to the org policy)       |
| `CODAI_ALLOW_INSECURE_HOST=1`                    | The same for commands without the flag, such as `codaid schedules executor`                                      |
| `codaid os-gate status`                          | JSON with the state, failing, blocking, overridden and warning checks, overrides and the policy                  |
| `codaid os-gate grant <ids> --yes`               | Overrides the listed BLOCK checks for 30 days (without `--yes` it is a dry run that exits 2)                     |
| `codaid os-gate revoke <ids>`                    | Drops the listed overrides                                                                                       |
| `codaid os-gate audit`                           | The local grant and revoke log as JSON                                                                           |
| `codai-agent-headless run --allow-insecure-host` | Overrides the gate for this headless process (also `once` and `desktop-session`); a warning is printed to stderr |

The headless agent has no override file and does not fetch the organization policy: its flag is the only way to lift the block, for that process only.

## Which surfaces enforce the gate [#which-surfaces-enforce-the-gate]

| Surface                             | Agent tools                                                 |
| ----------------------------------- | ----------------------------------------------------------- |
| Desktop app (Windows, macOS, Linux) | Enforced                                                    |
| `codai-agent-headless`              | Enforced                                                    |
| `codaid`                            | Enforced                                                    |
| Android phone app                   | Enforced                                                    |
| mobile-agent (Termux)               | Enforced                                                    |
| Wear OS                             | Banner only — the watch runs no agent tools                 |
| VS Code extension                   | Status-bar warning only — the extension runs no local tools |

When a blocked tool is called, the agent receives a `BLOCKED: os_protection_gate` result, does not retry tools in that turn and tells you what is off and how to fix it.

## Privacy [#privacy]

Detection runs entirely on the device; no registry value, command output or device detail is ever sent anywhere. When you are signed in, the only network signal is the override audit event — whether you granted or revoked an override, the check ids, the app, its version and the time — sent to [`POST /v1/os-gate/events`](../api/gateway/os-gate.mdx).
