The wrong default: remove the account first
In a two-to-fifteen engineer team, offboarding usually starts with the obvious action: disable the account. That is the wrong first move when the departing person’s identity is the only thing holding a pipeline together. The account is a human object. The pipeline depends on machine objects — deploy keys, CI/CD-scoped organization roles, cross-account trust policies, service-account impersonation grants — and several of those survive account removal entirely.
GitHub’s own repository-role documentation is explicit about one of them: when someone adds a deploy key to a repository, any user who has the private key can read from or write to the repository, depending on the key settings, even if they are later removed from the organization. Account removal is not credential removal. The offboarding sequence has to follow dependency direction, not calendar order.
This is a procedural argument, not a vendor recommendation. GitHub, GitLab, AWS, and Google Cloud document the mechanisms; none of them publish an offboarding order. The order below is a recommendation for lean teams, built from those mechanisms.
Step 0 — Inventory what the person’s identity is propping up
Before touching access, enumerate the objects that name the departing person or their personal credentials. In practice that means four lists:
- Deploy keys and personal tokens attached to repositories the pipeline deploys from or to.
- CI/CD-scoped organization roles. GitHub offers a predefined CI/CD admin role that grants admin access to manage Actions policies, runners, runner groups, hosted compute network configurations, secrets, variables, and usage metrics for an organization. If the departing person holds it, the pipeline’s secret store is in scope.
- Cross-account trust policies. An AWS cross-account IAM role includes a trust policy that allows principals in another account to assume it. If the trust policy names the person’s IAM user or a role only they can assume, revocation breaks the pipeline’s path into the target account.
- Service-account impersonation grants. In Google Cloud, a principal granted a role that allows service account impersonation can access everything the service account can access. The grant is on the person; the blast radius is the pipeline.
Write the list down. This inventory is the artifact that makes the rest of the sequence reversible.
Step 1 — Re-home machine credentials before revoking anything
Replace personal deploy keys and personal tokens with team-owned or pipeline-owned credentials. The replacement should be a key or token whose lifecycle is tied to the pipeline, not to a human account. Then confirm the pipeline runs green on the replacement before the original is revoked.
Two platform details matter here. First, GitHub’s deploy-key warning cuts both ways: a new team-owned deploy key is only as safe as its private-key custody, so store it where the pipeline reads it and nowhere else. Second, GitLab’s membership model distinguishes direct from inherited members. A direct project member can be removed from the project directly, but an inherited member from a parent group can only be removed from the parent group itself. If the departing person’s pipeline access comes through a group, re-homing means changing the group, not the project.
For a worked example, consider a hypothetical two-person team where the departing engineer’s personal SSH deploy key is the only write path into the deploy repository. The correct sequence is: generate a new deploy key owned by the pipeline, add it to the repository, run a deploy, confirm the deploy succeeded, then remove the old key. Removing the old key first would orphan the pipeline at the exact moment the team has the least capacity to fix it.
Step 2 — Re-point trust and impersonation
Trust policies and impersonation grants are the second class of object that outlives an account. AWS recommends scoping role trust to specific principals rather than :root, because referencing :root may allow more principals to assume the role than intended. That recommendation is a security control, but it also creates an offboarding dependency: if the trust policy names the departing person’s role, the pipeline loses its path the moment that role is deleted.
The fix is to re-point the trust policy at a role or group that will outlive the person — a pipeline service role, a team role, or a group whose membership is managed separately. AWS CodePipeline’s cross-account documentation describes the shape of this: a cross-account role with a trust relationship policy that allows the pipeline’s service role in one account to assume a role in the other. The trust names the service role, not a human.
Google Cloud has the same shape. If a user holds roles/iam.serviceAccountTokenCreator on a service account the pipeline uses, revoking the user’s access is correct, but only after the pipeline’s own identity has been granted the impersonation it needs. Google Cloud also warns against deleting service accounts that are still used by running instances. The same caution applies to any service account a pipeline depends on: delete the human grant, not the machine identity.
Step 3 — Downgrade human access before removing it
Handover work usually needs the departing person to answer questions, review a runbook, or confirm a credential location. Removing all access on day one makes that handover harder than it needs to be. The middle step is a downgrade: move the person from privileged roles to the least role that still lets handover proceed, then remove.
GitHub’s organization-role documentation is useful here. Organization owners have complete administrative access, and GitHub recommends limiting the role but keeping it assigned to no fewer than two people. If the departing person is one of two owners, the downgrade step is also an availability step: promote the second owner before demoting the first. A two-person team with a single owner is a structural single point of failure, and offboarding is the moment that failure becomes visible.
GitLab’s access-expiration feature offers a lighter version of the same control: a direct project member can be given an access expiration date, after which they can no longer access the project. That is a reasonable interim state for a handover window, provided the expiration is actually enforced and not extended indefinitely.
Step 4 — Revoke, then verify for surviving credentials
Only after the pipeline runs on team-owned credentials, trust policies name non-human principals, and the second owner exists should the account be removed. Then verify. Account removal does not touch several classes of object:
- Deploy keys remain valid for anyone holding the private key, per GitHub’s documentation.
- Forks and webhooks survive membership removal. GitLab advises verifying that a removed member has not forked the private repository or created webhooks, because existing forks continue to receive changes from the upstream project and webhooks continue to receive updates.
- Service-account keys are separate credentials. Google Cloud treats service account keys as a security risk if not managed correctly and recommends more secure alternatives where possible; if a key exists, its existence is independent of the human account that created it.
Verification is a checklist, not a feeling. For each object on the Step 0 inventory, confirm the object is either gone or re-homed. Then run a deploy and a rollback. A pipeline that deploys but cannot roll back is not verified.
Step 5 — Record the sequence as a runbook
The value of this sequence is that the next offboarding is a checklist rather than an archaeology project. Write it down in the same place the team keeps its recovery procedures. The Recovery Checklist Before You Need It is a useful model for the format: ordered steps, named owners, and a verification gate at each stage.
The runbook should record the dependency order explicitly — machine credentials first, trust and impersonation second, human access third, account removal last — and it should name the platform-specific objects that survive removal. That last part is what turns a generic offboarding checklist into something a lean team can actually execute at 6 p.m. on a Friday.
Why this order, and not another
The order follows dependency direction. A pipeline depends on machine credentials and trust relationships; a human account depends on nothing the pipeline needs. Revoking in the opposite order — human first, machine second — creates a window in which the pipeline is broken and the person who could explain why is already locked out.
The tradeoff is time. This sequence takes longer than disabling an account, and in a security incident the calculus changes: if the departure is adversarial, the human account comes first and the pipeline is treated as potentially compromised. For a routine departure, the dependency order is the safer default because it keeps production running while access is unwound.
Neither order is free. The point is to choose deliberately, write down which order applies to which situation, and rehearse the routine one before it is needed.
FAQ
Does removing someone from the GitHub organization revoke their deploy keys?
No. GitHub’s documentation states that anyone holding a deploy key’s private key can read from or write to the repository, even if they are later removed from the organization. Deploy keys must be enumerated and removed separately.
What happens to a GitLab member who was added through a parent group?
An inherited member can only be removed from the parent group itself, not from the project. Removing them from the project view will not work if their membership is inherited.
Can an AWS cross-account trust policy break when a person leaves?
Yes, if the trust policy names the person’s IAM user or a role only they can assume. AWS recommends scoping trust to specific principals rather than :root, which makes the named principal an offboarding dependency. Re-point the trust at a pipeline service role before removing the human principal.
Should we delete the service account a pipeline uses when the person who created it leaves?
No. Google Cloud warns against deleting service accounts that are still used by running instances, and the same logic applies to any service account a pipeline depends on. Revoke the human’s impersonation grant, not the machine identity.
How many organization owners should a small team have?
GitHub recommends limiting the owner role but keeping it assigned to no fewer than two people. For a two-person team, that means the second owner must be promoted before the first is demoted.