Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 45 additions & 6 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,23 @@ on:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
RELEASE_TAG: ${{ github.event.inputs.tag_name || github.ref_name }}

jobs:
publish:
jsr-publish:

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.

P1: Restore id-token: write on jsr-publish; otherwise npx jsr publish loses the GitHub OIDC token JSR requires and publication can fail before Docker runs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/publish.yaml, line 18:

<comment>Restore `id-token: write` on `jsr-publish`; otherwise `npx jsr publish` loses the GitHub OIDC token JSR requires and publication can fail before Docker runs.</comment>

<file context>
@@ -12,19 +12,23 @@ on:
 
 jobs:
-  publish:
+  jsr-publish:
     runs-on: ubuntu-latest
 
</file context>

runs-on: ubuntu-latest

permissions:
contents: read
packages: write
attestations: write
id-token: write

steps:
- uses: actions/checkout@v4
with:
ref: ${{ env.RELEASE_TAG }}

- uses: denoland/setup-deno@v2
with:
deno-version: v2.4.0
Comment on lines +18 to +31

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

sed -n '1,220p' .github/workflows/publish.yaml

Repository: deco-cx/deco

Length of output: 6050


🌐 Web query:

JSR GitHub Actions publish id-token write trusted publishing official docs

💡 Result:

To publish packages to JSR using trusted publishing from GitHub Actions, you must use OpenID Connect (OIDC) authentication [1][2]. This process eliminates the need for manual API tokens by allowing GitHub Actions to provide a short-lived OIDC token that JSR uses to verify your repository's identity [1][2][3]. To set up trusted publishing, follow these steps: 1. Link your package: Go to the settings tab of your package on jsr.io, enter your GitHub repository name, and click Link [1][4]. This is a required one-time setup [2]. 2. Configure your workflow: In your GitHub Actions workflow file (e.g.,.github/workflows/publish.yml), you must grant the job the necessary permissions to request an OIDC token [1][3]. Include the following in your job definition: permissions: contents: read id-token: write # Required for OIDC authentication with JSR 3. Publish: Use the jsr publish or deno publish command in your workflow steps [1][5][4]. By publishing through this native GitHub Actions integration, JSR automatically generates SLSA provenance attestations stored in the Sigstore Rekor transparency log, which helps verify the build source and provenance of your package [5][6]. You can opt out of this by using the --no-provenance flag [5][6]. Token-based authentication remains available for other CI providers, but does not support automatic provenance generation [1][4].

Citations:


Add id-token: write to jsr-publish
npx jsr publish uses JSR trusted publishing, so this job needs permissions: id-token: write alongside contents: read; otherwise the publish steps can’t authenticate.

🔧 Proposed fix
     permissions:
       contents: read
+      id-token: write
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
jsr-publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ env.RELEASE_TAG }}
- uses: denoland/setup-deno@v2
with:
deno-version: v2.4.0
jsr-publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ env.RELEASE_TAG }}
- uses: denoland/setup-deno@v2
with:
deno-version: v2.4.0
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 25-27: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/publish.yaml around lines 18 - 31, The jsr-publish
workflow job is missing the OIDC permission needed for trusted publishing.
Update the permissions block in jsr-publish to include id-token: write alongside
contents: read so the npx jsr publish step can authenticate; use the jsr-publish
job name and its permissions section to locate the change.

Source: Linters/SAST tools


- name: Publish package
run: npx jsr publish
Expand All @@ -35,6 +39,41 @@ jobs:
- name: Publish dev package
run: cd dev/ && npx jsr publish

- name: Verify JSR package is resolvable
run: |
#!/bin/bash
set -euo pipefail

VERSION="${{ env.RELEASE_TAG }}"

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.

P2: Potential script injection via direct ${{ }} interpolation into the shell script. While env.RELEASE_TAG is somewhat trusted (set from workflow_dispatch input or ref_name), the safer pattern is to pass it through the step's env: mapping to avoid shell metacharacter issues.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/publish.yaml, line 47:

<comment>Potential script injection via direct `${{ }}` interpolation into the shell script. While `env.RELEASE_TAG` is somewhat trusted (set from `workflow_dispatch` input or `ref_name`), the safer pattern is to pass it through the step's `env:` mapping to avoid shell metacharacter issues.</comment>

<file context>
@@ -35,6 +39,41 @@ jobs:
+          #!/bin/bash
+          set -euo pipefail
+
+          VERSION="${{ env.RELEASE_TAG }}"
+
+          for attempt in $(seq 1 30); do
</file context>


for attempt in $(seq 1 30); do
if deno cache "jsr:@deco/deco@${VERSION}/scripts/run"; then
echo "JSR version ${VERSION} is resolvable (attempt ${attempt})"
exit 0
fi

echo "Waiting for JSR propagation (attempt ${attempt}/30)..."
sleep 10
done

echo "JSR version ${VERSION} not resolvable after 5 minutes"
exit 1

Comment on lines +42 to +61

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Script injection via direct ${{ }} interpolation into shell.

VERSION="${{ env.RELEASE_TAG }}" is template-expanded by GitHub Actions into the script text before bash runs it, rather than passed as a shell variable. If RELEASE_TAG (derived from a workflow_dispatch input or ref_name) ever contains shell metacharacters, this allows arbitrary command injection into the runner. zizmor flags this pattern explicitly.

🔒 Proposed fix using `env:` mapping
       - name: Verify JSR package is resolvable
+        env:
+          VERSION: ${{ env.RELEASE_TAG }}
         run: |
           #!/bin/bash
           set -euo pipefail
-
-          VERSION="${{ env.RELEASE_TAG }}"
 
           for attempt in $(seq 1 30); do
             if deno cache "jsr:`@deco/deco`@${VERSION}/scripts/run"; then
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Verify JSR package is resolvable
run: |
#!/bin/bash
set -euo pipefail
VERSION="${{ env.RELEASE_TAG }}"
for attempt in $(seq 1 30); do
if deno cache "jsr:@deco/deco@${VERSION}/scripts/run"; then
echo "JSR version ${VERSION} is resolvable (attempt ${attempt})"
exit 0
fi
echo "Waiting for JSR propagation (attempt ${attempt}/30)..."
sleep 10
done
echo "JSR version ${VERSION} not resolvable after 5 minutes"
exit 1
- name: Verify JSR package is resolvable
env:
VERSION: ${{ env.RELEASE_TAG }}
run: |
#!/bin/bash
set -euo pipefail
for attempt in $(seq 1 30); do
if deno cache "jsr:`@deco/deco`@${VERSION}/scripts/run"; then
echo "JSR version ${VERSION} is resolvable (attempt ${attempt})"
exit 0
fi
echo "Waiting for JSR propagation (attempt ${attempt}/30)..."
sleep 10
done
echo "JSR version ${VERSION} not resolvable after 5 minutes"
exit 1
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 47-47: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/publish.yaml around lines 42 - 61, The shell step in the
JSR resolvability check is interpolating RELEASE_TAG directly into the script
via `${{ }}`, which can lead to command injection. Update the workflow so the
`Verify JSR package is resolvable` step receives `RELEASE_TAG` through an `env:`
mapping and then reads it as a normal shell variable inside the bash script;
keep the existing `deno cache` loop and `VERSION` usage, but remove direct
template expansion from the run block.

Source: Linters/SAST tools

docker-build:
runs-on: ubuntu-latest
needs: jsr-publish

permissions:
contents: read
packages: write
attestations: write
id-token: write

steps:
- uses: actions/checkout@v4
with:
ref: ${{ env.RELEASE_TAG }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

Expand All @@ -59,7 +98,7 @@ jobs:
REGISTRY: ${{ env.REGISTRY }}
REPOSITORY: ${{ env.IMAGE_NAME }}
IMAGE_TAG_LATEST: latest
IMAGE_TAG_COMMIT: ${{ github.event.inputs.tag_name || github.ref_name }}
IMAGE_TAG_COMMIT: ${{ env.RELEASE_TAG }}
run: |
#!/bin/bash

Expand Down Expand Up @@ -110,7 +149,7 @@ jobs:
REGISTRY: ${{ env.REGISTRY }}
REPOSITORY: ${{ env.IMAGE_NAME }}/deno2
IMAGE_TAG_LATEST: latest
IMAGE_TAG_COMMIT: ${{ github.event.inputs.tag_name || github.ref_name }}
IMAGE_TAG_COMMIT: ${{ env.RELEASE_TAG }}
run: |
#!/bin/bash

Expand Down
Loading