claude-sonnet-4-5 predates auto mode, so Claude Code fell back to its
default permission mode in the dedupe job. Move it and claude.yml to
claude-sonnet-4-6. The action sets --permission-mode acceptEdits for
@claude mentions and appends the workflow's claude_args after it, so the
--permission-mode auto in claude.yml wins. Drop claude.yml from
EXEMPT_FROM_AUTO_MODE.
The check now also fails when a step in auto mode names a model older than
claude-opus-4-6.
A settings file that an earlier step writes at run time can't be read by
the step-level check, so also fail when the job's definition mentions
defaultMode at all.
The security check looked for defaultMode only in an inline 'settings'
input. Also read the file a 'settings' input or a --settings flag in
claude_args names, when it is inside the repository, and fail if it sets
a permission mode.
- .github/egress-firewall.yaml: the hosts that jobs on the
egress-firewall runner may reach, in enforce mode, each with what
uses it.
- .github/workflows/workflow-hardening.yml and
.github/scripts/check_workflow_hardening.py: a check that fails when a
job that calls Claude is not on the egress-firewall runner, does not
pass --permission-mode auto, or when the allow list is missing, empty, not in
enforce mode or names a host with '*'.
claude.yml is listed as exempt from the permission mode rule, with
the reason.
- CLAUDE.md: a "Security hardening for GitHub Actions" section so that
new and edited workflows keep these protections.