# How AllowRepoCommands Works in no-mistakes: Securing Repo Config Execution

> Learn how AllowRepoCommands in no-mistakes secures repo configuration execution by default preventing supply-chain attacks. Ensure trusted code execution.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: deep-dive
- Published: 2026-06-27

---

**The `AllowRepoCommands` field in no-mistakes defaults to `false` to prevent supply-chain attacks, ensuring code-executing configurations like shell commands and agent selections are only read from the trusted default branch, never from a contributor's potentially malicious pushed branch.**

The `no-mistakes` repository implements a default-deny security model for repository configuration. By separating code-executing fields from safe configuration options, the system prevents malicious contributors from injecting arbitrary shell commands through pull requests.

## The Security Problem: Code-Executing vs. Safe Config Fields

`no-mistakes` categorizes repository configuration into two distinct risk classes. **Code-executing fields** include `commands.{lint,test,format}` and `agent`, which specify shell commands the daemon runs on the host and the AI agent spawned with maintainer credentials. **Safe fields** include ignore patterns, auto-fix limits, intent extraction settings, and test configurations—data that cannot execute arbitrary code.

If the daemon honored code-executing fields from a contributor's pushed branch, a malicious actor could inject `rm -rf /` into the test command or switch the agent to an untrusted executable. The `AllowRepoCommands` field exists specifically to gate whether these high-risk configurations can be sourced from untrusted branches.

## How AllowRepoCommands Is Defined

The configuration structure lives in [`internal/config/config.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go). The `RepoConfig` struct defines the field with explicit documentation about its security constraints:

```go
type RepoConfig struct {
    // … other fields …
    // AllowRepoCommands opts in to honoring the code‑executing selection fields
    // (commands.{test,lint,format} and agent) from a contributor's pushed branch
    // instead of the trusted default‑branch copy. It is read ONLY from the
    // trusted default‑branch copy of .no‑mistakes.yaml (never the pushed SHA),
    // so a contributor cannot self‑enable it. Default false.
    AllowRepoCommands bool `yaml:"allow_repo_commands"`
    // … other fields …
}

```

*(source: [config.go line 70‑80](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go#L70-L80))*

Crucially, the daemon only reads this flag from the **trusted default-branch copy**. A contributor cannot enable this feature on their feature branch because the system ignores the flag when parsing the pushed configuration.

## The EffectiveRepoConfig Logic

When a run starts, the daemon loads two copies of the repository configuration: the **trusted** version from the default-branch tip, and the **pushed** version from the contributor's checkout. The `EffectiveRepoConfig` function in [`internal/config/config.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go) implements the merging logic:

```go
func EffectiveRepoConfig(pushed, trusted *RepoConfig, allowRepoCommands bool) *RepoConfig {
    if pushed == nil { pushed = &RepoConfig{} }
    effective := *pushed
    if allowRepoCommands {
        return &effective                // honour everything from the pushed copy
    }
    // otherwise, pull only the safe fields from the pushed copy
    if trusted != nil {
        effective.Commands = trusted.Commands
        effective.Agent    = trusted.Agent
    } else {
        effective.Commands = Commands{}
        effective.Agent    = ""
    }
    return &effective
}

```

*(source: [config.go line 86‑106](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go#L86-L106))*

If `allowRepoCommands` is `false` (the default), the function **overwrites** the pushed branch's `Commands` and `Agent` fields with values from the trusted copy, or clears them entirely if no trusted copy exists. This ensures executable commands never originate from untrusted input unless the maintainer explicitly opts in via the default branch configuration.

## Daemon Implementation

The daemon's manager retrieves the flag from the trusted configuration before calling the effective config logic. As implemented in [`internal/daemon/manager.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/manager.go):

```go
allowRepoCommands := trustedRepoCfg != nil && trustedRepoCfg.AllowRepoCommands

```

*(source: [daemon/manager.go line 379](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/manager.go#L379))*

This boolean then drives the security decision. The daemon uses `LoadRepoFromBytes` to parse the trusted default-branch YAML and `LoadRepo` to parse the pushed working tree configuration. Only the trusted copy determines whether contributor-defined commands are permissible.

## Configuration Examples

### Secure Default Configuration

```yaml

# .no-mistakes.yaml on the default branch

agent: claude
commands:
  lint: "golangci-lint run ./..."
  test: "go test ./..."

# allow_repo_commands omitted → defaults to false

```

With this configuration, any contributor attempting to modify commands in a feature branch will see their changes ignored. The daemon executes only the trusted default-branch commands.

### Blocked Malicious Attempt

```yaml

# .no-mistakes.yaml on a feature branch

commands:
  lint: "rm -rf $HOME/* && echo 'pwned'"
allow_repo_commands: true   # <-- ignored because the trusted copy doesn't have it

```

Even though the contributor sets `allow_repo_commands: true`, the daemon ignores this value because it only reads the flag from the trusted default branch. The malicious `lint` command is discarded and replaced with the trusted version.

### Maintainer Opt-In Scenario

```yaml

# .no-mistakes.yaml on the default branch

allow_repo_commands: true
agent: claude
commands:
  lint: "golangci-lint run ./..."

```

When the maintainer commits this to the default branch, contributors may now customize `commands` and `agent` in their feature branches. The daemon honors these values because the trusted copy explicitly enables the functionality.

## Summary

- **`AllowRepoCommands` defaults to `false`** to enforce a secure-by-default posture.
- **The flag is only read from the trusted default-branch copy**, preventing contributors from self-enabling command execution.
- **Code-executing fields** (`commands` and `agent`) are overwritten with trusted values when the flag is `false`.
- **Safe fields** (ignore patterns, limits, intent settings) are always honored from the pushed branch regardless of the flag.
- The logic is implemented in `EffectiveRepoConfig` within [`internal/config/config.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config.go) and invoked by the daemon manager in [`internal/daemon/manager.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/daemon/manager.go).

## Frequently Asked Questions

### What happens if a contributor sets `allow_repo_commands: true` in their PR?

The daemon ignores the flag. Because `AllowRepoCommands` is only read from the trusted default-branch copy of [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml), a contributor cannot enable command execution from their feature branch. The system uses the trusted copy's value (default `false`) and sanitizes the pushed configuration accordingly.

### Which configuration fields are considered "code-executing" in no-mistakes?

The `commands` struct (containing `lint`, `test`, and `format` shell commands) and the `agent` field (specifying which AI agent to spawn) are treated as code-executing. These fields directly influence process execution on the host system, making them high-risk targets for injection attacks.

### How can a maintainer safely enable contributor-defined commands?

To permit contributors to customize commands, the maintainer must add `allow_repo_commands: true` to the [`.no-mistakes.yaml`](https://github.com/kunchenguid/no-mistakes/blob/main/.no-mistakes.yaml) file on the default branch and commit this change. Once present in the trusted configuration, the daemon will honor `commands` and `agent` values from pushed branches, allowing per-branch customization while maintaining auditability through the default branch history.

### Where are the security guarantees tested?

The end-to-end security guarantees are verified in [`internal/e2e/repo_config_security_test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/e2e/repo_config_security_test.go), which tests that malicious configurations from pushed branches cannot execute. Unit tests for the loading and defaulting behavior reside in [`internal/config/config_repo_trust_test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/config/config_repo_trust_test.go). These files ensure the `AllowRepoCommands` logic prevents supply-chain attacks even as the codebase evolves.