Add setting_sources input and default base-action to user-only#1115
Add setting_sources input and default base-action to user-only#1115km-anthropic wants to merge 1 commit intomainfrom
Conversation
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'.
| 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" |
There was a problem hiding this comment.
🔴 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:
options.settingSources— fromINPUT_SETTING_SOURCES(always"user,project,local"for main action)extraArgs["setting-sources"]— parsed fromclaude_args- 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"- User does not set
setting_sourcesinput explicitly. - GitHub Actions resolves
inputs.setting_sourcesto"user,project,local"(the default). action.ymlpassesINPUT_SETTING_SOURCES: ${{ inputs.setting_sources }}→"user,project,local".run.tspassessettingSources: process.env.INPUT_SETTING_SOURCES→"user,project,local".- In
parseSdkOptions,options.settingSourcesis"user,project,local"(truthy), so the first branch is taken. - The
--setting-sources userfromclaude_argsis parsed intoextraArgs["setting-sources"]but never checked. - 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.
Summary
Project and local settings (
.claude/settings.json,.claude/settings.local.json) additively merge theirpermissions.allowwith whateverallowed_toolsa 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
setting_sourcesinput on bothclaude-code-actionandclaude-code-base-action. Previously only reachable via--setting-sourcesinclaude_args.["user", "project", "local"]→["user"]. Workflows that want project/local settings must now opt in explicitly.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.setting_sourcesinput >--setting-sourcesinclaude_args> default.Breaking change (base-action only)
Workflows using
claude-code-base-actionthat rely on.claude/settings.jsonbeing loaded automatically need to add:The main
claude-code-actionis unaffected — it passes the permissive default explicitly.Test plan
bun test— 657 passbun run typecheck— cleanbun run format:check— cleanclaude_argsfallback, precedence, whitespace trimmingaction.ymlcorrectly falls through to["user"]--setting-sourcesusers viaclaude_argsare unaffected