-
Notifications
You must be signed in to change notification settings - Fork 3
fix(ci): harden workflow supply-chain and injection surface #43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,22 +10,28 @@ on: | |
| - "install-code-intel-pipeline.ps1" | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| # Run darwin-skill 8-dim scoring on every new/modified SKILL.md | ||
| score-skills: | ||
| name: Darwin score (8-dim) | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Detect changed SKILL.md files | ||
| id: detect | ||
| env: | ||
| EVENT_NAME: ${{ github.event_name }} | ||
| BASE_REF: ${{ github.base_ref }} | ||
| run: | | ||
| if [ "${{ github.event_name }}" = "pull_request" ]; then | ||
| if [ "$EVENT_NAME" = "pull_request" ]; then | ||
| # PR — diff against base | ||
| git diff --name-only origin/${{ github.base_ref }}...HEAD \ | ||
| git diff --name-only "origin/$BASE_REF"...HEAD \ | ||
| | grep -E '(^|/)SKILL\.md$' > /tmp/changed_skills || true | ||
| else | ||
| # workflow_dispatch — scan all | ||
|
|
@@ -39,10 +45,10 @@ jobs: | |
| cat /tmp/changed_skills >> $GITHUB_OUTPUT | ||
| echo "EOF" >> $GITHUB_OUTPUT | ||
|
|
||
| - name: Setup Python + Anthropic SDK | ||
| - name: Setup Python + pinned deps | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| python -m pip install anthropic pyyaml | ||
| python -m pip install --require-hashes -r requirements-ci.txt | ||
|
Comment on lines
+48
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== workflow excerpt =="
sed -n '1,90p' .github/workflows/skill-check.yml 2>/dev/null || true
echo
echo "== dependency files =="
git ls-files | rg '(^|/)(requirements.*\.txt|pyproject\.toml|poetry\.lock|Pipfile\.lock|uv\.lock|pip-tools|requirements_ci|requirements-ci\.txt)$' || true
echo
echo "== pip install occurrences =="
rg -n 'pip install|--upgrade pip|--require-hashes|requirements-ci\.txt' .github . -g '!node_modules' -g '!dist' -g '!build' || trueRepository: 2233admin/code-intel-pipeline Length of output: 4439 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== requirements-ci.txt =="
cat -n requirements-ci.txt
echo
echo "== pip dependency declaration occurrences =="
rg -n '^[ \t]*(pip|pyyaml|yaml|anthropic|pytest)' requirements-ci.txt .github/workflows/skill-check.yml || true
echo
echo "== pip install commands with hashes nearby =="
python3 - <<'PY'
from pathlib import Path
import re
path = Path('requirements-ci.txt')
text = path.read_text()
for i,line in enumerate(text.splitlines(),1):
s=line.strip()
if not s or s.startswith('#'): continue
if re.search(r'(--hash=|hash=)', s):
print(f'{i}: {s}')
PYRepository: 2233admin/code-intel-pipeline Length of output: 2107 Do not install an unpinned pip version.
🤖 Prompt for AI AgentsThere was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== workflow files =="
git ls-files ".github/workflows/*" || true
echo "== skill-check relevant sections =="
wc -l .github/workflows/skill-check.yml
sed -n '1,220p' .github/workflows/skill-check.yml
echo "== requirements manifests =="
for f in requirements-ci.txt requirements.txt pyproject.toml setup.py setup.cfg; do
if [ -f "$f" ]; then echo "--- $f ---"; sed -n '1,220p' "$f"; fi
done
echo "== all pip install with require-hashes and requirements-ci.txt =="
rg -n "pip install --require-hashes -r requirements-ci.txt|pip install --require-hashes|requirements-ci\.txt" .Repository: 2233admin/code-intel-pipeline Length of output: 9647 Do not install the PR-supplied Both 📍 Affects 1 file
🤖 Prompt for AI AgentsSource: MCP tools |
||
|
|
||
| - name: Run darwin-skill 8-dim scoring | ||
| env: | ||
|
|
@@ -130,7 +136,7 @@ jobs: | |
| name: Link integrity check | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 | ||
|
|
||
| - name: Check all .md files in /crates/code-nexus-lite/ have no broken links | ||
| run: | | ||
|
|
@@ -151,11 +157,11 @@ jobs: | |
| name: Frontmatter YAML validation | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 | ||
|
|
||
| - name: Validate all SKILL.md frontmatter | ||
| run: | | ||
| python -m pip install pyyaml | ||
| python -m pip install --require-hashes -r requirements-ci.txt | ||
| python <<'PYEOF' | ||
| import sys, yaml, subprocess | ||
| from pathlib import Path | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # Hash-pinned Python dependency for .github/workflows/skill-check.yml | ||
| # (supply-chain-001). Installed with: | ||
| # pip install --require-hashes -r requirements-ci.txt | ||
| # | ||
| # Hashes cover the sdist plus manylinux x86_64 wheels for the CPython | ||
| # versions ubuntu-latest realistically ships (3.10-3.14). Regenerate by | ||
| # fetching https://pypi.org/pypi/PyYAML/json and pulling the sha256 | ||
| # digests for the target version's sdist + manylinux2014_x86_64 wheels, | ||
| # or bump the version range here if ubuntu-latest's default Python moves | ||
| # outside cp310-cp314. | ||
| pyyaml==6.0.3 \ | ||
| --hash=sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f \ | ||
| --hash=sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b \ | ||
| --hash=sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d \ | ||
| --hash=sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc \ | ||
| --hash=sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6 \ | ||
| --hash=sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5 |
There was a problem hiding this comment.
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
🧩 Analysis chain
🏁 Script executed:
Repository: 2233admin/code-intel-pipeline
Length of output: 10791
🌐 Web query:
actions/checkout v4 persist-credentials default true README💡 Result:
In the actions/checkout v4 action, the persist-credentials input defaults to true [1][2]. When persist-credentials is set to true (the default behavior), the authentication token or SSH key is persisted in the local Git configuration [3][4]. This allows subsequent scripts in your workflow to run authenticated Git commands [3][5]. The action ensures the token is removed during post-job cleanup [3]. If you wish to opt out of this behavior, you must explicitly set persist-credentials to false in your workflow file [3][4]: - uses: actions/checkout@v4 with: persist-credentials: false
Citations:
🌐 Web query:
GitHub Actions pull_request GITHUB_TOKEN permissions default read contents💡 Result:
By default, the GITHUB_TOKEN used in GitHub Actions workflows is granted permissions based on settings configured at the repository, organization, or enterprise level [1]. Administrators can choose between two default permission configurations: 1. Permissive: The GITHUB_TOKEN has read/write access for all scopes [1][2]. 2. Restricted: The GITHUB_TOKEN only has read access for the contents and packages scopes [3][1]. When a workflow is triggered by a pull request from a forked repository, GitHub enforces stricter security measures [4][2]. In this scenario, the GITHUB_TOKEN is automatically downgraded to read-only access for all scopes [1][2], regardless of the default settings, unless specific administrative settings ("Send write tokens to workflows from pull requests") are enabled (which is not recommended for public forks due to security risks) [1][5]. The
pull_request_targetevent is an exception to this automatic downgrade [5][6]. To follow the principle of least privilege, you can explicitly define the permissions required for your workflow or individual jobs using the permissions key in your YAML workflow file [7][2]. Any permissions not explicitly listed in this key are set to none [2]. Example configuration: permissions: contents: read pull-requests: write For more detailed control or cases where the GITHUB_TOKEN lacks sufficient permissions, you may need to use a personal access token (stored as a secret) or a GitHub App installation access token [7].Citations:
How the permissions are calculated for a workflow jobgithub/docs#32398Disable persisted checkout credentials in all checkout steps.
actions/checkoutpersists the workflow token by default, and subsequent steps execute repository-controlled code. Setpersist-credentials: falseon the three checkout usages;fetch-depth: 0still supplies all needed history without leaving credentials in local Git config.🧰 Tools
🪛 zizmor (1.26.1)
[warning] 22-24: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
📍 Affects 1 file
.github/workflows/skill-check.yml#L22-L24(this comment).github/workflows/skill-check.yml#L139-L139.github/workflows/skill-check.yml#L160-L160🤖 Prompt for AI Agents
Sources: MCP tools, Linters/SAST tools