# Security Model

What Kasetto can write to disk, how it handles credentials, and whether syncing skills from a URL is safe.

**When you need this:** You want to know what Kasetto can modify on disk, how it handles credentials, and whether syncing from URLs is safe.

**What you'll learn:**

- What Kasetto touches (and what it avoids)
- How tokens are provided (env vars only)
- How remote config fetching is authenticated

## What Kasetto Changes on Disk

During `kst sync`, Kasetto may:

- **Install/update skills** by copying skill directories into the chosen destination path
- **Remove skills** that are no longer in your config (for the selected scope)
- **Merge MCPs** into agent-native settings files (additive merge; existing servers are preserved, except a kasetto-managed server replaced by `--update`)
- **Write the lock file** for the selected scope

Kasetto is designed around a "tracked-only" principle:

- **Skills**: fully managed at their install paths for entries tracked in the lock
- **MCPs**: only server entries that Kasetto installed (tracked in the lock) are removed during cleanup

See [How Sync Works](/docs/how-sync-works) for details.

## MCP Server Installation

New MCPs are merged into agent settings files automatically on `kst sync`, with no confirmation prompt. Use `--dry-run` to preview what would be written before committing.

## Self-Update Integrity

`kst self update` verifies the downloaded binary against `checksums.txt` from the same GitHub release using SHA256, the same verification the shell installer (`install.sh`) performs. If the checksum doesn't match, the update is aborted and the existing binary is left untouched.

## What Kasetto Does Not Do

- It does not run skill code.
- It does not overwrite MCP server entries it didn't install (only a kasetto-managed server is replaced, and only under `--update`).
- It does not write a credentials file. It can optionally *read* one for [secret injection](/docs/secrets).

## Secret Injection

MCP packs can carry `${kst_...}` placeholders that Kasetto resolves at sync time from environment variables, `$XDG_CONFIG_HOME/kasetto/credentials.yaml`, or an external manager via the tagged form: `op` (1Password), `vault` (HashiCorp Vault), `kp` (KeePassXC), `aws` (Secrets Manager), `gcp` (Secret Manager), `az` (Key Vault), `pass` (pass/gopass), `keychain` (macOS). Each shells out to the provider's own CLI and inherits your existing session, so kasetto stores no tokens. The resolved value is written **only** to the agent's settings file, never to `kasetto.lock` (which hashes the placeholder source), the source cache, or the stage directory. A missing required secret fails the entry and exits non-zero by default. See [Secret Injection](/docs/secrets) for the full model.

## Credentials and Tokens

Kasetto reads tokens from environment variables (per host).

Examples:

- GitHub / GitHub Enterprise: `GITHUB_TOKEN` or `GH_TOKEN`
- GitLab / self-hosted GitLab: `GITLAB_TOKEN` or `CI_JOB_TOKEN`
- Bitbucket Cloud: `BITBUCKET_EMAIL` + `BITBUCKET_TOKEN` (or app password variants)

See [Authentication](/docs/authentication) for the full list and host detection rules.

## Remote Config Fetching (`--config https://...`)

When you pass a URL to `--config`, Kasetto:

- Fetches the YAML over HTTPS
- Applies the same host-based token selection rules as skill/MCP sources

This means a private config hosted on a git provider can be accessed by setting the appropriate token env var for that host.

## Practical Recommendations

- Prefer pinning remote sources to immutable refs (`ref: v1.2.3` or a commit SHA) for stable rollouts.
- In CI, use `--dry-run` (and ideally `--json`) to validate without writing changes.
