Skip to content

ops(ci): harden authorisation, migrate notify-slack action to TypeScript, and remove dead workflows#2878

Open
mw-w wants to merge 2 commits into
mainfrom
security/harden-ci
Open

ops(ci): harden authorisation, migrate notify-slack action to TypeScript, and remove dead workflows#2878
mw-w wants to merge 2 commits into
mainfrom
security/harden-ci

Conversation

@mw-w

@mw-w mw-w commented May 26, 2026

Copy link
Copy Markdown
Contributor

Summary

CI hardening as a prerequisite for the PAT migration. Replaces JSON-secret allowlists and repo-admin checks with GitHub Environment protection rules, adds missing actor gates to three prod CDN deploy workflows, migrates the Slack notify action to TypeScript, and removes dead workflows and scripts.

Detail and impact of the change

Added

  • GitHub Environment gates on all deployment and publishing and deploying workflows (npm-publish, cdn-deploy)
  • sticky-comment composite action for posting updateable PR comments
  • dependabot.yml for GitHub Actions version tracking
  • flows.md documenting the new CI access control model and migration rationale with Mermaid diagrams

Changed

  • notify-slack-publish-status action rewritten in TypeScript with Rollup (node24, @actions/core@3, pnpm workspace isolation, ESM output)
  • publish.yaml: environment gate replaces admin check + JSON allowlist steps; id-token: write now also serves npm OIDC trusted publishing; secrets scoped to steps that need them
  • build-game-bridge.yaml: environment gate replaces SDK team membership check
  • pr.yaml func-tests job: 8 test secrets and 14 config vars moved from job-level env to step-level on the Run functional tests step only
  • deploy-audience-cdn.yaml, deploy-pixel-cdn.yaml: AWS_REGION inlined into configure-aws-credentials step
  • publish.yaml: use upload and download action instead of cache between workflow jobs
  • build-game-bridge.yaml: attest all built artifact
  • publish.yaml: tag git pre-release now runs after release to NPM and is conditioned on the publish step succeeding and DRY_RUN being false.

Removed

  • publish-docs.yaml, publish-example-tutorials.yaml workflows
  • .github/scripts/ docs-related shell scripts
  • check-user-permission action (sole caller removed)
  • SDK_PUBLISH_MAJOR_VERSION_ACTORS and SDK_TEAM_MEMBERS secret references (both can now be removed)

Security

  • Actor gates now enforced by GitHub environments before the runner starts
  • Write-access collaborators can no longer trigger prod CDN/S3 deploys on dispatch without approval

Anything else worth calling out?

The GitHub Environments (npm-publish, cdn-deploy) must be created in GitHub Settings with the correct allowed actors before this branch is merged — the YAML references them and GitHub will block jobs until they exist. See flows.md for recommended membership and protection type per environment.

TS_IMMUTABLE_SDK_NPM_TOKEN, SDK_TEAM_MEMBERS, and SDK_PUBLISH_MAJOR_VERSION_ACTORS can be revoked from repo secrets after merge.

Follow up will remove TS_IMMUTABLE_SDK_GITHUB_TOKEN with short lived, least privilege scoped tokens

@nx-cloud

nx-cloud Bot commented May 26, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 54aeade

Command Status Duration Result
nx run-many -p @imtbl/sdk,@imtbl/checkout-widge... ✅ Succeeded 1s View ↗
nx affected -t build,lint,test ✅ Succeeded <1s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-06-09 08:17:54 UTC

@github-actions

github-actions Bot commented May 26, 2026

Copy link
Copy Markdown

✅ Audience Bundle Size — @imtbl/audience

Metric Size Delta vs main (cb1451d)
Gzipped 18710 bytes (18.27 KB) -307 bytes
Raw (minified) 54679 bytes -591 bytes

Budget: 24.00 KB gzipped (warn at 20.00 KB)

@socket-security

socket-security Bot commented May 26, 2026

Copy link
Copy Markdown

Warning

According to your organization's Security Policy, you must resolve all "Block" alerts before proceeding. It is recommended to resolve "Warn" alerts too. Learn more about Socket for GitHub.

Please tag @prodsec or slack us at #ask-security if you need assitance.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm @typescript-eslint/eslint-plugin is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: .github/actions/notify-slack-publish-status/pnpm-lock.yamlnpm/typescript-eslint@8.60.0npm/@typescript-eslint/eslint-plugin@8.60.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@typescript-eslint/eslint-plugin@8.60.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm @typescript-eslint/eslint-plugin is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: ?npm/typescript-eslint@8.61.0npm/@typescript-eslint/eslint-plugin@8.61.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/@typescript-eslint/eslint-plugin@8.61.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

… tagging, and migrate deploy workflows

Replace JSON-secret allowlists and repo-admin checks with GitHub Environment protection rules across all deployment and publishing workflows. Add missing actor gates to three prod CDN deploy workflows that were previously open to any write-access collaborator. Scope test secrets to the step that needs them and clean up dead workflows, scripts, and the check-user-permission action.

Authorization changes:
- publish.yaml: replace Check User Permission, Admin Permission Check, and Allowed Actors steps with `environment: npm-publish`; collapse npm-publish and npm-publish-major into a single environment — npm Trusted Publisher only accepts one environment per package so both publish paths must share one; drop SDK_PUBLISH_MAJOR_VERSION_ACTORS from job env
- build-game-bridge.yaml: replace Check SDK Team Membership with `environment: npm-publish`; replace TS_IMMUTABLE_SDK_GITHUB_TOKEN secret with the github-token OIDC action in create-unity-pr and create-unreal-pr (id-token: write, scoped installation token for checkout and gh pr create)
- deploy-audience-cdn.yaml, deploy-pixel-cdn.yaml, passport-sdk-sample-app-deployment.yaml: add missing environment gates; consolidate cdn-deploy-audience, cdn-deploy-pixel, and cdn-deploy-passport into a single cdn-deploy environment gated by ped-stream-blockchain-services-list
- delete .github/actions/check-user-permission — sole caller removed

github-token action (new):
- TypeScript action backed by the Immutable Token Service
- inputs: repositories (newline-separated owner/repo), permissions (key: value)
- output: scoped installation token; caller must set id-token: write

notify-slack-publish-status action:
- rewrite in TypeScript with Rollup bundler (ESM output, node24, @actions/core@3)
- add pnpm workspace isolation, eslint, prettier, tsconfig
- add explicit `webhook` input; move secrets to step-level

Secret scoping:
- pr.yaml func-tests: move 8 test secrets and 14 config vars from job env to step env on the Run functional tests step; NX_CLOUD_ACCESS_TOKEN stays at job level
- deploy-audience-cdn.yaml, deploy-pixel-cdn.yaml: inline AWS_REGION directly into configure-aws-credentials with: block, remove from job env

build-game-bridge.yaml artifact passing:
- replace actions/cache save+restore pattern with actions/upload-artifact (id: upload-artifact) in build-game-bridge and actions/download-artifact by artifact-id in create-unity-pr and create-unreal-pr; cache is not guaranteed for the workflow run lifetime whereas upload/download is
- attest build artifacts (unity/index.html, unreal/index.js) with actions/attest after build and before upload; build-game-bridge job gains id-token: write and attestations: write
- disable pnpm store cache (enable-cache: "false") in all three jobs to match publish workflow

Prerelease tagging fix (publish.yaml):
- move Tag Git Pre-Release step to after Release to NPM; previously tagging before publish left an orphaned git tag whenever the publish failed, causing subsequent runs to compute the same version and collide on the tag
- condition the tag step on steps.npm_release.conclusion == 'success' && env.DRY_RUN == 'false'; dry-run publishes do not write package.json versions to disk so jq reads the stale version and collides with the tag from the prior real publish

Disable pnpm cache in deploy workflows:
- deploy-audience-cdn.yaml, deploy-pixel-cdn.yaml, passport-sdk-sample-app-deployment.yaml, build-game-bridge.yaml: pass enable-cache: "false" to the setup action; production artifact builds use a clean install to avoid stale cached dependencies affecting deployed output

Dead code removed:
- publish-docs.yaml, publish-example-tutorials.yaml workflows
- .github/scripts/{check-docs-deployed,check-docs-version,process-tutorials,push-docs,update-docs-link}.sh
- notify-slack-publish-status/index.js (replaced by src/index.ts + dist/)

Other:
- pixel-bundle-size.yaml: fix contents:read accidentally placed inside env: block
- add dependabot.yml for GitHub Actions ecosystem
- add sticky-comment composite action
- add flows.md documenting environment gates, access control model, and Mermaid diagrams for all workflow trigger paths
@mw-w mw-w force-pushed the security/harden-ci branch from 85f6ac8 to dd70959 Compare June 3, 2026 01:20
@mw-w mw-w deployed to npm-publish June 3, 2026 01:22 — with GitHub Actions Active
@mw-w mw-w marked this pull request as ready for review June 3, 2026 01:29
@mw-w mw-w requested review from a team as code owners June 3, 2026 01:29
rytimx
rytimx previously approved these changes Jun 3, 2026
JCSanPedro
JCSanPedro previously approved these changes Jun 3, 2026
@mw-w mw-w enabled auto-merge June 5, 2026 04:36
nattb8
nattb8 previously approved these changes Jun 9, 2026
@mw-w mw-w disabled auto-merge June 9, 2026 06:18
@mw-w mw-w added this pull request to the merge queue Jun 9, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to no response for status checks Jun 9, 2026
@mw-w mw-w dismissed stale reviews from nattb8, JCSanPedro, and rytimx via 4469082 June 9, 2026 07:38
… main

publish.yaml: remove "Get GitHub Release Name and URL" step which had an inverted condition — contains(env.RELEASE_TYPE, 'release') matched 'prerelease' but not 'patch'/'minor'/'major', so Slack notifications for public releases always received an empty version. Remove the unconditional sleep 30 that preceded it. Add a single "Read SDK version" step after the version bump that outputs SDK_VERSION from sdk/package.json once, passed to downstream steps via env blocks, replacing five repeated jq subprocess calls.

pr.yaml: add push to main trigger to populate the playwright browser cache after each merge so merge queue runs hit it rather than cold-installing. Add timeout-minutes: 15 on the Setup playwright step to prevent indefinite hangs.
@mw-w mw-w force-pushed the security/harden-ci branch from 8b3a301 to 54aeade Compare June 9, 2026 08:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants