Skip to content

Commit b6feab2

Browse files
authored
fix: address code scanning alerts (#305)
## Summary - Replace exporter HTML text extraction/entity decoding paths that triggered CodeQL with shared scanner helpers, preserving literal comparison text like `2 < 3` while still stripping real tags. - Add regression tests for Markdown and editable PPTX export text extraction. - Pin GitHub Actions to commit SHAs and restrict default workflow token permissions. - Harden `pull_request_target` PR review automation so fork PRs require the `safe-to-review` label before the write-token bot runs. - Remove unnecessary release friction: Snap remains best-effort and no longer gates provenance/publish. - Clarify AGENTS/CLAUDE license policy so shipped/runtime dependencies stay permissive while workflow-only tools can use copyleft licenses when not bundled or distributed. - Restore winget release automation and explicitly allow its workflow-only action in Dependency Review. ## Why GitHub code scanning currently reports CodeQL high alerts in exporter text cleanup and Scorecard alerts around workflow token permissions, unpinned actions, and `pull_request_target` risk. The exporter issue came from regex-based tag/entity handling; the workflow issues came from broad defaults and floating action tags. The previous blanket AGPL/GPL rule was too broad for CI-only tooling. This PR keeps the product/distribution boundary strict while allowing isolated release automation that does not ship in the app. ## Validation - `pnpm --filter @open-codesign/exporters exec vitest run src/pptx.test.ts src/markdown.test.ts` - `pnpm typecheck` - `pnpm test` - `pnpm lint` - `git diff --check` - Workflow YAML parsed successfully with Ruby YAML loader - Verified no remaining `uses: ...@(vN|main|master)` references in `.github/workflows` ## Notes - Local `codeql` and `actionlint` CLIs are not installed here, so final CodeQL/Scorecard closure needs GitHub Actions to rescan this PR. - Created the `safe-to-review` label in the repository for maintainers to opt external fork PRs into bot review.
1 parent 4111928 commit b6feab2

19 files changed

Lines changed: 194 additions & 166 deletions

.github/prompts/codex-pr-review.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Open CoDesign is an open-source AI design tool — Electron desktop app that tur
2525

2626
**Project constraints:**
2727
- ≤ 30 prod dependencies
28-
- MIT-compatible permissive licenses only (reject GPL/AGPL/SSPL/proprietary/unclear copied assets)
28+
- Shipped app/runtime dependencies and copied/bundled assets must be MIT-compatible permissive. Workflow-only CI/release actions may use copyleft licenses when they are not vendored or distributed and their outputs are ordinary metadata/manifests.
2929
- All LLM calls via `@mariozechner/pi-ai` (no direct provider SDK imports in app code)
3030
- No silent fallbacks for user-visible failure, data loss, auth/security decisions,
3131
or persisted state. Best-effort cleanup, optional discovery, and non-critical

.github/workflows/ci.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ on:
66
pull_request:
77
branches: [main, dev/v0.2]
88

9+
permissions:
10+
contents: read
11+
912
concurrency:
1013
group: ${{ github.workflow }}-${{ github.ref }}
1114
cancel-in-progress: true
@@ -17,13 +20,13 @@ jobs:
1720
name: Lint, typecheck, test
1821
runs-on: ubuntu-latest
1922
steps:
20-
- uses: actions/checkout@v4
23+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
2124

2225
- name: Setup pnpm
23-
uses: pnpm/action-setup@v4
26+
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
2427

2528
- name: Setup Node
26-
uses: actions/setup-node@v4
29+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
2730
with:
2831
node-version-file: .nvmrc
2932
cache: pnpm

.github/workflows/codeql.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ on:
1212
schedule:
1313
- cron: '23 4 * * 1'
1414

15+
permissions:
16+
contents: read
17+
1518
jobs:
1619
analyze:
1720
name: Analyze
@@ -26,10 +29,10 @@ jobs:
2629
matrix:
2730
language: [javascript-typescript]
2831
steps:
29-
- uses: actions/checkout@v4
30-
- uses: github/codeql-action/init@v3
32+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
33+
- uses: github/codeql-action/init@0daab03d71ff584ef619d027a3fd9146679c5d84 # v3
3134
with:
3235
languages: ${{ matrix.language }}
33-
- uses: github/codeql-action/analyze@v3
36+
- uses: github/codeql-action/analyze@0daab03d71ff584ef619d027a3fd9146679c5d84 # v3
3437
with:
3538
category: "/language:${{ matrix.language }}"

.github/workflows/codex-pr-review.yml

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,22 @@ concurrency:
88
group: codex-pr-review-${{ github.event.pull_request.number }}
99
cancel-in-progress: true
1010

11+
permissions:
12+
contents: read
13+
1114
jobs:
1215
pr-review:
16+
# Fork PRs can carry adversarial content. Run the write-token bot only
17+
# after a maintainer explicitly adds safe-to-review.
1318
if: |
1419
github.event.pull_request.draft == false &&
1520
!endsWith(github.actor, '[bot]') &&
1621
!contains(github.event.pull_request.labels.*.name, 'bot-skip') &&
17-
vars.CODEX_BOT_ENABLED == 'true'
22+
vars.CODEX_BOT_ENABLED == 'true' &&
23+
(
24+
github.event.pull_request.head.repo.full_name == github.repository ||
25+
contains(github.event.pull_request.labels.*.name, 'safe-to-review')
26+
)
1827
runs-on: ubuntu-latest
1928
permissions:
2029
contents: read
@@ -25,7 +34,7 @@ jobs:
2534
steps:
2635
- name: Check bot review state
2736
id: check_bot
28-
uses: actions/github-script@v7
37+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
2938
with:
3039
script: |
3140
const marker = "*Open-CoDesign Bot*";
@@ -67,9 +76,9 @@ jobs:
6776

6877
- name: Checkout repository
6978
if: steps.check_bot.outputs.has_review_for_current_head != 'true'
70-
uses: actions/checkout@v4
79+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
7180
with:
72-
ref: ${{ github.event.pull_request.base.ref }}
81+
ref: ${{ github.event.pull_request.base.sha }}
7382
fetch-depth: 0
7483

7584
- name: Pre-fetch base and head refs
@@ -85,7 +94,7 @@ jobs:
8594
# This workflow runs under pull_request_target so it can post reviews.
8695
# The checked-out merge ref is untrusted contributor content; never
8796
# let a PR modify the prompt that receives write-token access.
88-
git show "origin/${{ github.event.pull_request.base.ref }}:.github/prompts/codex-pr-review.md" \
97+
git show "${{ github.event.pull_request.base.sha }}:.github/prompts/codex-pr-review.md" \
8998
> .github/prompts/codex-pr-review.md
9099
91100
- name: Resolve review provider config
@@ -155,7 +164,7 @@ jobs:
155164
- name: Run Codex for PR Review
156165
id: run_codex
157166
if: steps.check_bot.outputs.has_review_for_current_head != 'true' && steps.review_config.outputs.is_deepseek != 'true'
158-
uses: openai/codex-action@v1
167+
uses: openai/codex-action@e0fdf01220eb9a88167c4898839d273e3f2609d1 # v1
159168
env:
160169
GH_TOKEN: ${{ github.token }}
161170
GITHUB_TOKEN: ${{ github.token }}

.github/workflows/dependency-review.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ jobs:
1515
if: github.event.repository.visibility == 'public'
1616
runs-on: ubuntu-latest
1717
steps:
18-
- uses: actions/checkout@v4
19-
- uses: actions/dependency-review-action@v4
18+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
19+
- uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4
2020
with:
2121
fail-on-severity: moderate
2222
deny-licenses: GPL-2.0-only, GPL-2.0-or-later, GPL-3.0-only, GPL-3.0-or-later, AGPL-3.0-only, AGPL-3.0-or-later, SSPL-1.0
23+
# Workflow-only release tooling is not bundled, linked, vendored, or
24+
# distributed with the app. Keep shipped/runtime deps under the deny
25+
# list above, but allow this action so winget automation can run.
26+
allow-dependencies-licenses: pkg:githubactions/vedantmgoyal9/winget-releaser

.github/workflows/deploy-website.yml

Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ on:
88

99
permissions:
1010
contents: read
11-
pages: write
12-
id-token: write
1311

1412
concurrency:
1513
group: pages
@@ -19,15 +17,15 @@ jobs:
1917
build:
2018
runs-on: ubuntu-latest
2119
steps:
22-
- uses: actions/checkout@v4
20+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
2321
with:
2422
fetch-depth: 0
2523

26-
- uses: pnpm/action-setup@v4
24+
- uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
2725
with:
2826
version: 9.15.0
2927

30-
- uses: actions/setup-node@v4
28+
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
3129
with:
3230
node-version: 22
3331
cache: pnpm
@@ -38,9 +36,9 @@ jobs:
3836
- name: Build website
3937
run: pnpm --filter open-codesign-website build
4038

41-
- uses: actions/configure-pages@v4
39+
- uses: actions/configure-pages@1f0c5cde4bc74cd7e1254d0cb4de8d49e9068c7d # v4
4240

43-
- uses: actions/upload-pages-artifact@v3
41+
- uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
4442
with:
4543
path: website/.vitepress/dist
4644

@@ -54,33 +52,7 @@ jobs:
5452
contents: read
5553
pages: write
5654
id-token: write
57-
actions: write
5855
steps:
59-
# Work around actions/upload-pages-artifact@v3 bug where transient
60-
# network hiccups during upload can produce >1 artifact named
61-
# "github-pages" in a single run, which then makes deploy-pages@v4
62-
# fail with "Multiple artifacts named 'github-pages'". Delete all
63-
# but the most recent before deploying.
64-
- name: Prune duplicate github-pages artifacts
65-
env:
66-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
67-
RUN_ID: ${{ github.run_id }}
68-
REPO: ${{ github.repository }}
69-
run: |
70-
set -euo pipefail
71-
artifacts=$(gh api "/repos/$REPO/actions/runs/$RUN_ID/artifacts" \
72-
--jq '[.artifacts[] | select(.name == "github-pages")] | sort_by(.created_at) | reverse')
73-
count=$(echo "$artifacts" | jq 'length')
74-
echo "Found $count github-pages artifact(s) in this run."
75-
if [ "$count" -le 1 ]; then
76-
exit 0
77-
fi
78-
# Keep index 0 (newest); delete the rest.
79-
echo "$artifacts" | jq -r '.[1:] | .[].id' | while read -r id; do
80-
echo "Deleting duplicate artifact $id"
81-
gh api -X DELETE "/repos/$REPO/actions/artifacts/$id"
82-
done
83-
8456
- name: Deploy to GitHub Pages
8557
id: deployment
86-
uses: actions/deploy-pages@v4
58+
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4

.github/workflows/issue-auto-response.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ concurrency:
88
group: issue-auto-response-${{ github.event.issue.number }}
99
cancel-in-progress: false
1010

11+
permissions:
12+
contents: read
13+
1114
jobs:
1215
auto-response:
1316
if: |
@@ -23,7 +26,7 @@ jobs:
2326
steps:
2427
- name: Check for existing bot response
2528
id: check_bot
26-
uses: actions/github-script@v7
29+
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
2730
with:
2831
script: |
2932
const marker = "*Open-CoDesign Bot*";
@@ -50,7 +53,7 @@ jobs:
5053

5154
- name: Checkout repository
5255
if: steps.check_bot.outputs.has_bot != 'true'
53-
uses: actions/checkout@v4
56+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
5457
with:
5558
fetch-depth: 0
5659

@@ -105,7 +108,7 @@ jobs:
105108

106109
- name: Run Codex for Issue Auto Response
107110
if: steps.check_bot.outputs.has_bot != 'true' && steps.issue_config.outputs.is_deepseek != 'true'
108-
uses: openai/codex-action@v1
111+
uses: openai/codex-action@e0fdf01220eb9a88167c4898839d273e3f2609d1 # v1
109112
env:
110113
GH_TOKEN: ${{ github.token }}
111114
GITHUB_TOKEN: ${{ github.token }}

.github/workflows/labeler.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
label:
1616
runs-on: ubuntu-latest
1717
steps:
18-
- uses: actions/labeler@v5
18+
- uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5
1919
with:
2020
repo-token: ${{ secrets.GITHUB_TOKEN }}
2121
sync-labels: true

.github/workflows/packaging-smoke.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ on:
3434
- '.github/workflows/release.yml'
3535
- '.github/workflows/release-macos-x64-native-check.yml'
3636

37+
permissions:
38+
contents: read
39+
3740
# Per-SHA group, no cancellation. Each commit gets an independent smoke
3841
# that always runs to completion (or fails loudly). Skipping the
3942
# cancel-in-progress saves us from the ci.yml bug where an unrelated
@@ -52,13 +55,13 @@ jobs:
5255
# and got killed with no useful diagnostic.
5356
timeout-minutes: 30
5457
steps:
55-
- uses: actions/checkout@v4
58+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
5659

5760
- name: Setup pnpm
58-
uses: pnpm/action-setup@v4
61+
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
5962

6063
- name: Setup Node
61-
uses: actions/setup-node@v4
64+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
6265
with:
6366
node-version-file: .nvmrc
6467
cache: pnpm

.github/workflows/release-macos-x64-native-check.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
env:
2929
CHECK_REF: ${{ github.event_name == 'push' && github.ref || inputs.ref }}
3030
steps:
31-
- uses: actions/checkout@v4
31+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
3232
with:
3333
ref: ${{ env.CHECK_REF }}
3434
fetch-depth: 0
@@ -37,7 +37,7 @@ jobs:
3737
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4
3838

3939
- name: Setup Node
40-
uses: actions/setup-node@v4
40+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
4141
with:
4242
node-version-file: .nvmrc
4343
cache: pnpm
@@ -82,7 +82,7 @@ jobs:
8282
exit 1
8383
8484
- name: Upload native x64 artifact
85-
uses: actions/upload-artifact@v4
85+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
8686
with:
8787
name: native-check-macos-x64
8888
path: apps/desktop/release/*.dmg

0 commit comments

Comments
 (0)