Skip to content

ci: harden preview/deploy workflows (script injection, curl|sh, secret scoping) - #1195

Draft
ital0 wants to merge 6 commits into
mainfrom
cursor/sec-workflow-hardening
Draft

ci: harden preview/deploy workflows (script injection, curl|sh, secret scoping)#1195
ital0 wants to merge 6 commits into
mainfrom
cursor/sec-workflow-hardening

Conversation

@ital0

@ital0 ital0 commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Fixes 10 open code-scanning alerts on the preview/deploy CI surface: #90, #60, #77, #40, #86, #81, #76, #78, #79, #80, plus follow-up alert #102 raised on this PR.

Changes

Script injection (alerts 60, 40)${{ inputs.stack_name }} in stack-deploy.yml's destroy job and ${{ github.base_ref }} in pr-metrics.yml were interpolated directly into run: scripts. Both now go through quoted env: variables, matching the INPUT_* pattern already used everywhere else in these files.

curl | sh removal (alerts 90, 77) — the destroy path of stack-deploy.yml and preview-cleanup.yml installed Pulumi via curl -fsSL https://get.pulumi.com | sh. The Pulumi CLI is preinstalled on ubuntu-latest runners — the deploy job of stack-deploy.yml already relies on that (it runs pulumi stack select with no install step). The installs were redundant and are removed.

PULUMI_ACCESS_TOKEN scoping (alerts 86, 81, 76) — moved from workflow-level env: to step-level env: on exactly the steps that run Pulumi, in stack-deploy.yml, previews-shared-deploy.yml and preview-cleanup.yml.

secrets: inherit → explicit maps (alerts 78, 79, 80)stack-deploy.yml now declares 11 secrets in on.workflow_call.secrets (all required: false, preserving the current "missing secret = empty string" semantics). Callers pass exactly what each path needs: preview-deploy passes 10; preview-destroy and preview-cleanup pass only PULUMI_ACCESS_TOKEN + AWS_DEPLOY_ROLE_ARN; EXA_API_KEY remains environment-resolved.

Static environment-secret access (alert 102)EXA_API_KEY is declared in the reusable workflow contract and referenced as secrets.EXA_API_KEY, avoiding a dynamic lookup that could make every available job secret visible to the runner.

Note for reviewers: EXA_API_KEY

EXA_API_KEY is scoped to the preview environment and resolves via the deploy job's environment: preview. Callers intentionally do not pass it. The optional workflow_call.secrets declaration makes the static dotted reference valid to actionlint; GitHub uses the environment secret in preference to a same-named secret passed by a caller.

Validation

  • actionlint on all six files: zero new findings vs main (only pre-existing shellcheck info-level warnings remain; one warning was removed along with the deleted installer step).
  • bun run check passes on the updated branch.
  • The preview deploy path is self-validating: this PR's own preview deploy exercises the changed stack-deploy.yml deploy job, and closing the PR exercises the destroy path.

ital0 added 3 commits August 5, 2026 16:39
- prevent script injection by routing workflow inputs through environment variables
- remove curl-piped Pulumi installs because hosted runners ship the CLI
- scope PULUMI_ACCESS_TOKEN to only the steps that use it
- replace inherited secrets with explicit maps while keeping EXA_API_KEY environment-resolved
- make each optional secret's purpose clear to workflow callers
- preserve empty-secret behavior while excluding environment-scoped EXA_API_KEY
- keep EXA_API_KEY environment-scoped instead of declaring it for callers
- avoid a false actionlint error from its exhaustive workflow secret model
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

Semgrep Security Scan

No security issues found.

Comment thread .github/workflows/stack-deploy.yml Fixed
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

Preview environment deployed 🚀

Service URL
Marketing / blog / docs https://thunderbolt-pr-1195.preview.thunderbolt.io
App https://app-pr-1195.preview.thunderbolt.io
API https://api-pr-1195.preview.thunderbolt.io
Keycloak https://auth-pr-1195.preview.thunderbolt.io
PowerSync https://powersync-pr-1195.preview.thunderbolt.io

Stack: preview-pr-1195 · Commit: 6a2d68ce826349ab43e9308e1c689570b084d810

Auto-destroys on PR close/merge. Login via the bundled Keycloak realm — demo@thunderbolt.io / demo by default.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

PR Metrics

Metric Value
Lines changed (prod code) +77 / -26
JS bundle size (gzipped) 🟢 589.2 KB → 591.3 KB (+2.1 KB, +0.4%)
Test coverage 🟢 81.28% → 81.41% (+0.1%)
Performance (preview) Preview not ready — Render deploy may have timed out
Accessibility
Best Practices
SEO

Updated Fri, 07 Aug 2026 00:39:17 GMT · run #2622

Declare EXA_API_KEY in the reusable workflow contract so the environment secret uses a static lookup.
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