# A periodic access-review procedure is documented in the repo

- **Pattern:** `ab-002628` (`soc2-readiness.logical-access.access-review-procedure-documented`)
- **Severity:** info
- **Lifecycle:** active
- **Last modified:** 2026-07-03
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002628
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002628)

## Why it matters

SOC 2 CC6.3 requires that access to systems and data is modified or removed based on roles, and that access grants are periodically reviewed: an auditor's first request in the logical-access section is "show me your access-review procedure and its last output." This is an evidence-pointer check: it verifies committed evidence of the control (a doc naming who holds production and admin access, how often the grant list is reviewed, and who runs the review), which is exactly the artifact an auditor will ask for. It does not, and cannot, verify that reviews actually happen off-repo. AI-generated and vibe-coded apps almost never carry this artifact: coding assistants scaffold roles, RBAC middleware, and admin routes on request, but "write down our quarterly access-review ritual" is an organizational habit, not a code prompt, so the repo ships with admin surfaces and zero paper trail. Teams then discover the gap during audit readiness, when reconstructing months of undocumented review history is impossible and the Type II observation window has to restart. Committing the procedure now (even a half-page in `SECURITY.md`) is the cheapest control in the whole SOC 2 readiness set.

## Severity rationale

Info because the absence of a committed procedure doc creates audit-evidence friction, not a direct exploitable weakness: the underlying access controls are scored by separate checks, and this one only measures whether the review ritual is written down where an auditor can see it.

## Remediation

Commit an access-review section to `SECURITY.md` (or a dedicated `docs/security/access-review.md`) that names three things: scope (which systems and roles are reviewed, e.g. production database, Vercel team members, Supabase dashboard, admin-role users), cadence (e.g. quarterly), and owner (the role or person who runs the review and revokes stale grants). Example skeleton:

```markdown
## Access review
- Scope: production DB, hosting dashboard, admin-role app users, CI secrets
- Cadence: quarterly
- Owner: engineering lead; findings tracked as issues, stale grants revoked within 7 days
```

This is the committed evidence a SOC 2 auditor asks for under CC6.3; keeping it beside the code means it evolves with the roles it governs.

## Detection

- **ID:** `access-review-procedure-documented`
- **Severity:** `info`
- **What to look for:** This is an evidence-pointer check: it measures committed documentation of a periodic access review, not whether reviews happen. Search the repo's documentation surfaces: `SECURITY.md`, `.github/SECURITY.md`, `README.md`, `docs/**/*.md`, `ops/**/*.md`, `runbooks/**/*.md`, `compliance/**/*.md`, `policies/**/*.md` (same paths regardless of language; applies equally to Python and Go repos). Look for a section or file about access review: headings or filenames matching `access review`, `access-review`, `access_review`, `user access`, `entitlement review`, `least privilege review`. Separately, establish whether the project has an access surface worth reviewing: an admin role or multi-role model (role/enum fields like `role`, `is_admin` in `prisma/schema.prisma`, Supabase migrations, Django/SQLAlchemy models, Go structs), admin routes (`app/admin/*`, `pages/admin/*`, `/admin` handlers in Express/FastAPI/Gin), RBAC middleware, or team artifacts such as a `CODEOWNERS` file.
- **Pass criteria:** A committed doc contains an access-review section that names BOTH (a) a review cadence (a concrete recurring interval such as quarterly, monthly, or "every N weeks/months") AND (b) the scope of the review (which systems, dashboards, or roles are covered, e.g. production database access, hosting-platform team members, admin-role users). Naming who runs the review strengthens the evidence but is not required to pass.
- **Fail criteria:** The project has an admin-role surface or team artifacts, and no committed doc satisfies the pass criteria. Fail the sneaky variants too: a doc that mentions "access control" or "least privilege" but contains no review cadence; an access-review heading whose body is a TODO, "coming soon", or empty stub; a copied policy template with unfilled placeholders like `{FREQUENCY}` or `[COMPANY]` in the cadence or scope lines; a cadence with no scope, or a scope with no cadence; review prose that exists only inside commented-out markdown or a `.template` file that is not adopted.
- **Skip (N/A) when:** The app has no admin-role surface (no role/admin model fields, no admin routes, no RBAC middleware) AND no team artifacts (no `CODEOWNERS`, no multi-role model): a true solo toy with nothing to review. Quote: `"No admin-role surface and no team artifacts (no CODEOWNERS, no multi-role model); nothing in scope for an access review"`.
- **Before evaluating, quote:** On pass, quote the doc's file path plus the 1-3 lines naming the cadence and the scope. On fail, quote the evidence that an access surface exists (e.g. the `role` field in `prisma/schema.prisma`, the `app/admin/` route path, or the `CODEOWNERS` path) and name the doc locations searched. Never judge from a heading alone; the cadence and scope lines themselves must be excerpted.
- **Report even on pass:** `"Access-review procedure at <path>: cadence <cadence>, scope <scope summary>, owner <owner or 'not named'>"`.
- **Detail on fail:** `"Admin role in prisma/schema.prisma and CODEOWNERS present, but no committed evidence of an access-review procedure in SECURITY.md, docs/, ops/, or runbooks/. A review may happen off-repo; commit the procedure (cadence + scope) as auditor-ready evidence."` or `"docs/security.md has an 'Access review' heading but the section is a TODO stub with no cadence or scope; no committed evidence of an access-review procedure. Commit evidence of the actual ritual."`
- **Remediation:** Add an access-review section to `SECURITY.md` (or `docs/security/access-review.md`) naming scope (production DB, hosting dashboard, admin-role users, CI secrets), cadence (e.g. quarterly), and owner, with a line on how stale grants get revoked. Broader access-control enforcement (who can hit admin routes at all) is covered in depth by the `security-hardening` audit.

## External references

- soc2 CC6.3
- iso-27001 A.5.18
- nist AC-6(7)

Taxons: access-control, regulatory-conformance

HTML version: https://auditbuffet.com/patterns/ab-002628
