ci: harden preview/deploy workflows (script injection, curl|sh, secret scoping) - #1195
Conversation
- 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
Semgrep Security ScanNo security issues found. |
|
Preview environment destroyed 🧹 Stack |
PR Metrics
Updated Mon, 10 Aug 2026 19:44:11 GMT · run #2647 |
6a2d68c to
a025d2c
Compare
|
@thunderbolt-automation-agent review this PR |
|
Most of the hardening verifies. The script-injection fixes in
This is comment-only feedback. It does not approve or merge this pull request. |
6099ae0 to
936487e
Compare
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 }}instack-deploy.yml's destroy job and${{ github.base_ref }}inpr-metrics.ymlwere interpolated directly intorun:scripts. Both now go through quotedenv:variables, matching theINPUT_*pattern already used everywhere else in these files.curl | shremoval (alerts 90, 77) — the destroy path ofstack-deploy.ymlandpreview-cleanup.ymlinstalled Pulumi viacurl -fsSL https://get.pulumi.com | sh. The Pulumi CLI is preinstalled onubuntu-latestrunners — the deploy job ofstack-deploy.ymlalready relies on that (it runspulumi stack selectwith no install step). The installs were redundant and are removed.PULUMI_ACCESS_TOKENscoping (alerts 86, 81, 76) — moved from workflow-levelenv:to step-levelenv:on exactly the steps that run Pulumi, instack-deploy.yml,previews-shared-deploy.ymlandpreview-cleanup.yml.secrets: inherit→ explicit maps (alerts 78, 79, 80) —stack-deploy.ymlnow declares 11 secrets inon.workflow_call.secrets(allrequired: false, preserving the current "missing secret = empty string" semantics). Callers pass exactly what each path needs:preview-deploypasses 10;preview-destroyandpreview-cleanuppass onlyPULUMI_ACCESS_TOKEN+AWS_DEPLOY_ROLE_ARN;EXA_API_KEYremains environment-resolved.Static environment-secret access (alert 102) —
EXA_API_KEYis declared in the reusable workflow contract and referenced assecrets.EXA_API_KEY, avoiding a dynamic lookup that could make every available job secret visible to the runner.Note for reviewers:
EXA_API_KEYEXA_API_KEYis scoped to thepreviewenvironment and resolves via the deploy job'senvironment: preview. Callers intentionally do not pass it. The optionalworkflow_call.secretsdeclaration 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
actionlinton all six files: zero new findings vsmain(only pre-existing shellcheck info-level warnings remain; one warning was removed along with the deleted installer step).bun run checkpasses on the updated branch.stack-deploy.ymldeploy job, and closing the PR exercises the destroy path.