Filter the scan by changed paths: use your CI system's path filters or a list of changed files, run the scanner only on affected directories, and keep a scheduled full scan for everything else. This keeps pull request checks fast while shared dependencies still get covered.
Why scope the scan
A full scan of a large legacy monorepo can take long enough that developers start to avoid the check. Scoping the pull request scan to what changed brings it back to minutes. The cost is a risk of blind spots, which the steps below handle.
Option one: CI path filters
GitHub Actions workflows can use paths and paths-ignore filters on triggers. The documentation notes that if you define both branch filters and path filters, the workflow runs only when both are satisfied. That detail matters: a workflow limited to a branch and to a path will skip a pull request that matches only one.
A trigger scoped to one service directory looks like this:
on:
pull_request:
paths:
- "services/billing/**"
- "libs/shared-money/**"
This works well when each service has its own workflow file, but it multiplies files in a big repository.
Option two: compute the changed list
A single workflow can ask git what changed and pass directories to the scanner. Git's diff command can list only file names with its name-only option. Compare the pull request branch against the point where it diverged from the target branch, not against the tip of the target, or you will include other people's recent merges.
- Find the merge base of the target branch and the pull request head.
- List changed files between that base and the head.
- Map files to scan roots, for example the nearest directory holding a manifest.
- Run the scan for each root once, even if many files in it changed.
The blind spots
| Gap | How to close it |
|---|---|
| A shared library changes, but only its own directory is scanned | Map library changes to dependent services |
| A lockfile at the repository root changes | Treat as touching everything it covers |
| A new vulnerability is published for an unchanged package | Scheduled full scan, daily or weekly |
| Path filter misses a renamed directory | Review filters whenever directories move |
The last row is easy to overlook. A newly published advisory affects code that has not changed, so a pull request scan can never catch it. Pair scoped scans with a scheduled full run.
Set a rule for the root files
Define a short list of files that always trigger a full scan: root lockfiles, shared build configuration and the scanner policy itself. Document the list in the repository so people know why a small edit sometimes runs a long check.
Where Safeguard fits
Safeguard policies and gates can block a pull request on what the change introduces, and continuous monitoring covers newly published advisories on code that has not changed. Try the walkthrough below.
Try it yourself
Click through it at your own pace, or open it full screen.
Watch how a pull request gate reports only what the change introduces.
Quick check
Will scoped scans miss transitive dependencies?
Not if you scan the whole service directory that holds the manifest. The risk is mapping files to the wrong root, so test the mapping.
How often should the full scan run?
At least weekly, and daily if you can afford it, because advisories appear without any code change.
Sources
- GitHub Docs, workflow syntax for GitHub Actions
- Git documentation, git-diff
- Git documentation, git-merge-base
Last reviewed: 19 October 2026.