Skip to content
Merged
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
36 changes: 36 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,42 @@ jobs:
- name: Voice tests (torch-free; null backend + static metadata)
run: uv run --directory servers/voice --group dev pytest -q

viewer-tests:
# The viewer is where most recent regressions landed, but its suite was not in
# CI (three viewer PRs each had to caveat "verified locally"). This job runs the
# whole viewer/tests/ suite, single-process, on push + PR so viewer regressions
# are caught in CI like the engine/rules/voice suites.
runs-on: ubuntu-latest
Comment on lines +23 to +28

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add explicit least-privilege permissions for this job.

This job currently inherits default token permissions, which is broader than needed for read-only test execution.

🔐 Proposed fix
   viewer-tests:
+    permissions:
+      contents: read
     # The viewer is where most recent regressions landed, but its suite was not in
📝 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
viewer-tests:
# The viewer is where most recent regressions landed, but its suite was not in
# CI (three viewer PRs each had to caveat "verified locally"). This job runs the
# whole viewer/tests/ suite, single-process, on push + PR so viewer regressions
# are caught in CI like the engine/rules/voice suites.
runs-on: ubuntu-latest
viewer-tests:
permissions:
contents: read
# The viewer is where most recent regressions landed, but its suite was not in
# CI (three viewer PRs each had to caveat "verified locally"). This job runs the
# whole viewer/tests/ suite, single-process, on push + PR so viewer regressions
# are caught in CI like the engine/rules/voice suites.
runs-on: ubuntu-latest
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 23-57: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block

(excessive-permissions)

🤖 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/ci.yml around lines 23 - 28, The viewer-tests job
currently inherits broad default token permissions; update the viewer-tests job
to declare explicit least-privilege permissions by adding a permissions block
that limits the GITHUB_TOKEN to only the scopes needed for read-only test
execution (for example: set contents: read and any other minimal read-only
scopes required by your test harness) so the job no longer inherits full default
permissions.

steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Install Node (for the JSX behaviour harness)
# A subset of viewer tests transpile the real .jsx through the VENDORED
# babel-standalone (viewer/openworlds/vendor/) and run it under node's `vm`.
# Babel is vendored and the harness only requires node built-ins (fs, vm), so
# NO `npm install` is needed — just a node binary on PATH. Without node these
# tests `skipIf` themselves; we install it so they actually RUN in CI.
uses: actions/setup-node@v4
Comment on lines +30 to +39

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Show the referenced section of ci.yml with line numbers
if [ -f .github/workflows/ci.yml ]; then
  echo "---- .github/workflows/ci.yml (lines 1-120) ----"
  nl -ba .github/workflows/ci.yml | sed -n '1,120p'
else
  echo "Missing: .github/workflows/ci.yml"
fi

# 2) Check if persist-credentials is already set anywhere in workflows
echo "---- Searching for persist-credentials in .github/workflows ----"
rg -n "persist-credentials\s*:" .github/workflows || true

# 3) List all action uses across workflows (only 'uses:' lines)
echo "---- Listing all uses: lines across .github/workflows ----"
rg -n "^\s*uses:\s*([^\s]+)" .github/workflows || true

# 4) Narrow to the specific actions mentioned in the comment
echo "---- Searching for actions/checkout, setup-uv, setup-node usage ----"
rg -n "uses:\s*(actions/checkout@|astral-sh/setup-uv@|actions/setup-node@)" .github/workflows || true

Repository: electricsheephq/WorldOS

Length of output: 177


🏁 Script executed:

#!/bin/bash
set -euo pipefail

if [ -f .github/workflows/ci.yml ]; then
  echo "---- .github/workflows/ci.yml (first 160 lines with line numbers) ----"
  awk 'NR<=160{printf "%d\t%s\n", NR, $0}' .github/workflows/ci.yml
else
  echo "Missing: .github/workflows/ci.yml"
fi

echo "---- Searching for persist-credentials in .github/workflows ----"
rg -n "persist-credentials\s*:" .github/workflows || true

echo "---- Listing all uses: lines across .github/workflows (uses only) ----"
rg -n "^\s*uses:\s*" .github/workflows || true

echo "---- Searching for actions/checkout, astral-sh/setup-uv, actions/setup-node usage ----"
rg -n "uses:\s*(actions/checkout@|astral-sh/setup-uv@|actions/setup-node@)" .github/workflows || true

Repository: electricsheephq/WorldOS

Length of output: 4091


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show macos-swift.yml with line numbers
if [ -f .github/workflows/macos-swift.yml ]; then
  echo "---- .github/workflows/macos-swift.yml (first 120 lines) ----"
  awk 'NR<=120{printf "%d\t%s\n", NR, $0}' .github/workflows/macos-swift.yml
fi

# Confirm there is no persist-credentials in that file
if [ -f .github/workflows/macos-swift.yml ]; then
  echo "---- persist-credentials occurrences (macos-swift.yml) ----"
  rg -n "persist-credentials\s*:" .github/workflows/macos-swift.yml || true
fi

Repository: electricsheephq/WorldOS

Length of output: 1243


Harden workflow action supply-chain usage (pin SHAs) and disable checkout credential persistence.

In .github/workflows/ci.yml’s viewer-tests job, actions/checkout@v4, astral-sh/setup-uv@v5, and actions/setup-node@v4 are only pinned to tags, and checkout does not set persist-credentials: false.

🛡️ Proposed fix
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@<FULL_LENGTH_COMMIT_SHA>
+        with:
+          persist-credentials: false
       - name: Install uv
-        uses: astral-sh/setup-uv@v5
+        uses: astral-sh/setup-uv@<FULL_LENGTH_COMMIT_SHA>
       - name: Install Node (for the JSX behaviour harness)
-        uses: actions/setup-node@v4
+        uses: actions/setup-node@<FULL_LENGTH_COMMIT_SHA>
🧰 Tools
🪛 zizmor (1.25.2)

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

(artipacked)


[error] 30-30: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 32-32: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 39-39: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 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/ci.yml around lines 30 - 39, The workflow currently uses
unpinned tags for actions (actions/checkout@v4, astral-sh/setup-uv@v5,
actions/setup-node@v4) and leaves checkout credentials persisted; update the
viewer-tests job to pin each action to a specific commit SHA instead of the tag
and modify the actions/checkout step to include persist-credentials: false to
avoid leaking tokens to checked-out workflows. Locate the steps referencing the
exact strings "actions/checkout@v4", "astral-sh/setup-uv@v5", and
"actions/setup-node@v4" and replace their uses with the corresponding full
commit SHAs, and add persist-credentials: false under the checkout step.

with:
node-version: "20"
- name: Create + activate a venv with the viewer test deps
# Most viewer tests import viewer/server.py (stdlib-only at import time) and need
# no third-party deps. The exception is test_portrait_gen's real-subprocess test,
# which shells the engine via `uv run --directory servers/engine --no-project`
# (a bare interpreter) to prove the null image provider opens no socket. That
# child resolves the ACTIVE venv, so installing pydantic (the engine's runtime
# dep, declared in servers/engine/pyproject.toml) here lets the engine subprocess
# import `store`/`imagegen` and the test runs instead of erroring on import.
run: |
uv venv .venv-viewer --python 3.12
echo "VIRTUAL_ENV=$PWD/.venv-viewer" >> "$GITHUB_ENV"
echo "$PWD/.venv-viewer/bin" >> "$GITHUB_PATH"
uv pip install --python .venv-viewer pydantic pytest
- name: Viewer tests (single-process; JSX harness via node + vendored babel)
# -p no:xdist keeps this single-process (no parallel workers) — lean by design.
run: python -m pytest viewer/tests -q -p no:xdist

license-check:
runs-on: ubuntu-latest
steps:
Expand Down
Loading