Introduction
Pull request review evidence shows, for each change in your audit sample, that someone other than the author reviewed and approved the code before it was merged and deployed.
In a SOC 2 Type 2 examination, auditors commonly test change management by selecting a sample of production changes from the audit period and checking each one. For engineering teams that work in GitHub, the pull request is usually where most of that evidence lives: who wrote the change, who approved it, when, and whether checks passed.
This guide focuses on per-change evidence: how to build the population, which attributes auditors tend to check on each pull request, how to export the records, and how to handle the edge cases that cause exceptions. For repository settings such as protected branches and rulesets, see GitHub Branch Protection Evidence for SOC 2. For the term itself, see What Is Pull Request Approval?.
In plain language: settings show the rule existed, and pull request records show the rule was followed for each change.
Where Pull Request Review Fits in SOC 2
The AICPA Trust Services Criteria include CC8.1, which addresses how changes to infrastructure, data, software, and procedures are authorized, designed, developed, tested, approved, and implemented. Code review before merge is one common way teams meet the approval and testing parts of that criterion. It also supports segregation of duties, because the author does not approve their own change.
SOC 2 does not require pull requests or GitHub. It requires that your described controls operate as described. If your system description says every production change is reviewed and approved by a second engineer, the auditor will test that statement. For the wider picture of how CC8.1 is tested, see CC8.1 Change Management Controls: What Auditors Test.
Settings Evidence vs Per-Change Evidence
| Evidence type | What it shows | Example |
|---|---|---|
| Settings evidence | The rule was configured | Ruleset requiring one approving review on the default branch |
| Per-change evidence | The rule was followed for a specific change | Pull request 1234 approved by a different engineer before merge |
| Population evidence | You know every change in the period | Export of all merged pull requests and default-branch commits |
Auditors often ask for all three. Strong settings reduce the chance of a failed sample, but they do not replace the sample itself.
Step 1: Build a Complete Change Population
Auditors select samples from a population, so the population has to be complete. See What Is an Audit Sample? for how sampling works.
A useful population usually includes, for each in-scope repository:
- Every pull request merged into the production branch during the audit period
- Pull request number, title, author, merged by, and merge date
- A link to the pull request
- A link to the related ticket, if your process requires one
Export the population from the system of record rather than building it by hand. With the GitHub CLI, for example, gh pr list --state merged --base main --search "merged:2026-01-01..2026-06-30" --json number,title,author,mergedAt,mergedBy,url --limit 1000 returns merged pull requests for a date range. Save the exact command or query with the export, because auditors may ask how the population was produced.
Check for changes that skipped pull requests
A list of merged pull requests only shows changes that went through pull requests. To test completeness, compare it with the commits on the production branch for the same period. The GitHub REST API can list pull requests associated with a commit, so commits with no associated pull request stand out. Investigate each one. Common causes are admin direct pushes, automated commits, or history imported before your process started.
Step 2: Agree on the Attributes Tested for Each Change
Before the audit, confirm with your auditor what they will check on each sampled pull request. Common attributes include:
- Independent approval. At least one approving review from someone other than the author.
- Approval before merge. The approving review was submitted before the merge time.
- Approval on the final code. No new commits were pushed after the approval without a fresh review, or stale approvals were dismissed.
- Required checks passed. Tests or other status checks were green at merge.
- Ticket linkage. The change links to a ticket or request, if your control requires it.
- Deployment traceability. The merged change can be tied to a deployment, if your control covers deployment.
Write these attributes down. Matching your evidence to the exact control wording avoids surprises.
Step 3: Export Evidence for Each Sampled Pull Request
For each sampled pull request, teams commonly provide:
- The pull request page or an export showing author, base branch, merge time, and merged by
- The review list, including reviewer, review state, and submitted time
- The commit the approval applied to, compared with the final merged commit
- Status check results at merge
- The linked ticket
The GitHub REST API returns reviews for a pull request with the reviewer, the state (such as APPROVED), the submitted time, and the commit ID the review applied to. Saving that JSON alongside the pull request record gives you dated, system-generated audit evidence instead of screenshots taken months later. See GitHub Docs for the current endpoint details.
If you use GitLab, merge request approvals provide similar records. The attributes stay the same even if the export differs.
Edge Cases That Cause Exceptions
Self-approval and shared accounts
An approval from the author, or from a shared account the author can use, does not show independent review. Use named accounts and require reviews from someone other than the last pusher where your platform supports it.
Approvals that went stale
If an author pushes new commits after approval and the approval was not dismissed or renewed, the approved code is not the merged code. Auditors may treat this as a failed sample if your control says the final change is reviewed.
Bot and dependency updates
Automated pull requests, such as dependency updates, still change production code. Decide how they are handled, document it in your control, and apply it consistently. Some teams require human approval for every bot pull request; others define a separate, documented path.
Emergency changes
If your process allows emergency merges without prior review, it should also require a documented after-the-fact review within a defined time. Keep that record with the change.
Merges by administrators
Admin bypass of review requirements should be rare, logged, and explained. Unexplained admin merges commonly become exceptions. Tie bypass rights to your user access review.
Common Gaps
- Populations built from memory or a spreadsheet instead of an export
- Repositories left out of the population
- Approvals given after merge
- Reviews by the author through a second account
- No record explaining direct pushes found during completeness testing
- Control descriptions that promise more review than the team performs
When a sampled change fails, handle it through exception management and remediation rather than hiding it.
A Practical Preparation Checklist
- List in-scope repositories and production branches.
- Confirm review requirements are enforced in settings for the whole period.
- Agree on tested attributes with your auditor.
- Export merged pull requests for the period and save the query.
- Compare against production branch commits and explain any direct pushes.
- Pull review records, checks, and tickets for each sampled item.
- Document how bot, emergency, and admin changes are handled.
How AuditFlo.co Helps
AuditFlo.co helps teams retain continuous evidence collection and audit-period history for operational artifacts when those records are stored or linked through connected systems and workflows your team already uses, such as GitHub and Jira.
For pull request review, that can mean dated change records are already organized when the auditor selects a sample. AuditFlo.co does not perform code review, does not select samples, does not issue SOC 2 reports, does not certify compliance, and does not replace auditors.
To see the workflow for your stack, request a demo.
Final Thoughts
Pull request review evidence is strongest when it is system-generated, complete, and tied to the exact wording of your control. Build the population from exports, check that nothing bypassed pull requests, and keep review records for every change so any sample can be answered quickly.
FAQ
Does SOC 2 require pull request reviews?
No. SOC 2 does not name pull requests. It expects changes to be authorized, tested, and approved as your controls describe. Pull request review is a common way engineering teams meet that expectation.
How many pull requests will the auditor sample?
It depends on your auditor's methodology, how often the control runs, and risk. Ask your auditor for planned sample sizes rather than relying on generic numbers.
Are screenshots of pull requests acceptable?
Some auditors accept them, but exports from the platform with timestamps and reviewer details are usually more complete and easier to verify.
What if we find a merged pull request with no approval?
Investigate it, document what happened, and handle it as an exception. Do not remove it from the population.
Do dependency update pull requests count as changes?
They change production code, so they are usually in the population. Define and document how they are reviewed.
Does AuditFlo.co change our GitHub settings?
No. AuditFlo.co helps retain and organize evidence from connected systems. Your team configures and enforces review requirements in GitHub.