Skip to content

Add setting_sources input and default base-action to user-only#1115

Open
km-anthropic wants to merge 1 commit intomainfrom
setting-sources-default
Open

Add setting_sources input and default base-action to user-only#1115
km-anthropic wants to merge 1 commit intomainfrom
setting-sources-default

Conversation

@km-anthropic
Copy link
Copy Markdown
Collaborator

Summary

Project and local settings (.claude/settings.json, .claude/settings.local.json) additively merge their permissions.allow with whatever allowed_tools a workflow specifies. A workflow author writing a restrictive allowlist reasonably expects it to be the complete allow-set — but repo settings can silently expand it.

Changes

  • New setting_sources input on both claude-code-action and claude-code-base-action. Previously only reachable via --setting-sources in claude_args.
  • base-action default changed from ["user", "project", "local"]["user"]. Workflows that want project/local settings must now opt in explicitly.
  • Main action default stays permissive (user,project,local) because .claude/ is restored from the PR base branch before execution (Restore .claude/ and .mcp.json from PR base branch before CLI runs #1066), so project settings are maintainer-trusted in that context.
  • Precedence: setting_sources input > --setting-sources in claude_args > default.

Breaking change (base-action only)

Workflows using claude-code-base-action that rely on .claude/settings.json being loaded automatically need to add:

setting_sources: "user,project,local"

The main claude-code-action is unaffected — it passes the permissive default explicitly.

Test plan

  • bun test — 657 pass
  • bun run typecheck — clean
  • bun run format:check — clean
  • New tests cover: default, direct input, claude_args fallback, precedence, whitespace trimming
  • Verified empty-string default from action.yml correctly falls through to ["user"]
  • Verified existing --setting-sources users via claude_args are unaffected

Project and local settings additively merge their permissions with whatever
allowed_tools a workflow specifies. A workflow author writing a restrictive
allowlist reasonably expects it to be the complete allow-set, but
.claude/settings.json can silently expand it.

Changes:
- Add setting_sources as a first-class input to both actions (previously
  only reachable via --setting-sources in claude_args)
- base-action now defaults to settingSources: ['user'] — workflows that want
  project/local settings must opt in explicitly
- Main action defaults to 'user,project,local' since .claude/ is restored
  from the PR base branch before execution, so project settings are
  maintainer-trusted in that context
- Precedence: setting_sources input > --setting-sources in claude_args > default

Breaking change for base-action: workflows relying on .claude/settings.json
being loaded automatically need to add setting_sources: 'user,project,local'.
Comment on lines +65 to +68
setting_sources:
description: "Comma-separated list of setting sources to load (user, project, local). Defaults to 'user,project,local' — project settings are safe here because .claude/ is restored from the PR base branch before execution. Set to 'user' to ignore in-repo settings entirely."
required: false
default: "user,project,local"
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.

🔴 The main action sets default: "user,project,local" for setting_sources, which GitHub Actions always resolves even when the user omits the input. This makes options.settingSources always truthy in parseSdkOptions, so --setting-sources passed via claude_args is silently ignored for main action users. Any workflow previously using claude_args: "--setting-sources user" to restrict sources will now silently get user,project,local instead.

Extended reasoning...

What the bug is

The new setting_sources input in action.yml (line 65-68) has default: "user,project,local". In GitHub Actions, when an input has a non-empty default and the user does not explicitly provide that input, GitHub resolves it to the default value. This means INPUT_SETTING_SOURCES is always set to "user,project,local" for every main action user who does not explicitly set setting_sources.

The code path

In parseSdkOptions (line 257-262), the precedence chain is:

  1. options.settingSources — from INPUT_SETTING_SOURCES (always "user,project,local" for main action)
  2. extraArgs["setting-sources"] — parsed from claude_args
  3. Default ["user"]

Since options.settingSources is always truthy for the main action, the extraArgs["setting-sources"] branch is dead code. The fallback from claude_args is unreachable.

Step-by-step proof

Consider a workflow that previously worked:

uses: anthropics/claude-code-action@v1
with:
  claude_args: "--setting-sources user"
  1. User does not set setting_sources input explicitly.
  2. GitHub Actions resolves inputs.setting_sources to "user,project,local" (the default).
  3. action.yml passes INPUT_SETTING_SOURCES: ${{ inputs.setting_sources }}"user,project,local".
  4. run.ts passes settingSources: process.env.INPUT_SETTING_SOURCES"user,project,local".
  5. In parseSdkOptions, options.settingSources is "user,project,local" (truthy), so the first branch is taken.
  6. The --setting-sources user from claude_args is parsed into extraArgs["setting-sources"] but never checked.
  7. Result: settingSources = ["user", "project", "local"] instead of the intended ["user"].

Why existing code doesn't prevent it

The precedence logic in parseSdkOptions is correct in isolation — it properly prioritizes direct input over claude_args. The problem is that GitHub Actions conflates "user provided a value" with "default was applied". The base-action avoids this by using default: "", which is falsy. The main action uses a non-empty default, making it indistinguishable from an explicit user input.

Impact

Any main action user who previously used claude_args: "--setting-sources user" to restrict setting sources (e.g., to avoid in-repo .claude/settings.json expanding their allowlist) will have that restriction silently removed. The PR description explicitly states "Verified existing --setting-sources users via claude_args are unaffected," which is only true for the base-action.

How to fix

Either make the main action's default empty (like the base-action) and apply the permissive default ["user", "project", "local"] in run.ts before calling runClaude (only when INPUT_SETTING_SOURCES is empty/unset), or document this as a breaking change for users who relied on claude_args to override setting sources.

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.

1 participant