-
Notifications
You must be signed in to change notification settings - Fork 0
feat(lighthouse): add reusable lighthouse audit workflow #89
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 | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,68 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: lighthouse scan | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| workflow_call: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| inputs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| target_url: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: "url of the running application to audit" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| required: true | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| urls: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: "additional urls to audit as json array (e.g. '[\"https://example.com/about\"]')" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| default: "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| required: false | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| runner: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: "workflow-runner" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| default: "ubuntu-latest" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| required: false | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: string | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| outputs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| lighthouse_result: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: "lighthouse scan result" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: ${{ jobs.lighthouse.outputs.lighthouse_result }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| lighthouse: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: lighthouse audit | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ${{ inputs.runner }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| timeout-minutes: 15 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| permissions: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| contents: read | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| issues: write | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| outputs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| lighthouse_result: ${{ steps.audit.outcome }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| - uses: actions/checkout@v6 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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 🧩 Analysis chain🌐 Web query:
💡 Result: The latest release tag for actions/checkout v6 is v6.0.3 [1][2][3]. The commit SHA associated with the v6.0.3 tag is df4cb1c069e1874edd31b4311f1884172cec0e10 [4][5]. Citations:
🏁 Script executed: sed -n '1,160p' .github/workflows/lighthouse-scan.ymlRepository: tehw0lf/workflows Length of output: 2518 🏁 Script executed: python3 - <<'PY'
from pathlib import Path
p = Path('.github/workflows/lighthouse-scan.yml')
print(p.read_text())
PYRepository: tehw0lf/workflows Length of output: 2519 🏁 Script executed: awk 'NR>=1 && NR<=200 {print NR ":" $0}' .github/workflows/lighthouse-scan.ymlRepository: tehw0lf/workflows Length of output: 2713 Pin
🔒 Proposed fix- - uses: actions/checkout@v6
+ - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
+ with:
+ persist-credentials: false📝 Committable suggestion
Suggested change
🧰 Tools🪛 zizmor (1.26.1)[warning] 36-36: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false (artipacked) [error] 36-36: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: build urls list | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| id: urls | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| BASE_URL="${{ inputs.target_url }}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| EXTRA='${{ inputs.urls }}' | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -n "$EXTRA" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| URLS=$(echo "$EXTRA" | jq -c ". + [\"$BASE_URL\"]") | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| URLS="[\"$BASE_URL\"]" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "urls=$URLS" >> $GITHUB_OUTPUT | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+38
to
+48
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 | 🔴 Critical | ⚡ Quick win Code injection: pass inputs via
🔒 Proposed fix - name: build urls list
id: urls
+ env:
+ BASE_URL: ${{ inputs.target_url }}
+ EXTRA: ${{ inputs.urls }}
run: |
- BASE_URL="${{ inputs.target_url }}"
- EXTRA='${{ inputs.urls }}'
if [ -n "$EXTRA" ]; then
- URLS=$(echo "$EXTRA" | jq -c ". + [\"$BASE_URL\"]")
+ URLS=$(echo "$EXTRA" | jq -c --arg base "$BASE_URL" '. + [$base]')
else
- URLS="[\"$BASE_URL\"]"
+ URLS=$(jq -cn --arg base "$BASE_URL" '[$base]')
fi
echo "urls=$URLS" >> $GITHUB_OUTPUT📝 Committable suggestion
Suggested change
🧰 Tools🪛 zizmor (1.26.1)[error] 41-41: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) [error] 42-42: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: run lighthouse | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| id: audit | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| uses: treosh/lighthouse-ci-action@v12 | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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 🧩 Analysis chain🌐 Web query:
💡 Result: Latest release tag for treosh/lighthouse-ci-action v12 (as of 2026-06-24): 12.6.2 [1][2]. Commit SHA for tag 12.6.2: 3e7e23f8e4a1e7f1c9a9c8b8f6c9d8a7b6c5d4e3 (short SHA shown as 3e7e23f) [3]. Citations:
Pin
🔒 Proposed fix- uses: treosh/lighthouse-ci-action@v12
+ uses: treosh/lighthouse-ci-action@3e7e23f8e4a1e7f1c9a9c8b8f6c9d8a7b6c5d4e3 # v12.6.2📝 Committable suggestion
Suggested change
🧰 Tools🪛 zizmor (1.26.1)[error] 52-52: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| urls: ${{ steps.urls.outputs.urls }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| uploadArtifacts: true | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| temporaryPublicStorage: true | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: format report summary | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if: always() && steps.audit.outcome != 'skipped' | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "### 🔦 Lighthouse Audit Results" >> $GITHUB_STEP_SUMMARY | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "" >> $GITHUB_STEP_SUMMARY | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "| URL | Performance | Accessibility | Best Practices | SEO |" >> $GITHUB_STEP_SUMMARY | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "|-----|-------------|---------------|----------------|-----|" >> $GITHUB_STEP_SUMMARY | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo '${{ steps.audit.outputs.manifest }}' | jq -r '.[] | "| \(.url) | \(.summary.performance * 100 | round)% | \(.summary.accessibility * 100 | round)% | \(.summary["best-practices"] * 100 | round)% | \(.summary.seo * 100 | round)% |"' >> $GITHUB_STEP_SUMMARY || true | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "" >> $GITHUB_STEP_SUMMARY | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Full reports: ${{ steps.audit.outputs.links }}" >> $GITHUB_STEP_SUMMARY | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| continue-on-error: true | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+58
to
+68
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 | 🟡 Minor | ⚡ Quick win Move step outputs into
🔒 Proposed fix - name: format report summary
if: always() && steps.audit.outcome != 'skipped'
+ env:
+ MANIFEST: ${{ steps.audit.outputs.manifest }}
+ LINKS: ${{ steps.audit.outputs.links }}
run: |
echo "### 🔦 Lighthouse Audit Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| URL | Performance | Accessibility | Best Practices | SEO |" >> $GITHUB_STEP_SUMMARY
echo "|-----|-------------|---------------|----------------|-----|" >> $GITHUB_STEP_SUMMARY
- echo '${{ steps.audit.outputs.manifest }}' | jq -r '.[] | "| \(.url) | \(.summary.performance * 100 | round)% | \(.summary.accessibility * 100 | round)% | \(.summary["best-practices"] * 100 | round)% | \(.summary.seo * 100 | round)% |"' >> $GITHUB_STEP_SUMMARY || true
+ echo "$MANIFEST" | jq -r '.[] | "| \(.url) | \(.summary.performance * 100 | round)% | \(.summary.accessibility * 100 | round)% | \(.summary["best-practices"] * 100 | round)% | \(.summary.seo * 100 | round)% |"' >> $GITHUB_STEP_SUMMARY || true
echo "" >> $GITHUB_STEP_SUMMARY
- echo "Full reports: ${{ steps.audit.outputs.links }}" >> $GITHUB_STEP_SUMMARY
+ echo "Full reports: $LINKS" >> $GITHUB_STEP_SUMMARY
continue-on-error: true📝 Committable suggestion
Suggested change
🧰 Tools🪛 zizmor (1.26.1)[info] 65-65: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) [info] 67-67: code injection via template expansion (template-injection): may expand into attacker-controllable code (template-injection) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||||||||||||||||||||||||||||||||||||||||||||||||||||
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
Drop the unused
issues: writepermission.The job never creates or comments on issues (it only writes to
$GITHUB_STEP_SUMMARY), soissues: writeis an unnecessary privilege escalation. Reducing it tocontents: readkeeps the job at least-privilege.🔒 Proposed fix
permissions: contents: read - issues: writeAs per coding guidelines: "Apply minimal permissions principle to all workflow jobs - use
contents: readby default and only escalate permissions when needed".📝 Committable suggestion
🤖 Prompt for AI Agents
Sources: Coding guidelines, Linters/SAST tools