Skip to content

fix(ci): make the sandbox kit workflow runnable - #3459

Merged
migmartri merged 2 commits into
mainfrom
fix/sandbox-kit-workflow-empty-expression
Sep 22, 2026
Merged

migmartri merged 2 commits into
mainfrom
fix/sandbox-kit-workflow-empty-expression

Conversation

@migmartri

@migmartri migmartri commented Sep 21, 2026 •

Copy link
Copy Markdown
Member

Summary

The Package Sandbox Kit workflow has never run successfully. Two independent blockers.

1. The workflow file does not parse. A shell comment inside the "Add Attestation (Sandbox Kit) and Push Kit" step contained the literal empty expression syntax. GitHub expands template expressions across the whole workflow file, including inside run: bodies and the shell comments within them, so the empty expression failed expression parsing and the entire file was rejected. Runs surfaced only as "This run likely failed because of a workflow file issue", with no jobs and no check runs. The comment is reworded and now states the constraint so it is not reintroduced.

2. The Docker Hub login could not succeed. The step passes the organization as username, omits password and sets DOCKERHUB_OIDC_CONNECTIONID, which is the documented Docker Hub OIDC shape. That support landed in docker/login-action v4.5.0, but the step pinned v4.4.0, which ignores the variable and rejects a password-less login with "Password required". Pinned to v4.6.0.

Since the workflow triggers on devel/sandbox-kit/*/spec.yaml, which the release bump script rewrites, every release bump produced a failed run and no sandbox kit has been published.

Verification

  • actionlint is clean on the file.
  • The discover step's script was replayed against the real v1.109.0 to v1.110.0 push (kits=["claude"]) and against a no-op range (kits=[]).
  • docker/login-action v4.6.0 confirmed to implement DOCKERHUB_OIDC_CONNECTIONID; v4.4.0 confirmed not to.
  • The pinned sbx v0.43.0 publishes DockerSandboxes-linux-amd64-ubuntu2404.deb and ubuntu-latest is ubuntu-24.04.
  • sbx kit validate REFERENCE and sbx kit push DIRECTORY REFERENCE --sign match the invocations, and sbx v0.43.0 reports VALID for devel/sandbox-kit/claude.
  • The pinned installer digest matches the current dl.chainloop.dev/cli/install.sh.

Still unexercised until this actually runs: the Docker Hub OIDC connection ruleset, the push to docker.io/chainloop/sbx-kit-claude, and the material kind auto-detection for chainloop attestation add --name sandbox-kit, which has no entry in .github/workflows/contracts/ unlike every other attesting workflow.

AI assistance

This change was produced with the assistance of Claude Code. Both commits carry an Assisted-by: Claude Code trailer.

🤖 Posted by Maximus bot (Claude Code) on behalf of @migmartri

A shell comment in the "Add Attestation and Push Kit" step contained the
literal empty expression syntax. GitHub expands template expressions across
the entire workflow file, including inside run bodies and their comments, so
the empty expression failed expression parsing and the whole file was
rejected. The workflow never scheduled a job on any release bump, which means
no sandbox kit has been published since it was added.

Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>

Chainloop-Trace-Sessions: 1e55d1fc-a673-481e-a278-4cdd9eecb47f
@chainloop-platform

chainloop-platform Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

AI Session Checks — 🟡 82% · ⚠️ 1 failing

Avg score Sessions Failing policies Attribution Files Lines Total Duration
🟡 82% 1 ⚠️ 1 100% AI / 0% Human 1 +9 / -3 10m16s

🟡 82% — 100% AI — ⚠️ 1 policies failing

Sep 21, 2026 13:42 UTC · 10m16s · $6.94 · 192 in / 50.5k out · claude-code 2.1.278 (claude-opus-5)

View session details ↗

Change Summary

  • Rewords the package_sandbox_kit workflow comment that contained an empty ${{ }} expression.
  • Bumps docker/login-action from v4.4.0 to v4.6.0 for Docker Hub OIDC support.
  • Adds workflow comments documenting the OIDC version requirement.

AI Session Overall Score

🟡 82% — Solid fix, but planning was thin and workflow success was never end-to-end verified.

AI Session Analysis Breakdown

🟢 94% · scope-discipline

🟢 Both fixes stayed in the same workflow file the investigation centered on. · High Impact

🟢 92% · solution-quality

🟢 The AI found two concrete root causes instead of papering over the failure. · High Impact

🟢 90% · alignment

🟢 AI explicitly warned the first fix only restored parsing, not full execution. · Medium Impact

🟢 90% · user-trust-signal

No notes.

🟡 65% · context-and-planning

🟠 The session started from a thin prompt and never produced a visible plan before editing. · Medium Severity

💡 For workflow investigations, write a short plan before editing so validation steps are explicit.

🟡 65% · verification

🟠 Workflow changes were locally probed, but the GitHub Actions path was never rerun after the fixes. · Medium Severity

💡 For workflow fixes, rerun the job or trigger the path before saying it will work.


File Attribution

████████████████████ 100% AI / 0% Human

Status Attribution File Lines
modified ai .github/workflows/package_sandbox_kit.yaml +9 / -3

Policies (4, 1 failing)

Status Policy Material Messages
✅ Passed ai-config-ai-agents-allowed ai-coding-session-1e55d1 -
✅ Passed ai-config-no-dangerous-commands ai-coding-session-1e55d1 -
⚠️ Failed ai-config-no-secrets ai-coding-session-1e55d1
  • Secret (generic-password) detected in session content [turn=161, source=assistant-text, line=7]: One caveat: this only makes the workflow parse. It has never actually executed a single step, so the rest of it — the Docker Hub OIDC login (which passes username with no [REDACTED:generic-passwo...</li><li>Secret (generic-password) detected in session content [turn=185, source=tool_result, line=33]: [REDACTED:generic-password]: ${{ secrets.GITHUB_TOKEN }}</li><li>Secret (generic-password) detected in session content [turn=230, source=tool_result, line=13]: 155-action as the [REDACTED:generic-password].</li><li>Secret (generic-password) detected in session content [turn=230, source=tool_result, line=2]: 144- [REDACTED:generic-password]: ${{ secrets.AZURE_CLIENT_SECRET }}</li><li>Secret (generic-password) detected in session content [turn=233, source=tool_result, line=17]: [REDACTED:generic-password]:</li><li>Secret (generic-password) detected in session content [turn=248, source=tool_result, line=111]: await Docker.getExecOutput(['login', '--[REDACTED:generic-password]-stdin', '--username', username, registry], {</li><li>Secret (generic-password) detected in session content [turn=248, source=tool_result, line=114]: input: Buffer.from([REDACTED:generic-password]),</li><li>Secret (generic-password) detected in session content [turn=248, source=tool_result, line=51]: await loginECR(auth.registry, auth.username, auth.[REDACTED:generic-password], auth.scope);</li><li>Secret (generic-password) detected in session content [turn=248, source=tool_result, line=53]: await loginStandard(auth.registry, auth.username, auth.[REDACTED:generic-password], auth.scope);</li><li>Secret (generic-password) detected in session content [turn=248, source=tool_result, line=77]: export async function loginStandard(registry: string, username: string, [REDACTED:generic-password]: string, scope?: string): Promise<void> {</li><li>Secret (generic-password) detected in session content [turn=248, source=tool_result, line=78]: if (!username && ![REDACTED:generic-password]) {</li><li>Secret (generic-password) detected in session content [turn=248, source=tool_result, line=79]: throw new Error('Username and [REDACTED:generic-password] required');</li><li>Secret (generic-password) detected in session content [turn=248, source=tool_result, line=84]: if (![REDACTED:generic-password]) {</li><li>Secret (generic-password) detected in session content [turn=248, source=tool_result, line=87]: await loginExec(registry, username, [REDACTED:generic-password], scope);</li><li>Secret (generic-password) detected in session content [turn=248, source=tool_result, line=90]: export async function loginECR(registry: string, username: string, [REDACTED:generic-password]: string, scope?: string): Promise<void> {</li><li>Secret (generic-password) detected in session content [turn=248, source=tool_result, line=92]: const regDatas = await aws.getRegistriesData(registry, username, [REDACTED:generic-password]);</li><li>Secret (generic-password) detected in session content [turn=248, source=tool_result, line=94]: await loginExec(regData.registry, regData.username, regData.[REDACTED:generic-password], scope);</li><li>Secret (generic-password) detected in session content [turn=248, source=tool_result, line=98]: async function loginExec(registry: string, username: string, [REDACTED:generic-password]: string, scope?: string): Promise<void> {</li><li>Secret (generic-password) detected in session content [turn=252, source=tool_result, line=14]: 64:organization name as username, omit [REDACTED:generic-password], and set the OIDC connection</li><li>Secret (generic-password) detected in session content [turn=336, source=tool_result, line=10]: organization name as username, omit [REDACTED:generic-password]`, and set the OIDC connection
  • … and 3 more — view all ↗
✅ Passed ai-config-mcp-servers-allowed ai-coding-session-1e55d1 -

Security Checks — ✅ 10 passing

✅ secret-scan

Status Policy Messages
✅ Passed secrets-detection -

✅ github-actions-scan

Status Policy Messages
✅ Passed ci-pipeline-security -

✅ sast-scan

Status Policy Messages
✅ Passed owasp-top10-2025 -
✅ Passed sast -
✅ Passed cwe-top25 -
✅ Passed cwe-top26-40-cusp -

✅ iac-scan

Status Policy Messages
✅ Passed iac-misconfiguration -

PR info

Status Policy Messages
✅ Passed pr-min-approvals -
✅ Passed pr-description-required -
✅ Passed pr-user-story-linked -

⏭️ 1 scan not applied

Scan Reason
vulnerability-scan no manifest/lockfile changed

View attestation ↗
View attestation ↗


Powered by Chainloop and Chainloop Trace

@migmartri
migmartri requested a review from a team September 21, 2026 13:46

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 1 file

Re-trigger cubic

The Docker Hub login step passes the organization as `username`, omits
`password` and sets DOCKERHUB_OIDC_CONNECTIONID, which is the documented
Docker Hub OIDC shape. That support landed in docker/login-action v4.5.0;
the step pinned v4.4.0, which ignores the variable entirely and rejects a
password-less login with "Password required". Pin v4.6.0.

Assisted-by: Claude Code
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>

Chainloop-Trace-Sessions: 1e55d1fc-a673-481e-a278-4cdd9eecb47f
@migmartri migmartri changed the title fix(ci): make the sandbox kit workflow parseable fix(ci): make the sandbox kit workflow runnable Sep 21, 2026
@migmartri
migmartri merged commit 7d7618d into main Sep 22, 2026
16 of 17 checks passed
@migmartri
migmartri deleted the fix/sandbox-kit-workflow-empty-expression branch September 22, 2026 18:52
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.

3 participants