Skip to content

feat(workflows)!: add required environment input to enforce environment-scoped secrets#60

Draft
kryota-dev wants to merge 6 commits intomainfrom
claude/secrets-outside-env-remediation
Draft

feat(workflows)!: add required environment input to enforce environment-scoped secrets#60
kryota-dev wants to merge 6 commits intomainfrom
claude/secrets-outside-env-remediation

Conversation

@kryota-dev
Copy link
Copy Markdown
Owner

Summary

  • Add required environment input to deploy-web-hosting.yml, tagpr-release.yml, and undeploy-web-hosting.yml to enforce GitHub Environment-scoped secret access
  • Apply environment: ${{ inputs.environment }} to all jobs that reference secrets.*
  • Update internal callers (my-release.yml, my-update-release-pr.yml) to pass environment: release
  • Update all documentation (EN/JA) with new input, examples, and prerequisites

Motivation

zizmor v1.23.0 introduced the secrets-outside-env audit, which flags jobs accessing secrets without a dedicated GitHub Environment. GitHub Environments provide protection rules (reviewer approval, wait timers, branch restrictions) that add a security layer for secret access.

Rather than suppressing the audit, this PR addresses the root cause by requiring all secret-accessing jobs to be scoped to a GitHub Environment.

Breaking Changes

All callers of the affected Reusable Workflows must:

  1. Create a GitHub Environment in their repository settings (e.g., production, staging, release)
  2. Move secrets from repository level to environment level
  3. Add environment input to with: block when calling the workflow
# Before
jobs:
  deploy:
    uses: kryota-dev/actions/.github/workflows/deploy-web-hosting.yml@v0
    with:
      deploy-type: 'ftp'
      # ...
    secrets:
      server-host: ${{ secrets.SERVER_HOST }}

# After
jobs:
  deploy:
    uses: kryota-dev/actions/.github/workflows/deploy-web-hosting.yml@v0
    with:
      environment: 'production'  # NEW: required
      deploy-type: 'ftp'
      # ...
    secrets:
      server-host: ${{ secrets.SERVER_HOST }}

Test plan

  • actionlint passes locally
  • CI lint checks pass (zizmor secrets-outside-env audit resolved after merging with PR chore(deps): update dependency zizmorcore/zizmor to v1.24.1 #57)
  • Create release GitHub Environment in this repository and configure APP_TOKEN secret at environment level
  • Verify my-release.yml and my-update-release-pr.yml work correctly with the new environment

Related


Important

This is a breaking change. All downstream callers must update their workflows.

Generated with Claude Code

kryota-dev and others added 4 commits March 13, 2026 09:17
…ment-scoped secrets

Add `environment` input (required, string) to all Reusable Workflows
that access `secrets.*`, and apply `environment: ${{ inputs.environment }}`
to every secret-using job.

This addresses the zizmor `secrets-outside-env` audit (v1.23.0) by
ensuring secrets are only accessible to jobs with GitHub Environment
protection rules.

Affected workflows:
- deploy-web-hosting.yml (deploy job)
- tagpr-release.yml (tagpr + bump_major_tag jobs)
- undeploy-web-hosting.yml (delete job)

BREAKING CHANGE: Callers must create a GitHub Environment and pass the
`environment` input. Omitting it will cause a workflow call error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update internal callers to pass `environment: release` to
tagpr-release.yml, matching the new required input.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add `environment` to Usage, Inputs table, Examples, and Prerequisites
sections in all affected workflow docs (both English and Japanese).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a breaking change to the repo’s reusable GitHub Actions workflows to require a GitHub Environment name, aiming to ensure secret access is scoped to GitHub Environments (addressing zizmor’s secrets-outside-env audit).

Changes:

  • Add a required environment input to multiple reusable workflows and apply environment: ${{ inputs.environment }} to secret-using jobs.
  • Update internal wrapper workflows to pass environment: release into the reusable release workflow.
  • Update EN/JA workflow documentation and the changelog to describe the new required input and prerequisites.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
CHANGELOG.md Documents the breaking change and caller migration requirement.
.github/workflows/deploy-web-hosting.yml Adds required environment input and sets job environment for secret access.
.github/workflows/undeploy-web-hosting.yml Adds required environment input and sets job environment for secret access.
.github/workflows/tagpr-release.yml Adds required environment input and sets job environment(s) for secret access.
.github/workflows/my-release.yml Passes environment: release into the reusable workflow.
.github/workflows/my-update-release-pr.yml Passes environment: release into the reusable workflow.
.github/workflows/docs/deploy-web-hosting.md Updates docs/examples with the new environment input.
.github/workflows/docs/deploy-web-hosting.ja.md Same as above (JA).
.github/workflows/docs/undeploy-web-hosting.md Updates docs/examples with the new environment input.
.github/workflows/docs/undeploy-web-hosting.ja.md Same as above (JA).
.github/workflows/docs/tagpr-release.md Updates docs/examples with the new environment input and prerequisites.
.github/workflows/docs/tagpr-release.ja.md Same as above (JA).

Comment thread .github/workflows/docs/undeploy-web-hosting.md
Comment thread .github/workflows/docs/tagpr-release.ja.md Outdated
Comment thread .github/workflows/docs/tagpr-release.md
Comment thread CHANGELOG.md
Comment thread .github/workflows/docs/deploy-web-hosting.md
Comment thread .github/workflows/docs/tagpr-release.ja.md
Comment thread .github/workflows/docs/tagpr-release.md Outdated
Comment thread .github/workflows/my-release.yml Outdated
Comment thread .github/workflows/my-update-release-pr.yml Outdated
Comment thread .github/workflows/docs/deploy-web-hosting.ja.md
kryota-dev and others added 2 commits March 13, 2026 10:24
…t-direct secret access

- Remove workflow_call.secrets sections from all Reusable Workflows
- Change secret references from kebab-case to UPPER_SNAKE_CASE
- Remove secrets: blocks from callers (secrets accessed via environment)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace Secrets section with Environment Secrets section
- Remove secrets: blocks from Usage/Examples
- Update secret names to UPPER_SNAKE_CASE in Behavior/Prerequisites
- Add breaking change entry to CHANGELOG

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@kryota-dev kryota-dev force-pushed the claude/secrets-outside-env-remediation branch from af0ff2f to a54dc3c Compare March 13, 2026 01:24
@kryota-dev kryota-dev requested a review from Copilot March 13, 2026 01:24
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an environment input to several reusable workflows to scope secret access via GitHub Environments, and updates internal callers plus docs to match the new contract.

Changes:

  • Add required environment input and set environment: ${{ inputs.environment }} on secret-consuming jobs.
  • Switch secret references to environment-style UPPER_SNAKE_CASE names (e.g., APP_TOKEN, SERVER_HOST).
  • Update internal wrapper workflows and EN/JA docs/examples to pass the new environment input and document environment secrets.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
CHANGELOG.md Documents the breaking change and new environment-scoped secret approach.
.github/workflows/deploy-web-hosting.yml Adds environment input and scopes the deploy job; updates secret names.
.github/workflows/undeploy-web-hosting.yml Adds environment input and scopes the undeploy job; updates secret names.
.github/workflows/tagpr-release.yml Adds environment input and scopes jobs; updates token secret name to APP_TOKEN.
.github/workflows/my-release.yml Updates internal caller to pass environment: release.
.github/workflows/my-update-release-pr.yml Updates internal caller to pass environment: release.
.github/workflows/docs/deploy-web-hosting.md Updates examples and documents environment secrets + prerequisite environment.
.github/workflows/docs/deploy-web-hosting.ja.md Japanese doc updates for the new environment input and env secrets.
.github/workflows/docs/undeploy-web-hosting.md Updates examples and documents environment secrets + prerequisite environment.
.github/workflows/docs/undeploy-web-hosting.ja.md Japanese doc updates for the new environment input and env secrets.
.github/workflows/docs/tagpr-release.md Updates examples and documents environment + APP_TOKEN as an environment secret.
.github/workflows/docs/tagpr-release.ja.md Japanese doc updates for the new environment input and env secrets.

@@ -15,5 +15,5 @@ jobs:
contents: write
pull-requests: write
uses: ./.github/workflows/tagpr-release.yml
secrets:
app-token: ${{ secrets.APP_TOKEN }}
with:
environment: release
Comment on lines 70 to +74
id: check-slack
env:
SLACK_CHANNEL_ID: ${{ secrets.slack-channel-id }}
SLACK_BOT_OAUTH_TOKEN: ${{ secrets.slack-bot-oauth-token }}
SLACK_WEBHOOK_URL: ${{ secrets.slack-webhook-url }}
SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }}
SLACK_BOT_OAUTH_TOKEN: ${{ secrets.SLACK_BOT_OAUTH_TOKEN }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Comment on lines 60 to +64
uses: kryota-dev/actions/.github/actions/undeploy-web-hosting-ftp@568519d2e5e2722d8d2340f594f6af3e1564852e # v0.0.7
with:
ftp-server: ${{ secrets.server-host }}
ftp-username: ${{ secrets.server-user }}
ftp-password: ${{ secrets.server-password }}
target-path: ${{ secrets.server-path }}${{ steps.compute-path.outputs.deploy-path }}
ftp-server: ${{ secrets.SERVER_HOST }}
ftp-username: ${{ secrets.SERVER_USER }}
ftp-password: ${{ secrets.SERVER_PASSWORD }}
Comment on lines 33 to 36
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.app-token }}
token: ${{ secrets.APP_TOKEN }}
persist-credentials: false
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.

2 participants