Repository navigation
fix(gha): pull jsii-terraform CI image from GHCR instead of Docker Hub - #261
Conversation
Docker Hub anonymous pull throttling on GitHub's shared runner IP pool causes intermittent container-init failures across CI jobs. Publish the image to ghcr.io/open-constructs/jsii-terraform (public-package pulls from Actions runners are free and unauthenticated) and repoint all workflow container references to it. The pinned digest is unchanged: the existing image is mirrored registry-to-registry, which preserves the manifest digest. docker.yml keeps pushing to Docker Hub until consumers have moved, and adds the OCI source label so the GHCR package auto-links to this repository. Refs #206 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔒 Cache poisoning risks in workflow changesThis PR is clean and correct in intent, but the 1. Bare key: ${{ runner.os }}-buildx-${{ hashFiles('/Dockerfile', '.terraform.versions.json') }}
restore-keys: |
${{ runner.os }}-buildx-The Fix: add a hash fallback: restore-keys: |
${{ runner.os }}-buildx-${{ hashFiles('/Dockerfile', '.terraform.versions.json') }}
${{ runner.os }}-buildx-This prefers the exact-hash match but falls back to any 2. The leading Fix: use These are pre-existing, not introduced by this PR, but since this PR touches |
…sh workflow
zizmor flags the docker publish workflow with a high-severity
cache-poisoning finding: it restored a GitHub Actions layer cache
(actions/cache + buildx type=local) and then published the resulting
image, so a cache entry poisoned from a less-privileged context could
be baked into the published image. The pre-existing cache key also used
an absolute hashFiles('/Dockerfile') path that never resolves, plus a
bare restore-keys prefix that matched any prior buildx cache — so the
cache provided little isolation while carrying the risk.
Switch to a registry-backed buildx cache at
ghcr.io/open-constructs/jsii-terraform:buildcache (mode=max). Writing
to it requires packages:write, which only this workflow's token has
(push to main / dispatch), so less-privileged contexts cannot poison
it — unlike the Actions cache. Layer caching is preserved without the
attack vector.
Also set persist-credentials: false on checkout (zizmor artipacked).
zizmor now reports no findings on this workflow.
Refs #206
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Thanks for flagging this — addressed in 676fcbd, though with a different fix than the suggested key tightening. I ran Resolution — registry-backed buildx cache: cache-from: type=registry,ref=ghcr.io/open-constructs/jsii-terraform:buildcache
cache-to: type=registry,ref=ghcr.io/open-constructs/jsii-terraform:buildcache,mode=max
Also set |
Re-verified at 676fcbd — this is the right approach:
First-run cold cache: the |
🤖 Release PR — merge to cut a new release. Kept open and rebased as commits land on `main`. --- <details><summary>0.23.4</summary> ## [0.23.4](v0.23.3...v0.23.4) (2026-07-02) ### Features * **cli:** validate Terraform CLI feature versions ([#237](#237)) ([32d434c](32d434c)) * declared Terraform/OpenTofu target versions (validation foundation) ([#269](#269)) ([0aa2343](0aa2343)) * **lib:** S3-backend - Add `useLockfile` field and update `dynamodbTable` deprecated JSDoc ([#234](#234)) ([32a408f](32a408f)) * **lib:** validate Fn usage against Terraform/OpenTofu versions ([#268](#268)) ([cdf8115](cdf8115)) ### Bug Fixes * **cli:** don't mistake terraform error output for a missing-variable prompt ([#267](#267)) ([0ea946f](0ea946f)) * **cli:** release terraform state lock when interrupting diff/deploy ([#284](#284)) ([de617db](de617db)) * **cli:** resolve prebuilt Java provider versions via repo1.maven.org ([#285](#285)) ([d5af07d](d5af07d)) * **gha:** Adding CHANGELOG.md to prettier ignore list ([#258](#258)) ([5160469](5160469)) * **gha:** pull jsii-terraform CI image from GHCR instead of Docker Hub ([#261](#261)) ([f19d34b](f19d34b)) * **provider-generator:** copy only publishable files into the jsii compile bundle ([#292](#292)) ([562d4c7](562d4c7)) * **provider-generator:** match shorthand provider sources against OpenTofu schema keys ([#293](#293)) ([fda0103](fda0103)) * **release:** add Changelog title for correct release-please insertion ([#255](#255)) ([004818a](004818a)) * **release:** drop devEngines.packageManager that broke npm publish ([ef508a6](ef508a6)) * **tools:** repair generate-function-bindings tool ([#273](#273)) ([821e1cf](821e1cf)) ### Miscellaneous Chores * Add Gradle to Mise config ([#271](#271)) ([1578270](1578270)) * add pnpm to mise ([#266](#266)) ([48ab91f](48ab91f)) * add uv to mise ([#260](#260)) ([163cf3d](163cf3d)) * **deps:** bump nrwl/nx-set-shas from 38457b511e60ee4e1da09255b658e480748a1af4 to afb73a62d26e41464e9254689e1fd6122ee683c1 ([#236](#236)) ([b5ac018](b5ac018)) * **deps:** bump the github-actions-backward-compatible group across 1 directory with 7 updates ([#235](#235)) ([de67d9f](de67d9f)) * **deps:** replace uuid dependency with node:crypto.randomUUID ([#291](#291)) ([6d3657a](6d3657a)) * ESLint ignore test edge-provider-bindings ([#270](#270)) ([ba407bb](ba407bb)) * Fix Verdaccio logging config ([#272](#272)) ([aded64b](aded64b)) * **gha:** parallelize provider binding generation for documentation examples ([#244](#244)) ([0a9c955](0a9c955)) * Migrate package manager from yarn to pnpm ([#170](#170)) ([d23da4e](d23da4e)) * migrate planning artifacts to cdktn-planning [skip ci] ([968c358](968c358)) * **release:** add release-please automation for versioning ([#243](#243)) ([c759eec](c759eec)) * Remove dependency-pinner tool ([#250](#250)) ([42c27d5](42c27d5)) * Remove unused dependencies ([#281](#281)) ([c7de65e](c7de65e)) * **tests:** run verdaccio in-process ([#248](#248)) ([c17677d](c17677d)) * Update JSII version constraint ([#245](#245)) ([d89558f](d89558f)) * Update scheduled workflows to only run on open-constructs/cdk-terrain ([#256](#256)) ([ba408cf](ba408cf)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: open-constructs-cdktn[bot] <291052431+open-constructs-cdktn[bot]@users.noreply.github.com>
|
I'm going to lock this pull request because it has been closed for 30 days. This helps our maintainers find and focus on the active issues. If you've found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. |

Refs #206 (GHCR-for-CI half; OCF Public ECR for the devcontainer is a follow-up).
Why
Docker Hub's anonymous pull throttling on GitHub's shared runner IP pool is causing intermittent container-init failures across CI (see the audit in #206). All ~27
container:references across 12 workflows pullterraconstructs/jsii-terraformanonymously; GHCR public-package pulls from Actions runners are free, unmetered, and unauthenticated.What
docker.yml: also pushes toghcr.io/open-constructs/jsii-terraform(packages: write+docker/login-actionagainstghcr.iowithGITHUB_TOKEN). Docker Hub publishing stays until consumers have moved.Dockerfile: addsorg.opencontainers.image.sourcelabel so future pushes auto-link the GHCR package to this repo (plus description/licenses labels).container.imagerepointed toghcr.io/open-constructs/jsii-terraform@sha256:c46ac91…— the same digest as today, because the image is mirrored registry-to-registry (digest-preserving). No rebuild needed for this PR's CI to pass.Prerequisites before marking ready (one-time, maintainer)
docker.ymlpush to main).Follow-ups (tracked in #206)
.devcontainer.json+CONTRIBUTING.md.DOCKERHUB_*secrets once consumers have moved.🤖 Generated with Claude Code