AI-generated code changes the speed of a pull request, but it does not change the trust level of the code. A workflow should treat every pull request as potentially untrusted until the code and its dependencies have passed the right checks.
Start with least privilege
Set a restrictive default and grant permissions to individual jobs only when they need them:
~~~yaml
permissions:
contents: read
jobs:
security:
permissions:
contents: read
security-events: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npx ship-safe@latest ci . --threshold 80 --sarif ship-safe.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ship-safe.sarif
~~~
The exact permissions depend on your workflow, but a broad 'write' token should never be the default for an AI review job.
Keep fork pull requests away from secrets
Do not expose deployment keys, package publish tokens, or cloud credentials to code from an untrusted fork. A workflow that checks out a pull request and then runs its scripts with secrets has made the pull request a credentialed execution environment.
Use separate jobs for untrusted tests and trusted publishing. Require an approval boundary before any job can access protected environments.
Pin third-party actions
A mutable tag can point to different code later. Pin security-sensitive third-party actions to a full commit SHA and review updates intentionally. GitHub recommends this as part of hardening Actions workflows. See GitHub's security guidance and its guidance on pinning third-party actions.
Put the scan before the merge decision
The most useful security gate runs against the same commit that is about to merge. Keep the output machine-readable and make the threshold explicit:
~~~bash
npx ship-safe@latest ci . --threshold 80 --sarif ship-safe.sarif
~~~
Use a higher bar for critical findings than for informational findings. Do not hide a failing result by truncating or replacing the report; CI consumers need a complete, valid artifact.
Add provenance to what you publish
Once the build is trusted, record where it came from and how it was produced. GitHub artifact attestations establish build provenance for artifacts such as binaries and container images. GitHub's artifact attestation documentation explains the workflow and verification model.
Attestation does not make unsafe source safe. It answers a different question: can a consumer verify which workflow and source produced this artifact?
A review checklist
- Default workflow permissions are read-only.
- Fork pull requests cannot read deployment or publish secrets.
- Actions are pinned and updated through review.
- Dependency and AI-agent scans run on the merge candidate.
- SARIF and JSON reports are preserved as build artifacts.
- Production publishing requires a protected environment.
- Published artifacts carry provenance when the release model supports it.
Ship Safe's PR Guardian workflow is designed for the point where a repository needs a repeatable security decision before risky code merges. Start with the CLI if you want a local check, then add the hosted workflow when the team needs history and ownership.
