Skip to content

chore: add Dependency Guard workflow (alpha)#51

Open
gvago wants to merge 8 commits intomainfrom
feat/dependency-guard-alpha
Open

chore: add Dependency Guard workflow (alpha)#51
gvago wants to merge 8 commits intomainfrom
feat/dependency-guard-alpha

Conversation

@gvago
Copy link
Copy Markdown

@gvago gvago commented Apr 5, 2026

Adds supply-chain security scanning via qodo-ai/dependency-guard.

Fires on PRs that change lockfiles. Posts a verdict comment (SAFE / WARNING / MALICIOUS).

Setup required: Add QODO_API_KEY secret in repo settings before merging.

Alpha — GitHub only, comment-only (no merge blocking yet).

Adds supply-chain security scanning for dependency changes.
Scans package artifacts when lockfiles change in a PR.
Requires QODO_API_KEY secret — see repo settings.
@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Add Dependency Guard workflow for supply-chain security

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Adds Dependency Guard workflow for supply-chain security scanning
• Triggers on lockfile changes across multiple package managers
• Posts verdict comments (SAFE/WARNING/MALICIOUS) on PRs
• Requires QODO_API_KEY secret configuration in repository
Diagram
flowchart LR
  PR["Pull Request with<br/>lockfile changes"]
  TRIGGER["Dependency Guard<br/>workflow triggered"]
  SCAN["Scan package<br/>artifacts"]
  VERDICT["Post verdict<br/>comment"]
  PR -- "on: paths" --> TRIGGER
  TRIGGER -- "checkout code" --> SCAN
  SCAN -- "QODO_API_KEY" --> VERDICT
Loading

Grey Divider

File Changes

1. .github/workflows/dependency-guard.yml ✨ Enhancement +25/-0

New Dependency Guard security scanning workflow

• New GitHub Actions workflow for supply-chain security scanning
• Triggers on changes to lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt,
 poetry.lock, Pipfile.lock)
• Uses qodo-ai/dependency-guard@v1 action with QODO_API_KEY secret
• Configured with read contents and write pull-requests permissions

.github/workflows/dependency-guard.yml


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

qodo-free-for-open-source-projects Bot commented Apr 5, 2026

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX Issues (0)

Grey Divider


Action required

1. Unpinned action versions🐞 Bug ⛨ Security
Description
The workflow uses moving tags (actions/checkout@v4, qodo-ai/dependency-guard@v1), so the
executed CI code can change without review, creating a supply-chain risk and reducing
reproducibility.
Code

.github/workflows/dependency-guard.yml[R21-22]

+      - uses: actions/checkout@v4
+      - uses: qodo-ai/dependency-guard@v1
Evidence
The workflow references third-party actions by major-version tags, which are mutable and can be
retargeted to different commits over time. This contradicts the repo’s own security guidance to pin
versions for reproducible builds.

.github/workflows/dependency-guard.yml[21-22]
SECURITY.md[71-76]
Best Practice: GitHub Actions Security Hardening

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The workflow uses mutable action tags (`@v4`, `@v1`). This allows the code executed in CI to change without review and weakens supply-chain security.
## Issue Context
This repo’s SECURITY.md recommends pinning versions for reproducible builds. GitHub Actions security guidance also recommends pinning actions to full commit SHAs.
## Fix Focus Areas
- .github/workflows/dependency-guard.yml[21-24]
## Suggested change
- Replace `actions/checkout@v4` with a pinned commit SHA for the desired release.
- Replace `qodo-ai/dependency-guard@v1` with a pinned commit SHA for the desired release.
- (Optional) Add comments indicating the intended version (e.g., `# v4.x.x`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Fork PRs lack secret🐞 Bug ☼ Reliability
Description
This workflow runs on pull_request but unconditionally passes secrets.QODO_API_KEY; for PRs from
forks, the secret is not available, so the scan cannot authenticate and will not reliably post a
verdict comment.
Code

.github/workflows/dependency-guard.yml[R3-24]

+on:
+  pull_request:
+    paths:
+      - '**/package-lock.json'
+      - '**/yarn.lock'
+      - '**/pnpm-lock.yaml'
+      - '**/requirements.txt'
+      - '**/requirements*.txt'
+      - '**/poetry.lock'
+      - '**/Pipfile.lock'
+
+jobs:
+  scan:
+    runs-on: ubuntu-latest
+    permissions:
+      contents: read
+      pull-requests: write
+    steps:
+      - uses: actions/checkout@v4
+      - uses: qodo-ai/dependency-guard@v1
+        with:
+          qodo-api-key: ${{ secrets.QODO_API_KEY }}
Evidence
The trigger is pull_request and the job always passes secrets.QODO_API_KEY to the action. GitHub
Actions does not provide repository secrets to workflows triggered by forked PRs, so this workflow
won’t function as described for external contributors.

.github/workflows/dependency-guard.yml[3-5]
.github/workflows/dependency-guard.yml[22-24]
Best Practice: GitHub Actions documentation

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The workflow is triggered by `pull_request` and always attempts to run using `secrets.QODO_API_KEY`. On fork PRs, secrets are unavailable, so the workflow cannot authenticate and won’t deliver the intended SAFE/WARNING/MALICIOUS comment.
## Issue Context
If the goal is to cover open-source contributions, you need a safe fallback behavior for forks (skip with clear messaging), or a maintainer-triggered alternative.
## Fix Focus Areas
- .github/workflows/dependency-guard.yml[3-12]
- .github/workflows/dependency-guard.yml[20-24]
## Suggested change
Implement one of these patterns:
1) **Skip on forks / missing secret** (recommended for safety):
- Add a job/step `if: ${{ !github.event.pull_request.head.repo.fork && secrets.QODO_API_KEY != '' }}`.
- Add a fallback step that posts a neutral comment or step summary like "Dependency Guard skipped (fork PR / missing QODO_API_KEY)".
- Optionally add `continue-on-error: true` for alpha so it doesn’t create a failing check.
2) **Maintainer-triggered scan for forks**:
- Add `workflow_dispatch` with PR number input to allow maintainers to run the scan with secrets when needed.
Avoid switching to `pull_request_target` unless you are very careful to never execute untrusted PR code while secrets are available.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment thread .github/workflows/dependency-guard.yml Outdated
gvago added 7 commits April 5, 2026 20:15
- Pin actions/checkout to 11bd7190 (v4.2.2)
- Pin dependency-guard to 6b89a704 (v1.0.0-alpha.1)
- Add concurrency group to cancel stale runs on push
- Fail fast with clear error if QODO_API_KEY secret is missing
- Concurrency group now uses workflow name + PR number to avoid
  conflicts with other workflows on the same branch
- persist-credentials: false on checkout — GITHUB_TOKEN not
  stored in git config after the step completes
- Concurrency: use github.ref || github.run_id instead of PR number.
  github.event.pull_request.number is null for non-PR triggers;
  this form handles future trigger expansions safely.
- Checkout: pin to github.event.pull_request.head.sha (exact commit
  the developer pushed) rather than the default merge commit.
  Avoids merge-conflict lockfile artifacts causing false positives.
- fetch-depth: 0 — full history needed for git diff origin/main...HEAD
  three-dot merge-base computation. Shallow clone silently breaks the
  lockfile diff, causing detect-changes to return zero packages.
- timeout-minutes: 30 — prevents a hung LLM call from burning 6h of
  Actions minutes. Scan completes in <15 min under normal conditions.
- Reject: pr-number concurrency group (loses run_id fallback we added)
Three code review issues addressed:

1. Fork PRs under pull_request event have no access to repo secrets.
   Failing hard produces a permanent red check on external contributions.
   Fix: job-level if condition skips cleanly (shows as 'skipped').
   Condition covers both missing secret and fork PR cases.

2. Explicit check step removed — it was redundant once the job condition
   handles the missing-secret case. Also eliminates the underlying shell
   injection risk (secret interpolated into bash run script body).

3. requirements*.txt kept in paths — pip freeze output is a de facto
   lockfile in Python. Renamed to 'dependency files' in descriptions
   to be accurate rather than removing real-world coverage.
Finding 1 (red): pull_request withholds secrets from forks — valid
architectural concern, known limitation. All current repos are internal
qodo-ai with no fork PRs. Job condition already handles this correctly
(skips cleanly). workflow_run pattern is the proper fix for external-
facing repos; tracked for when alpha expands beyond internal repos.

Finding 2 (yellow): mutable tags — already fixed. SHAs pinned since
commit 6b89a70. Reviewer was looking at a stale version.
Replaces single pull_request workflow with a safe two-workflow pattern
that allows scanning fork PRs with access to secrets:

1. dependency-guard-prepare.yml (pull_request, no secrets)
   - Triggered on lockfile path changes from any source including forks
   - Saves PR metadata (number, head SHA, base ref, repo) as an artifact
   - Does NOT execute any fork code or analysis

2. dependency-guard.yml (workflow_run, has secrets)
   - Triggered when prepare workflow completes successfully
   - Runs in base repo context — QODO_API_KEY always available
   - Downloads artifact, fetches PR head via git ref
   - Runs scan against the PR's exact lockfile state
   - Posts verdict as a PR comment

Fork code is brought in via git fetch but never executed in the
privileged context — the action reads lockfiles and downloads packages
from public npm/PyPI registries only.

Resolves the red finding from code review.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant