Generally yes, because static analysis reads source without executing it, while builds and tests run the contributor's code on your runner. Still, treat both as untrusted: run them with no secrets, a read-only token and a clean hosted runner, and do the cheap read-only checks first.
Definitions
Static analysis inspects source code, configuration or dependency manifests without running the program. Dynamic work such as builds, tests and install scripts executes code supplied by the contributor.
Why the difference matters
Executing code means the contributor's code controls the machine for the length of the job. Install hooks, test files, build scripts and Makefiles are all code. A scanner that parses files does not hand control to the contributor in the same way, though a scanner can still have its own bugs. Treat them as software that can have flaws too.
So even static tools should run in the same restricted setup.
A staged order of checks
| Stage | Check | Executes contributor code? |
|---|---|---|
| 1 | Diff review, CODEOWNERS paths | No |
| 2 | Dependency manifest review and advisory check | No |
| 3 | Static code analysis | No |
| 4 | Build and unit tests, no secrets | Yes |
| 5 | Integration tests with credentials, after approval | Yes |
Cheap, non executing checks come first. If they fail, you never need to run the rest. Many maintainers also want stage 4 to wait for approval on first time contributors, which GitHub supports for public repositories.
The restricted setup
- Trigger on pull_request, so a fork gets no secrets and a read-only token.
- Use GitHub-hosted runners. GitHub says self-hosted runners should almost never be used for public repositories.
- Set a short job timeout and limit network egress where you can.
- Do not restore caches from privileged jobs into untrusted ones.
- Upload results as artifacts and report in a separate trusted workflow.
Do not forget dependency install scripts
Even a "static" workflow often runs a package install first. That runs install hooks of every dependency. If you just need the manifest, parse the manifest rather than installing.
When dynamic testing is worth it
Tests prove behavior, and an outside contribution that breaks the build is something you need to know. The point is not to avoid running tests, but to run them where a bad test can just waste minutes.
Try it yourself
Click through it at your own pace, or open it full screen.
Look at how findings are reported from reading code, without running the application.
Where Safeguard fits
Safeguard offers dependency scanning, SBOM and policy gates on pull requests, and reachability analysis. Try the free scan first.
Quick check
Is a scanner immune to a malicious repository?
No. Tools can have bugs when parsing untrusted input, so run them in a restricted job as well.
Should tests run before approval for a first time contributor?
On public repositories GitHub can hold those runs for maintainer approval. Review the diff, then approve.
Sources
- Secure use reference, GitHub Docs
- Events that trigger workflows, GitHub Docs
- Approving workflow runs from forks, GitHub Docs
Last reviewed: 19 October 2026.