mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-23 16:36:23 +00:00
* ci: surface E2E screenshots in review comment * ci: mark completed review commits in past tense * ci: surface approved sensitive-file reviews * ci: link sensitive files to reviewed changes * ci: stage desktop E2E visual evidence Track screenshots newly introduced against main and package visual diffs for a trusted publisher. * fix(ci): pass E2E evidence output paths Supply the manifest and staging-directory arguments required by the screenshot status helper. * fix(ci): download the OSV SARIF artifact Match the artifact name and result filename emitted by the pinned upstream reusable workflow.
127 lines
5.2 KiB
YAML
127 lines
5.2 KiB
YAML
name: OSV-Scanner
|
|
|
|
# Scans lockfiles (uv.lock, package-lock.json) against the OSV vulnerability
|
|
# database. Runs on every PR/push (via the ci.yml orchestrator's workflow_call)
|
|
# and on a weekly schedule against main.
|
|
#
|
|
# This is detection-only — OSV-Scanner does NOT open PRs or modify pins.
|
|
# It reports known CVEs in currently-pinned dependency versions so we can
|
|
# decide when and how to patch on our own schedule. Our pinning strategy
|
|
# (full SHA / exact version) is preserved; only the notification signal
|
|
# is added.
|
|
#
|
|
# Complements the supply-chain-audit.yml workflow (which scans for malicious
|
|
# code patterns in PR diffs) by covering the orthogonal "currently-pinned
|
|
# dep became known-vulnerable" case.
|
|
#
|
|
# Uses Google's officially-recommended reusable workflow, pinned by SHA.
|
|
# Findings land in the repo's Security tab (Code Scanning > OSV-Scanner).
|
|
# fail-on-vuln is disabled so the job does not block merges on pre-existing
|
|
# vulnerabilities in pinned deps that we may need to patch deliberately.
|
|
#
|
|
# The reusable workflow can't emit custom outputs, so a wrapper job
|
|
# downloads the SARIF result and summarizes the vulnerability count into
|
|
# a review_status for the unified PR comment.
|
|
|
|
on:
|
|
workflow_call:
|
|
schedule:
|
|
# Weekly scan against main — catches CVEs published after merge for
|
|
# deps that haven't changed since.
|
|
- cron: '0 9 * * 1'
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
# Required to upload SARIF file to CodeQL. See: https://github.com/github/codeql-action/issues/2117
|
|
actions: read
|
|
contents: read
|
|
security-events: write
|
|
|
|
jobs:
|
|
scan:
|
|
name: Scan lockfiles
|
|
uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@9a498708959aeaef5ef730655706c5a1df1edbc2 # v2.3.8
|
|
with:
|
|
# Scan explicit lockfiles rather than recursing, so we only look at
|
|
# the three sources of truth and skip vendored / test / worktree dirs.
|
|
scan-args: |-
|
|
--lockfile=uv.lock
|
|
--lockfile=package-lock.json
|
|
--lockfile=website/package-lock.json
|
|
# The upstream reusable workflow uploads this exact file under its
|
|
# fixed artifact name, which the wrapper downloads below.
|
|
results-file-name: osv-results.sarif
|
|
fail-on-vuln: false
|
|
|
|
emit-status:
|
|
name: Emit review status
|
|
runs-on: ubuntu-latest
|
|
needs: scan
|
|
if: always()
|
|
outputs:
|
|
review_status: ${{ steps.emit.outputs.review_status }}
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- name: Download SARIF result
|
|
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
with:
|
|
name: OSV Scanner SARIF file
|
|
path: /tmp/osv-results
|
|
continue-on-error: true
|
|
|
|
- name: Emit review_status
|
|
id: emit
|
|
run: |
|
|
set -euo pipefail
|
|
STATUS="[]"
|
|
|
|
if [ -f /tmp/osv-results/osv-results.sarif ]; then
|
|
# Count vulnerabilities from the SARIF file
|
|
VULN_COUNT=$(python3 -c "
|
|
import json, sys
|
|
try:
|
|
with open('/tmp/osv-results/osv-results.sarif') as f:
|
|
data = json.load(f)
|
|
count = 0
|
|
vulns = []
|
|
for run in data.get('runs', []):
|
|
for result in run.get('results', []):
|
|
count += 1
|
|
rule_id = result.get('ruleId', 'unknown')
|
|
message = result.get('message', {}).get('text', '')
|
|
loc = result.get('locations', [{}])[0].get('physicalLocation', {}).get('artifactLocation', {}).get('uri', '')
|
|
vulns.append(f'- {rule_id} in {loc}: {message}')
|
|
print(count)
|
|
if vulns:
|
|
print('\n'.join(vulns[:20]), file=sys.stderr)
|
|
except Exception:
|
|
print(0)
|
|
")
|
|
|
|
VULN_DETAIL=""
|
|
if [ "$VULN_COUNT" -gt 0 ] 2>/dev/null; then
|
|
VULN_PLURAL=$([ "$VULN_COUNT" -eq 1 ] && echo "y" || echo "ies")
|
|
VULN_DETAIL=$(python3 -c "
|
|
import json, sys
|
|
try:
|
|
with open('/tmp/osv-results/osv-results.sarif') as f:
|
|
data = json.load(f)
|
|
vulns = []
|
|
for run in data.get('runs', []):
|
|
for result in run.get('results', []):
|
|
rule_id = result.get('ruleId', 'unknown')
|
|
loc = result.get('locations', [{}])[0].get('physicalLocation', {}).get('artifactLocation', {}).get('uri', '')
|
|
vulns.append(f'- {rule_id} in {loc}')
|
|
print(json.dumps('\n'.join(vulns[:20])))
|
|
except Exception:
|
|
print(json.dumps(''))
|
|
")
|
|
STATUS="[{\"source\":\"osv scan\",\"results\":[{\"kind\":\"warning\",\"title\":\"OSV vulnerability scan\",\"summary\":\"${VULN_COUNT} known vulnerabilit${VULN_PLURAL} found in pinned dependencies.\",\"detail\":${VULN_DETAIL},\"how_to_fix\":\"Review the findings in the [Security tab](../../security/code-scanning). Update the affected dependencies if a patched version is available.\"}]}]"
|
|
else
|
|
STATUS="[]"
|
|
fi
|
|
fi
|
|
|
|
echo "review_status=${STATUS}" >> "$GITHUB_OUTPUT"
|