Trust Boundary for Repo Config in no-mistakes: Default Branch vs. Pushed SHA

The no-mistakes daemon treats the repository configuration (.no-mistakes.yaml) as a trusted artifact only when loaded from the default branch's pinned SHA, executing commands and selecting agents exclusively from that trusted version while allowing non-executable fields to merge from the pushed SHA.

The no-mistakes CI system implements a strict security model that prevents supply-chain remote-code-execution (RCE) attacks by isolating executable configuration to a trusted commit. Unlike typical CI systems that might execute configuration from the tip of a feature branch, the daemon resolves the default branch to an exact SHA and treats only that version as authoritative for dangerous operations. This design ensures that malicious shell commands cannot be injected through a simple pull request that modifies the repository configuration.

Why the Trust Boundary Exists

The trust boundary exists specifically to mitigate supply-chain RCE risks. When no-mistakes executes commands defined in commands.test, commands.lint, or commands.format, or selects an agent through the agent field, it runs arbitrary code that could compromise the build environment. If these fields were loaded from the pushed SHA—the tip of the branch being tested—a contributor could inject malicious shell commands into .no-mistakes.yaml and trigger immediate execution.

By restricting executable configuration to the default branch only, the repository maintainers control the trust boundary. Any changes to dangerous fields must be merged into the default branch before taking effect, preventing unilateral code execution by untrusted contributors.

How the Trust Boundary Is Enforced

The enforcement mechanism operates through a three-phase resolution process implemented in internal/daemon/manager.go. During run initialization, the daemon resolves the default branch reference, pins it to an immutable SHA, and loads the configuration from that specific commit.

Resolving the Trusted SHA

When startRun initiates a new run, it fetches the default branch reference and resolves it to an exact commit hash. This pinned SHA becomes the single source of truth for trusted configuration.

// In internal/daemon/manager.go (approx. line 337)
if sha, err := git.ResolveRef(ctx, wtDir, "origin/"+defaultBranch); err == nil {
    trustedSHA = sha // Pinned SHA for the entire run
}

If the fetch fails or the SHA cannot be resolved, trustedSHA remains empty. This failure state triggers a safe fallback that disables executable configuration entirely.

Loading the Trusted Configuration

The loadTrustedRepoConfig function reads .no-mistakes.yaml exclusively from the pinned SHA. This function returns nil when no trusted SHA exists, creating a hard boundary that prevents accidental execution of untrusted config.

// In internal/daemon/manager.go (approx. line 156)
func loadTrustedRepoConfig(ctx context.Context, wtDir, trustedSHA, runID string) *config.RepoConfig {
    if trustedSHA == "" {
        return nil // No trusted config → commands/agent disabled
    }
    content, err := git.ShowFile(ctx, wtDir, trustedSHA, ".no-mistakes.yaml")
    // ... YAML parsing ...
}

When trustedSHA is empty, the daemon cannot load executable configuration, effectively neutralizing any malicious commands present in the pushed SHA's version of the config file.

Merging with EffectiveRepoConfig

The EffectiveRepoConfig function in internal/config/config.go implements the final enforcement layer. This function merges global defaults, repository settings, and the trusted configuration while strictly separating executable from non-executable fields.

  • Executable fields (commands.*, agent): Sourced only from trustedRepoCfg
  • Non-executable fields (ignore_patterns, auto_fix, intent): May merge from the pushed SHA's configuration
// In internal/daemon/manager.go (approx. line 378)
trustedRepoCfg := loadTrustedRepoConfig(ctx, wtDir, trustedSHA, run.ID)

// Later in the run setup:
effectiveCfg := config.EffectiveRepoConfig(globalCfg, repoCfg, trustedRepoCfg)

If trustedRepoCfg is nil due to resolution failure, EffectiveRepoConfig deliberately clears the commands and agent fields from the pushed configuration, ensuring no executable code runs from untrusted sources.

Security Documentation and Rationale

This trust boundary is documented in the project's security architecture files. According to AGENTS.md, the design explicitly prevents supply-chain RCE by loading "code-executing selection fields (commands.{test,lint,format} and agent) from the trusted default branch, never from the pushed SHA." The CHANGELOG.md entry titled "security: load repo config from default branch, not pushed SHA (supply-chain RCE)" records the introduction of this mechanism, linking to the specific commits that implemented the loadTrustedRepoConfig and EffectiveRepoConfig isolation.

Summary

  • Trust boundary location: Between the default branch (trusted) and pushed SHA (untrusted) for executable configuration.
  • Key enforcement files: internal/daemon/manager.go (SHA resolution and loading) and internal/config/config.go (merging logic).
  • Critical functions: loadTrustedRepoConfig isolates trusted config; EffectiveRepoConfig filters dangerous fields.
  • Safe fallback: When the default branch SHA cannot be resolved, executable commands and agents are disabled entirely.
  • Flexibility preserved: Non-executable settings like ignore_patterns and auto_fix can still be tested from feature branches.

Frequently Asked Questions

What happens if the default branch fetch fails during a run?

If the daemon cannot fetch or resolve the default branch to a SHA, trustedSHA remains empty. The loadTrustedRepoConfig function returns nil, causing EffectiveRepoConfig to strip all commands and agent fields from the configuration. The run proceeds with non-executable settings only, preventing any code execution from the untrusted pushed SHA.

Can I test new commands in a pull request before merging to the default branch?

No. Because commands are sourced exclusively from the default branch SHA, you cannot test new command definitions in a feature branch. You must first merge the .no-mistakes.yaml changes to the default branch, after which subsequent runs will execute the new commands. This is the fundamental security trade-off of the trust boundary.

Are all configuration fields restricted to the default branch?

No. Only executable fields—specifically commands.test, commands.lint, commands.format, and agent—are restricted to the trusted default branch configuration. Non-executable fields such as ignore_patterns, auto_fix, and intent can be modified in feature branches and will be merged from the pushed SHA, allowing developers to test linting rules and ignore patterns without merging to the default branch first.

Where is the trust boundary logic implemented in the source code?

The primary implementation resides in internal/daemon/manager.go within the startRun function and the loadTrustedRepoConfig helper. The merging logic that enforces which fields come from which source is implemented in internal/config/config.go within the EffectiveRepoConfig function. Documentation explaining the security rationale appears in AGENTS.md and CHANGELOG.md at the repository root.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →