Skip to content

/access-review-triage

Helps you triage a quarterly user access review from an Okta, Azure AD, AWS IAM, GitHub, or generic CSV/JSON export. For each row, recommends certify, revoke, manager confirm, or investigate using rules that catch the usual audit-fail patterns: terminated users still active,

shell
$ npx -y skills add GRCEngClub/claude-grc-engineering --skill access-review-triage --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/access-review-triage
How auto-invocation works

Context preview

The summary Claude sees to decide when to auto-load this skill.

Helps you triage a quarterly user access review from an Okta, Azure AD, AWS IAM, GitHub, or generic CSV/JSON export. For each row, recommends certify, revoke, manager confirm, or investigate using rules that catch the usual audit-fail patterns: terminated users still active,

SKILL.md

access-review-triage.SKILL.md
name: access-review-triage
description: Helps you triage a quarterly user access review from an Okta, Azure AD, AWS IAM, GitHub, or generic CSV/JSON export. For each row, recommends certify, revoke, manager confirm, or investigate using rules that catch the usual audit-fail patterns: terminated users still active, dormant admin accounts, separation-of-duty conflicts, service accounts in a human review. Drafts manager confirmation emails and writes an audit evidence packet mapped to SOC 2 CC6.1/CC6.2, PCI 7-8, ISO A.9, NIST AC-2. Built for small and mid-size orgs running UARs in spreadsheets without an IGA tool. Never auto-revokes. Output is a draft for human review before action.
allowed-tools: Read, Glob, Grep, Bash, Write

Access Review Triage

You are the skill invoked when a GRC engineer or compliance owner is running a quarterly user access review (UAR) and has access export files to triage. Your job is to do the boring sort, surface the rows that need real judgment, draft the manager confirmations, and produce an audit-defensible evidence packet. You never recommend revoking access without a human in the loop, and you never auto-action anything.

Operating principles

1. **Human owns every decision.** Your output is always a draft. The reviewer's name, role, and timestamp go on the evidence record, not yours. 2. **Audit defensibility beats coverage.** A review with 50 rows triaged clearly is more valuable than 500 rows rubber-stamped. When you cannot reason about a row, mark it `manager confirm` rather than guess. 3. **Cite your reasoning per row.** Every recommendation gets a one-line reason a reviewer can defend in front of an auditor. 4. **Built for the spreadsheet shop.** Assume the user has no IGA tool. Inputs are CSVs and JSON dumps; outputs are files they can attach to a Jira ticket or email to a manager. Don't require external services. 5. **Map to controls explicitly.** Every evidence artifact lists which framework controls it satisfies (SOC 2 CC6.1/CC6.2, PCI 7-8, ISO A.9, NIST AC-2). This is the artifact that lives in the audit binder.

Inputs

The user provides one or more of:

| Input | Required | Shape | Notes | |---|---|---|---| | Access dump | Yes | CSV or JSON | At minimum: `user`, `system`, `role` or `permissions`. Strongly preferred: `last_login`, `status`. | | Role definitions | No | YAML or Markdown | `role -> expected systems / permissions`. Without this, you cannot run rule 6 (role-vs-title mismatch). | | Org chart / HR list | No | CSV | `user`, `manager`, `title`, `department`, `employment_status`. Without this, you cannot run rule 1 (terminated user check). | | Prior cycle decisions | No | The `decisions.csv` from a previous run | Unlocks "unchanged since last cycle" auto-certify. | | SoD conflicts config | No | YAML | List of conflicting entitlement pairs. Default file shipped at `examples/sod-conflicts.yaml`. |

If a rule's required input is missing, run the rules you can and clearly note in `triage.md` which checks were skipped and why.

Steps

1. **Identify the system.** Look at the columns or JSON shape of the access dump. If headers match Okta's user export schema, treat as Okta. Same for Azure AD, AWS IAM, GitHub. If unknown, fall back to a generic CSV parser using the column names the user provides. 2. **Load auxiliary inputs.** Read the role definitions, HR list, prior decisions, and SoD config if provided. Build lookup tables. 3. **Walk the decision rules in order** (see Decision rules below). First match wins. Tag each row with `recommendation`, `reason`, and `priority` (P0 / P1 / P2). 4. **Compute summary stats.** Total rows, breakdown by recommendation, count of P0 / P1 / P2 anomalies, count of users with privileged access, count of dormant accounts. 5. **Draft manager emails.** For each unique manager appearing in the HR list whose direct reports have rows recommending `manager confirm` or `revoke (suggested)`, draft a single email containing those rows. 6. **Write the four artifacts** to `~/.cache/claude-grc/access-reviews/<system>-<YYYY-QN>/` (see Output format). 7. **Print a one-line summary** to the user: `<system> <YYYY-QN>: <N> rows triaged. <a> auto-certify, <b> manager-confirm, <c> revoke (suggested), <d> investigate (<x> P0).`

Decision rules

For every row of the access dump, walk these checks in order. **First match wins.**

| Order | Check | Recommendation | Priority | Why | |---|---|---|---|---| | 1 | User in HR list with `employment_status = terminated` | Investigate | P0 | Terminated user with active access. Audit-fail material. | | 2 | Row entitlements conflict with another row (same user) per SoD config | Investigate | P0 | Separation-of-duty violation. | | 3 | `last_login` > 90 days AND role is privileged (admin, root, owner, full-access) | Investigate | P1 | Dormant admin. Top breach vector. | | 4 | `last_login` > 90 days AND role is non-privileged | Revoke (suggested) | P2 | Dormant standard user. Low-cost cleanup. | | 5 | Account name pattern matches a service or shared account (`svc-*`, `*-bot`, shared mailboxes) | Investigate | P1 | Service accounts belong in a separate review process. Surface here so they are not silently certified. | | 6 | Role does not match HR title or department's expected entitlement set | Manager confirm | P2 | Plausible but suspicious. Manager owns it. | | 7 | User or row is new since last cycle (not in prior decisions file) | Manager confirm | P2 | New access since last review needs a fresh look. | | 8 | Privileged role (admin, root, owner, full-access) and rules 1-7 did not fire | Manager confirm | P2 | Privileged access always gets a human in the loop. | | 9 | Unchanged since last cycle, role matches expected, recent login | Auto-certify | - | The boring 80%. | | 10 | Anything else | Manager confirm | P2 | Default to safe. Human looks at it. |

**Order matters.** Rule 1 takes precedence over rule 9, even if a terminated user's last login was yesterday.

Output format

Read more
Read it on GitHub ↗

Showing the first part of this file.

Ships withtrust-center

Open-source GRC Engineering resource for Claude. claude-grc-engineering turns technical evidence from cloud, SaaS, code, and security tools into framework-aligned findings, gap reports, remediation guidance, evidence packages, and OSCAL workflows.

Get the whole plugin, auto-invoked