SOC 2 Controls skill for Codex
Controls systems enforce, evidence that pulls itself. Codex maps engineering controls to the Trust Services Criteria, checks that GitHub rulesets, SSO, IAM and backups actually enforce what the policy promises, and writes scheduled exports that produce dated evidence for a Type I or Type II audit. It hunts the gaps auditors find, such as surviving leaver accounts and unreviewed merges, while leaving acceptance decisions to the auditor.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- soc2-controls Installs to ~/.agents/skills/soc2-controls/ for every project on this machine.
curl -fsSL codexskills.dev/cli.mjs -o codex-skills.mjsnode codex-skills.mjs install soc2-controls The CLI also searches, updates and removes skills. Run it with no arguments to pick from a list. Needs Node 20.12+.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- --project soc2-controls Installs to .agents/skills/soc2-controls/ in the current repository. Commit it and everyone who runs Codex there gets it.
curl -fsSLO codexskills.dev/downloads/soc2-controls.zipunzip -o soc2-controls.zip -d ~/.agents/skills/ The archive holds the skill folder with its generated agents/openai.yaml. Unzip into .agents/skills/ to scope it to a repo.
& ([scriptblock]::Create((irm codexskills.dev/install.ps1))) soc2-controls PowerShell 5.1 or 7. Installs to %USERPROFILE%\.agents\skills\. Add -Project for the current repo.
104-line POSIX script. No sudo, no telemetry. Read install.sh
Use it in Codex
Start a prompt with $soc2-controls, or pick it from /skills.
You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.
What Codex reads before loading it
Implements and evidences SOC 2 controls in engineering systems - access management, change management with branch protection and reviews, logging and monitoring, vulnerability management, backups, incident response and vendor reviews - mapped to the AICPA Trust Services Criteria (CC6, CC7, CC8, A1) and producing repeatable evidence from GitHub, cloud IAM and CI. Use when preparing for a SOC 2 Type I or Type II audit, answering auditor evidence requests, closing control gaps, or automating evidence collection for Vanta, Drata or a spreadsheet.
Use it when
- You are preparing for a first SOC 2 Type I or Type II audit
- An auditor sent an evidence request list for engineering
- Controls exist in policy but nobody can show they operate
- Evidence is gathered by screenshots every quarter
Use something else when
- You need GDPR rights handling or retention jobs: use gdpr-privacy-engineering
- You need a cloud misconfiguration scan rather than audit evidence: use cloud-security-posture
How to check the result
Each control's evidence query for the last full month runs unattended and shows zero unexplained exceptions, and a random sample of PRs, leavers and access grants traces cleanly end to end.
The mistake it prevents
Writing policies that promise controls no system enforces, then discovering the gap in the Type II sample instead of before the window.
Done well means: each control is something the systems enforce (not a promise in a policy document), it produces dated evidence without someone remembering to take screenshots, and the evidence matches what the policy says. The auditor (a licensed CPA firm) decides what satisfies a criterion; engineering makes the control real and the evidence easy to pull.
Orient first
- Ask for the scope: Type I (design at a point in time) or Type II (operating effectiveness over an observation window, typically 3-12 months); which Trust Services Criteria (Security is always in; Availability, Confidentiality, Processing Integrity, Privacy are optional); which systems are in the boundary.
- Read the existing policies and the control list (from the compliance platform or the auditor’s request list). Controls in policies that no system enforces are the main source of exceptions.
- Read
AGENTS.mdand find the real systems: Git host, CI, cloud accounts, identity provider, ticketing, on-call, logging.
Engineering control map
| Area | TSC | Control (enforced) | Evidence |
|---|---|---|---|
| Identity | CC6.1 | SSO via the IdP for GitHub, cloud console, CI, production tools; MFA enforced | IdP app list; org MFA/SSO setting export |
| Access provisioning | CC6.2, CC6.3 | Access granted by ticket with manager approval; removed within 24h of offboarding | Ticket samples; IdP deprovisioning logs |
| Access review | CC6.2, CC6.3 | Quarterly review of privileged and production access, changes actioned | Signed review export with removals |
| Least privilege | CC6.3 | No standing prod admin; break-glass with alerting | IAM policy export; break-glass alert config |
| Encryption | CC6.1, CC6.7 | TLS in transit; KMS at rest on DBs, buckets, backups | Config export / IaC |
| Change management | CC8.1 | Protected default branch, required review, required CI, no direct pushes | Ruleset export; PR samples |
| Vulnerability mgmt | CC7.1 | Dependency, container and cloud scanning with SLA by severity | Scanner reports; ticket ageing |
| Logging and monitoring | CC7.2 | Central logs, retention set, alerts routed to on-call | Retention config; alert rules; pager history |
| Incident response | CC7.3-CC7.5 | Documented IR process, tabletop or real incident per year, postmortems | IR doc; postmortem links |
| Backups and recovery | A1.2, A1.3 | Automated backups; restore tested at least annually | Backup policy; restore test record |
| Vendor management | CC9.2 | Critical vendors reviewed annually (their SOC 2 report, DPA) | Vendor list with review dates |
Remediation SLAs commonly used (confirm against the written policy): critical 7-15 days, high 30 days, medium 90 days. Whatever the policy says is what the auditor tests.
Change management in GitHub
Enforce with repository rulesets (org-level where possible) so the setting is uniform:
gh api repos/OWNER/REPO/rulesets --jq '.[] | {id, name, enforcement}'
gh api repos/OWNER/REPO/rulesets/RULESET_ID --jq '.rules[].type'
# expect: pull_request (required approvals >= 1, dismiss stale reviews),
# required_status_checks, non_fast_forward, deletion
gh api repos/OWNER/REPO/branches/main/protection 2>/dev/null # classic protection, if used
- Required approvals at least 1, from someone other than the author; dismiss stale approvals on new commits; require code owner review for infra and auth paths.
- Bypass list empty or limited to a break-glass role, and every bypass reviewed. An admin who can merge without review is a finding in every Type II sample.
- Infrastructure changes go through the same flow (Terraform in Git, applied by CI). Console changes in production break the control; detect them with drift detection or CloudTrail alerts.
- Changing org rulesets or IdP enforcement affects everyone; propose the change and apply it only after the user confirms.
Evidence collection that runs itself
Write small scripts that export evidence with dates, and run them on a schedule (CI cron) into a restricted bucket or the compliance platform. Prefer the compliance platform’s native integrations when they cover a control; script only the gaps.
# Sample of merged PRs with reviewers for the observation window
gh pr list --repo OWNER/REPO --state merged --search "merged:2026-07-01..2026-09-30" \
--limit 500 --json number,title,author,mergedAt,reviews,mergedBy \
> evidence/cc8.1/prs-2026Q3.json
# PRs merged without an approving review (should be empty or explained)
jq '[.[] | select(([.reviews[] | select(.state=="APPROVED")] | length) == 0)
| {number, title, author: .author.login, mergedBy: .mergedBy.login}]' \
evidence/cc8.1/prs-2026Q3.json
# Org members without 2FA (needs org admin token)
gh api "orgs/ORG/members?filter=2fa_disabled" --jq '.[].login'
# AWS: IAM users with console access and no MFA (read-only IAM permissions)
aws iam generate-credential-report >/dev/null; sleep 5
aws iam get-credential-report --query Content --output text | base64 --decode \
| awk -F, 'NR>1 && $4=="true" && $8=="false" {print $1}'
Evidence rules:
- Every artifact is dated, shows the system it came from, and covers the whole population or the auditor’s sample, not a hand-picked example.
- Keep evidence in a restricted location; exports contain names, emails and access lists.
- Screenshots only where no export exists, with the URL and clock visible.
Gaps that cause exceptions
- Offboarding removes the IdP account but a local GitHub, cloud IAM user or database user survives. Reconcile every system against HR’s leaver list monthly.
- Shared accounts or long-lived access keys for humans. Replace with SSO and roles.
- Emergency hotfix pushed directly to main with “will review later” and no later review. Policy should define the emergency path with retroactive review within a set time.
- Access reviews done but not actioned: the export shows a “remove” decision and the access still exists a month later.
- Restore test never performed; backups configured is not the same as recoverable.
- Policy promises (encryption of laptops, annual training, background checks) with no system or record behind them. Either implement or change the policy before the window.
Verification
- For each control, run its evidence query for the last full month and confirm the output shows the control operating with zero unexplained exceptions.
- Pick five random merged PRs, five leavers and five production access grants; trace each end to end as an auditor would.
- List remaining gaps with owner and date, and hand the control matrix to the compliance owner. Whether a gap is acceptable is the auditor’s judgement, not Codex’s.
Output template
| Control ID | TSC | Control | System enforcing | Evidence source | Frequency | Status | Owner |
|---|---|---|---|---|---|---|---|
| ENG-CM-01 | CC8.1 | Default branch requires 1 approval + CI | GitHub org ruleset "prod-default" | evidence/cc8.1/*.json | Quarterly export | Operating | @platform |
| ENG-AC-03 | CC6.2 | Leavers removed from AWS within 24h | IAM Identity Center via Okta SCIM | Okta deprovision log | Monthly reconciliation | Gap: 2 local IAM users | @infra, 2026-11-15 | What the zip contains
SKILL.md plus the interface file below. Nothing runs on install.
agents/openai.yaml
Gives the Codex app a display name, a one-line description and a starter prompt for this skill.
interface:
display_name: "SOC 2 Controls"
short_description: "Controls systems enforce, evidence that pulls itself"
default_prompt: "$soc2-controls Our SOC 2 Type II window starts next month - check our GitHub change management controls" About this skill
Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.