{
  "generatedAt": "2026-10-12T16:01:05.493Z",
  "note": "Credentials with no scopes (keys), settings that decide what everything else may do (policies), access given outside roles (grants) and AI agents. Keys take the tier of what they act as; policies the tier of what changing them allows. related lists the permissions that change or use each one.",
  "items": [
    {
      "id": "ssh-key",
      "name": "SSH key on a user account",
      "kind": "key",
      "scope": "user",
      "tier": 1,
      "plane": "data",
      "contextDependent": true,
      "why": "Acts as the user's Git access, with no scopes to narrow it. That includes pushing changes to workflow files, which then run with the repository's secrets.",
      "summary": "An SSH key registered to the account authenticates git push, pull and clone over SSH without a web-based 2FA challenge.",
      "attackPath": "If an attacker obtains the private key (from an unencrypted disk or a leaked dotfile), they can push to every repository the account can write to, indefinitely, since SSH Git authentication is not gated by the session 2FA prompts the web UI uses.",
      "mitigations": [
        "Always set a passphrase on SSH private keys",
        "Rotate or revoke keys found on shared or unmanaged machines",
        "Use SSH certificates with a short validity where possible"
      ],
      "related": [
        "contents:write",
        "workflows:write",
        "keys:write"
      ],
      "docsUrl": "https://docs.github.com/en/authentication/connecting-to-github-with-ssh",
      "docsLabel": "GitHub Docs: Connecting to GitHub with SSH",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/authentication/connecting-to-github-with-ssh"
      },
      "detect": {
        "events": [
          "public_key.create",
          "public_key.update",
          "git.push"
        ],
        "match": "exact"
      }
    },
    {
      "id": "deploy-key",
      "name": "Deploy key with write access",
      "kind": "key",
      "scope": "repository",
      "tier": 1,
      "plane": "data",
      "why": "Pushes to its repository like Contents: write. A key carries no scopes, so nothing in it stops pushes to workflow files either, and it has no user, no 2FA and no expiry.",
      "summary": "An SSH key attached to one repository instead of a user. Read-only by default; write access is opt-in when the key is added.",
      "attackPath": "A write deploy key is a Git credential with no user, no 2FA and no expiry. It survives the departure of whoever created it and does not show up in member reviews. Stolen from a server or CI config, it pushes to that repository until someone deletes it.",
      "mitigations": [
        "Prefer read-only deploy keys, or a GitHub App with Contents: write",
        "Delete keys nobody can name an owner for",
        "Turn off deploy keys at the organization level if nothing needs them"
      ],
      "related": [
        "contents:write",
        "administration:write"
      ],
      "docsUrl": "https://docs.github.com/en/authentication/connecting-to-github-with-ssh/managing-deploy-keys",
      "docsLabel": "GitHub Docs: Managing deploy keys",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/authentication/connecting-to-github-with-ssh/managing-deploy-keys"
      },
      "detect": {
        "events": [
          "public_key.create",
          "public_key.update",
          "git.push"
        ],
        "match": "exact"
      }
    },
    {
      "id": "ssh-ca-key",
      "name": "SSH certificate authority private key",
      "kind": "key",
      "scope": "organization",
      "tier": 0,
      "plane": "control",
      "why": "Signs certificates for any member of the organization or enterprise that trusts it, so whoever holds it can push as anyone.",
      "summary": "An organization or enterprise can trust an SSH CA, so members use short-lived certificates instead of personal SSH keys. The CA's private key signs those certificates.",
      "attackPath": "Short-lived certificates are a good control, but the CA key behind them is now the credential to protect. Whoever holds it can sign a certificate for any member and push as them. It lives outside GitHub, in whatever system issues the certificates.",
      "mitigations": [
        "Keep the CA key in an HSM or a managed signing service",
        "Require an expiry on every certificate (upgrade legacy CAs that are exempt)"
      ],
      "related": [
        "contents:write"
      ],
      "docsUrl": "https://docs.github.com/en/organizations/managing-git-access-to-your-organizations-repositories/about-ssh-certificate-authorities",
      "docsLabel": "GitHub Docs: About SSH certificate authorities",
      "availability": {
        "on": [
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/organizations/managing-git-access-to-your-organizations-repositories/about-ssh-certificate-authorities"
      },
      "detect": {
        "events": [
          "ssh_certificate_authority.create",
          "ssh_certificate_requirement.disable"
        ],
        "match": "exact"
      }
    },
    {
      "id": "app-private-key",
      "name": "GitHub App private key (.pem)",
      "kind": "key",
      "scope": "app",
      "tier": 0,
      "plane": "control",
      "contextDependent": true,
      "why": "Mints installation tokens for every installation of the App, so it carries the strongest permission any installation was given. For an App with organization Administration or Members permissions that is Tier 0.",
      "summary": "The App's signing key, used to create JWTs and mint installation access tokens for every organization and repository where the App is installed.",
      "attackPath": "A leaked private key lets an attacker mint installation tokens for every installation of the App, instantly inheriting whatever permissions each installation granted. Since one App is often installed organization-wide, this is frequently the highest-leverage credential in an organization's supply chain.",
      "mitigations": [
        "Rotate keys regularly",
        "Store it in a secrets manager, never in a repository or CI logs",
        "Give the App the minimum permissions",
        "Install on selected repositories, not all"
      ],
      "related": [
        "installation_repositories:write"
      ],
      "docsUrl": "https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/managing-private-keys-for-github-apps",
      "docsLabel": "GitHub Docs: Managing private keys for GitHub Apps",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/managing-private-keys-for-github-apps"
      },
      "detect": {
        "events": [
          "integration.manager_added",
          "org.integration_manager_added",
          "integration.transfer"
        ],
        "match": "related"
      }
    },
    {
      "id": "webhook-secret",
      "name": "Webhook secret",
      "kind": "key",
      "scope": "app",
      "tier": 2,
      "plane": "data",
      "contextDependent": true,
      "why": "Grants nothing on GitHub. It lets someone forge events to the service that receives them, so its real tier is whatever that service does with an event, such as starting a deployment.",
      "summary": "The shared secret used to check that incoming webhook payloads really came from GitHub.",
      "attackPath": "A leaked webhook secret lets an attacker forge signed payloads to the receiving service, which may trigger deployment or automation logic with fake event data the attacker chose.",
      "mitigations": [
        "Rotate webhook secrets like any other credential",
        "Have receivers re-check state through the API instead of trusting payload contents"
      ],
      "related": [
        "repository_hooks:write",
        "organization_hooks:write"
      ],
      "docsUrl": "https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries",
      "docsLabel": "GitHub Docs: Validating webhook deliveries",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries"
      },
      "detect": {
        "events": [
          "hook.config_changed",
          "hook.create"
        ],
        "match": "exact"
      }
    },
    {
      "id": "gpg-key",
      "name": "GPG key for commit signing",
      "kind": "key",
      "scope": "user",
      "tier": 2,
      "plane": "data",
      "why": "The same tier as GPG keys: write. Grants no access on its own, but the private key makes commits and tags show as Verified for this user, which defeats a signed-commit rule as a control. Pushing still needs separate write access.",
      "summary": "Makes commits and tags signed with the matching private key show as Verified for the user.",
      "attackPath": "With the private key, or the ability to add a key to the account, an attacker signs commits as that user. Where a ruleset requires signed commits, or reviewers trust the Verified badge, forged commits pass as the user's own. Pushing them still needs write access from another credential.",
      "mitigations": [
        "Protect signing keys like other credentials when signed commits are required by a ruleset",
        "Remove signing keys from accounts that leave, and alert on new ones"
      ],
      "related": [
        "gpg_keys:write"
      ],
      "docsUrl": "https://docs.github.com/en/authentication/managing-commit-signature-verification",
      "docsLabel": "GitHub Docs: Managing commit signature verification",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/authentication/managing-commit-signature-verification"
      }
    },
    {
      "id": "ssh-signing-key",
      "name": "SSH key for commit signing",
      "kind": "key",
      "scope": "user",
      "tier": 2,
      "plane": "data",
      "why": "The same tier as SSH signing keys: write. Like a GPG key, it makes signed commits and tags show as Verified for this user, which defeats a signed-commit rule as a control. Pushing still needs separate write access.",
      "summary": "An SSH key added to the account as a signing key rather than an authentication key. Commits and tags signed with it show as Verified.",
      "attackPath": "An SSH key registered for signing does not authenticate Git, but it signs commits as the user. A stolen signing key, or one added to the account, makes forged commits pass a signed-commit rule.",
      "mitigations": [
        "Protect signing keys like other credentials when signed commits are required by a ruleset",
        "Remove signing keys from accounts that leave, and alert on new ones"
      ],
      "related": [
        "git_signing_ssh_public_keys:write"
      ],
      "docsUrl": "https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification",
      "docsLabel": "GitHub Docs: About commit signature verification",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification"
      }
    },
    {
      "id": "web-session",
      "name": "Web session cookie",
      "kind": "key",
      "scope": "user",
      "tier": 0,
      "plane": "control",
      "contextDependent": true,
      "why": "Acts as the signed-in account in the browser, with everything that account can do, including its settings. For an organization or enterprise owner that is Tier 0. It was issued after the password and 2FA, so a stolen cookie skips both.",
      "summary": "The cookie that keeps a person signed in to GitHub in the browser.",
      "attackPath": "Infostealer malware copies browser cookies. Replayed elsewhere, the session is already past the password and 2FA, and SSO for the organization may still be valid. The attacker can then create tokens, add SSH keys or change settings as that person.",
      "mitigations": [
        "Review and revoke sessions in the account's security settings after a suspected infection",
        "Keep owner accounts on managed devices, and use a separate account for day-to-day work",
        "Alert on new personal access tokens, SSH keys and OAuth grants for owner accounts"
      ],
      "related": [
        "administration:write",
        "organization_administration:write",
        "keys:write"
      ],
      "docsUrl": "https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/viewing-and-managing-your-sessions",
      "docsLabel": "GitHub Docs: Viewing and managing your sessions",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/viewing-and-managing-your-sessions"
      },
      "detect": {
        "events": [
          "org.sso_response",
          "business.sso_response",
          "business.revoke_sso_session"
        ],
        "match": "related"
      }
    },
    {
      "id": "runner-registration",
      "name": "Runner registration token or JIT configuration",
      "kind": "key",
      "scope": "organization",
      "tier": 1,
      "plane": "management",
      "why": "Registers a machine as a self-hosted runner. That machine then receives the jobs routed to its labels and the secrets those jobs get, so it is the same reach as Self-hosted runners: write.",
      "summary": "A short-lived credential (a registration token expires after one hour) or a just-in-time runner configuration, used to add a self-hosted runner to a repository or organization.",
      "attackPath": "A registration token or JIT configuration copied from a build log, a script or a provisioning pipeline lets an attacker register their own machine under the expected labels. Jobs then run on it, with their secrets and GITHUB_TOKEN, until someone notices the extra runner.",
      "mitigations": [
        "Create registration tokens just before use and never log them",
        "Use runner groups limited to the repositories that need them",
        "Alert on new self-hosted runners"
      ],
      "related": [
        "organization_self_hosted_runners:write",
        "administration:write"
      ],
      "docsUrl": "https://docs.github.com/en/rest/actions/self-hosted-runners",
      "docsLabel": "GitHub REST: Self-hosted runners",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/rest/actions/self-hosted-runners"
      },
      "detect": {
        "events": [
          "org.register_self_hosted_runner",
          "org.configure_self_hosted_jit_runner",
          "repo.register_self_hosted_runner",
          "enterprise.register_self_hosted_runner"
        ],
        "match": "exact"
      }
    },
    {
      "id": "app-client-secret",
      "name": "GitHub App or OAuth App client secret",
      "kind": "key",
      "scope": "app",
      "tier": 2,
      "plane": "data",
      "contextDependent": true,
      "why": "Not a credential on its own: it exchanges authorization codes and refresh tokens for user access tokens. Stolen together with stored refresh tokens, it turns them into live tokens for every user of the App, at those users' access.",
      "summary": "The secret an App uses with its client ID to get user access tokens and refresh them.",
      "attackPath": "Apps often keep the client secret next to the refresh tokens of their users. Whoever gets both can mint user access tokens for each of those users until the secret is rotated and the tokens revoked.",
      "mitigations": [
        "Keep client secrets and refresh tokens in a secrets manager, apart from each other",
        "Rotate the client secret when the App's servers are compromised"
      ],
      "related": [],
      "docsUrl": "https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/best-practices-for-creating-a-github-app",
      "docsLabel": "GitHub Docs: Best practices for creating a GitHub App",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/best-practices-for-creating-a-github-app"
      },
      "detect": {
        "events": [
          "oauth_application.generate_client_secret",
          "oauth_application.reset_secret",
          "integration.remove_client_secret"
        ],
        "match": "related"
      }
    },
    {
      "id": "codespaces-token",
      "name": "Codespaces token",
      "kind": "key",
      "scope": "repository",
      "tier": 2,
      "plane": "data",
      "contextDependent": true,
      "why": "Read and write on the codespace's repository when its owner has write access, plus any other repositories the codespace was authorized for. Data plane, and it expires on its own.",
      "summary": "The GitHub token a codespace gets each time it is created or restarted. Its scope follows the owner's access to the repository.",
      "attackPath": "Code running in a codespace, such as a malicious dependency or a dev container script, can read the token and push to the repository as the developer while it is valid.",
      "mitigations": [
        "Only authorize a codespace for the other repositories it needs",
        "Treat dev container configuration from untrusted branches as code that runs with this token"
      ],
      "related": [
        "contents:write",
        "codespaces:write"
      ],
      "docsUrl": "https://docs.github.com/en/codespaces/reference/security-in-github-codespaces",
      "docsLabel": "GitHub Docs: Security in GitHub Codespaces",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu"
        ],
        "source": "https://docs.github.com/en/codespaces/reference/security-in-github-codespaces"
      },
      "detect": {
        "events": [
          "codespaces.create",
          "codespaces.connect",
          "codespaces.allow_permissions"
        ],
        "match": "exact"
      }
    },
    {
      "id": "sso-recovery-codes",
      "name": "SSO recovery codes",
      "kind": "key",
      "scope": "enterprise",
      "tier": 0,
      "plane": "control",
      "why": "They let an owner reach the organization or enterprise when the identity provider is unavailable, so they bypass the IdP and its MFA and conditional access. A break-glass credential at the top of the tree.",
      "summary": "One-time codes an organization or enterprise owner downloads for signing in when the SAML or OIDC identity provider is down.",
      "attackPath": "Recovery codes are often saved once in a shared drive or a password manager entry nobody watches. With an owner's password and these codes, an attacker signs in without the IdP ever seeing it.",
      "mitigations": [
        "Store recovery codes offline or in a restricted password manager vault",
        "Alert on their use in the audit log, and regenerate them after use"
      ],
      "related": [
        "organization_administration:write"
      ],
      "docsUrl": "https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/managing-recovery-codes-for-your-enterprise/downloading-your-enterprise-accounts-single-sign-on-recovery-codes",
      "docsLabel": "GitHub Docs: Downloading your enterprise account's single sign-on recovery codes",
      "availability": {
        "on": [
          "enterprise-cloud",
          "emu"
        ],
        "notes": {
          "enterprise-cloud": "organization or enterprise SSO",
          "emu": "used by the setup user"
        },
        "source": "https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/managing-recovery-codes-for-your-enterprise/downloading-your-enterprise-accounts-single-sign-on-recovery-codes"
      },
      "detect": {
        "events": [
          "business.recovery_code_used",
          "org.recovery_code_used",
          "business.recovery_codes_downloaded",
          "org.recovery_codes_viewed"
        ],
        "match": "exact"
      }
    },
    {
      "id": "emu-setup-user",
      "name": "Enterprise Managed Users setup user",
      "kind": "key",
      "scope": "enterprise",
      "tier": 0,
      "plane": "control",
      "why": "The first enterprise owner and the only account in the enterprise that is not provisioned by SCIM. It signs in with a password, configures authentication and provisioning, and is the one that uses the recovery codes.",
      "summary": "The break-glass owner account of an Enterprise Managed Users enterprise, created with the enterprise.",
      "attackPath": "The setup user sits outside the IdP. If its password and 2FA, or the recovery codes, leak, an attacker owns the enterprise and can change authentication itself.",
      "mitigations": [
        "Keep the setup user's credentials in the company password manager with few people able to read them",
        "Require 2FA on it and alert on every sign-in"
      ],
      "related": [
        "enterprise_custom_enterprise_roles:write",
        "enterprise_scim:write"
      ],
      "docsUrl": "https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/understanding-iam-for-enterprises/getting-started-with-enterprise-managed-users",
      "docsLabel": "GitHub Docs: Getting started with Enterprise Managed Users",
      "availability": {
        "on": [
          "emu"
        ],
        "source": "https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/understanding-iam-for-enterprises/getting-started-with-enterprise-managed-users"
      },
      "detect": {
        "events": [
          "business.recovery_code_used",
          "business.update_saml_provider_settings",
          "business.disable_oidc"
        ],
        "match": "related"
      }
    },
    {
      "id": "management-console",
      "name": "Management Console access (Enterprise Server)",
      "kind": "key",
      "scope": "enterprise",
      "tier": 0,
      "plane": "control",
      "why": "Configures the whole GitHub Enterprise Server instance, including authentication. The root site administrator and Management Console users sit above every organization and enterprise role on the instance.",
      "summary": "Access to the Enterprise Server Management Console, held by the root site administrator and any Management Console users they create.",
      "attackPath": "Whoever signs in to the Management Console can change authentication for the instance, so every other control on it depends on this credential.",
      "mitigations": [
        "Limit Management Console users and keep the root site administrator's credentials offline",
        "Restrict network access to the Management Console"
      ],
      "related": [],
      "docsUrl": "https://docs.github.com/en/enterprise-server@latest/admin/administering-your-instance/administering-your-instance-from-the-web-ui/managing-access-to-the-management-console",
      "docsLabel": "GitHub Docs: Managing access to the Management Console",
      "availability": {
        "on": [
          "ghes"
        ],
        "source": "https://docs.github.com/en/enterprise-server@latest/admin/administering-your-instance/administering-your-instance-from-the-web-ui/managing-access-to-the-management-console"
      }
    },
    {
      "id": "ai-agent",
      "name": "Copilot cloud agent and other AI agents",
      "kind": "agent",
      "scope": "repository",
      "tier": 2,
      "plane": "data",
      "contextDependent": true,
      "why": "Opens pull requests and comments, which is data-plane write. Its real tier is the tokens, secrets and MCP tools it is given.",
      "summary": "An AI agent that takes an issue or prompt, works in its own environment and opens a pull request. It reads text that outsiders can write, and acts with the tools and MCP servers it is configured with.",
      "attackPath": "Its inputs are issues, comments and files, so prompt injection is the entry point. An agent with broad MCP tools or secrets in its environment can be talked into reading private data or pushing changes it was never asked for.",
      "mitigations": [
        "Keep its output behind normal review",
        "Treat the tokens and MCP servers it is given as grants to review like any other"
      ],
      "related": [
        "pull_requests:write",
        "issues:write",
        "organization_copilot_agent_settings:write"
      ],
      "docsUrl": "https://docs.github.com/en/copilot/concepts/agents/cloud-agent",
      "docsLabel": "GitHub Docs: Copilot cloud agent concepts",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu"
        ],
        "notes": {
          "free": "with a Copilot plan",
          "team": "with a Copilot plan",
          "emu": "organization repositories only"
        },
        "source": "https://docs.github.com/en/copilot/get-started/plans"
      },
      "detect": {
        "events": [
          "copilot.cfb_org_settings_changed",
          "mcp_registry.allowlist_add_server",
          "mcp_registry.settings_update"
        ],
        "match": "related"
      }
    },
    {
      "id": "ruleset-bypass",
      "name": "Ruleset bypass actor",
      "kind": "grant",
      "scope": "repository",
      "tier": 1,
      "plane": "management",
      "why": "Skips every rule the ruleset enforces: required reviews, signed commits, protected tags. That is control over what reaches production.",
      "summary": "A role, team or App on a ruleset's bypass list. It can push or merge past the rules that bind everyone else.",
      "attackPath": "Rulesets are where required reviews, signed commits and protected release tags live. Whoever is on the bypass list skips all of it, so a stolen bypass account or App token can force-push a default branch or move a release tag. Bypass entries are often added once for a release bot and never removed.",
      "mitigations": [
        "Keep bypass lists empty or limited to a break-glass team",
        "Prefer \"pull requests only\" bypass over \"always\""
      ],
      "related": [
        "administration:write",
        "organization_administration:write"
      ],
      "docsUrl": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/creating-rulesets-for-a-repository",
      "docsLabel": "GitHub Docs: Creating rulesets for a repository",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "notes": {
          "free": "public repositories only"
        },
        "source": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets"
      },
      "detect": {
        "events": [
          "repository_ruleset.update",
          "protected_branch.policy_override"
        ],
        "match": "exact"
      }
    },
    {
      "id": "environment-reviewer",
      "name": "Environment required reviewer",
      "kind": "grant",
      "scope": "repository",
      "tier": 2,
      "plane": "data",
      "contextDependent": true,
      "why": "Approving a deployment releases the environment's secrets to the job. On a production environment that is a Tier 1 decision.",
      "summary": "A person or team who must approve a job before it can deploy to an environment such as production.",
      "attackPath": "The approval is what releases the environment's secrets to the job. A compromised reviewer, or a reviewer list that includes the person who wrote the change, turns the gate into a formality. On Free, Pro and Team plans required reviewers only work on public repositories.",
      "mitigations": [
        "Turn on \"Prevent self-review\"",
        "Use a reviewer team separate from the authors"
      ],
      "related": [
        "deployments:write",
        "environments:write"
      ],
      "docsUrl": "https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments",
      "docsLabel": "GitHub Docs: Managing environments for deployment",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "notes": {
          "free": "public repositories only",
          "team": "public repositories only"
        },
        "source": "https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments"
      },
      "detect": {
        "events": [
          "environment.update_protection_rule",
          "environment.add_protection_rule",
          "workflows.approve_workflow_job"
        ],
        "match": "exact"
      }
    },
    {
      "id": "codeowners",
      "name": "Code owner (CODEOWNERS entry)",
      "kind": "grant",
      "scope": "repository",
      "tier": 2,
      "plane": "data",
      "contextDependent": true,
      "why": "A code owner's approval satisfies review for their paths. Whoever can edit CODEOWNERS on the protected branch chooses who approves.",
      "summary": "A person or team named in CODEOWNERS whose review is required for the paths they own, when the branch requires code owner review.",
      "attackPath": "Code owner approval is a grant written in a file. Anyone who can change CODEOWNERS on the protected branch decides who may approve, so the file needs its own owner. A wildcard entry that names a large team makes any member's approval enough.",
      "mitigations": [
        "Make CODEOWNERS itself owned by a small security or platform team",
        "Cover .github/workflows/ with a specific owner"
      ],
      "related": [
        "contents:write",
        "pull_requests:write"
      ],
      "docsUrl": "https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners",
      "docsLabel": "GitHub Docs: About code owners",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "notes": {
          "free": "public repositories only"
        },
        "source": "https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners"
      },
      "detect": {
        "events": [
          "protected_branch.update_require_code_owner_review",
          "git.push"
        ],
        "match": "related"
      }
    },
    {
      "id": "outside-collaborator",
      "name": "Outside collaborator",
      "kind": "grant",
      "scope": "repository",
      "tier": 1,
      "plane": "management",
      "contextDependent": true,
      "why": "Takes the tier of the repository role it is given, up to Admin. It lives outside the identity provider: GitHub does not require SSO for outside collaborators, so removing someone in the IdP, or SCIM, never touches this access.",
      "summary": "A person who is not a member of the organization but has a role on one or more of its repositories.",
      "attackPath": "An outside collaborator account is a personal account the organization does not manage. It keeps its repository roles through IdP offboarding and is not covered by SSO, so a contractor who left, or a compromised personal account, keeps Write or Admin until someone removes it by hand. Adding one is also a quiet way to keep access after an incident.",
      "mitigations": [
        "Only let organization owners invite outside collaborators",
        "Give each outside collaborator an internal sponsor and an end date, and review them with members",
        "Alert on new outside collaborators"
      ],
      "related": [
        "administration:write",
        "members:write"
      ],
      "docsUrl": "https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-saml-single-sign-on-for-your-organization/about-identity-and-access-management-with-saml-single-sign-on",
      "docsLabel": "GitHub Docs: About identity and access management with SAML single sign-on",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "ghes"
        ],
        "source": "https://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/managing-outside-collaborators/adding-outside-collaborators-to-repositories-in-your-organization"
      },
      "detect": {
        "events": [
          "org.add_outside_collaborator",
          "repository_invitation.create",
          "repo.add_member"
        ],
        "match": "exact"
      }
    },
    {
      "id": "enterprise-saml-sso",
      "name": "Enterprise SAML SSO enforcement",
      "kind": "policy",
      "scope": "enterprise",
      "tier": 0,
      "plane": "control",
      "why": "Decides whether the identity provider is the gate for every organization. Switching it off is a change to identity for the whole enterprise.",
      "summary": "Enforces, configures or disables SAML single sign-on across every organization in the enterprise.",
      "attackPath": "Disabling enterprise-wide SSO enforcement removes the IdP as the single control point for every organization at once, so stale or stolen GitHub credentials work without the IdP's MFA and conditional access.",
      "mitigations": [
        "Alert on any change to SSO configuration",
        "Keep the enterprise owners who can change it to a minimum"
      ],
      "related": [],
      "docsUrl": "https://docs.github.com/en/enterprise-cloud@latest/admin/identity-and-access-management/using-saml-for-enterprise-iam/about-identity-and-access-management-for-your-enterprise",
      "docsLabel": "GitHub Docs: About identity and access management for your enterprise",
      "availability": {
        "on": [
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "notes": {
          "emu": "SAML or OIDC, required",
          "ghes": "SAML for the whole instance"
        },
        "source": "https://docs.github.com/en/enterprise-cloud@latest/admin/identity-and-access-management/using-saml-for-enterprise-iam/about-identity-and-access-management-for-your-enterprise"
      },
      "detect": {
        "events": [
          "business.disable_saml",
          "business.update_saml_provider_settings",
          "business.enable_saml",
          "business.disable_oidc"
        ],
        "match": "exact"
      }
    },
    {
      "id": "enterprise-emu-provisioning",
      "name": "Enterprise Managed Users provisioning (SCIM)",
      "kind": "policy",
      "scope": "enterprise",
      "tier": 0,
      "plane": "control",
      "why": "Creates and removes the identities themselves, with their team memberships. That is who exists in the enterprise.",
      "summary": "Controls creation, deprovisioning and attribute mapping of Enterprise Managed User identities through SCIM.",
      "attackPath": "An attacker with this access can provision a new managed identity with chosen attributes and team memberships, minting a trusted user from nothing inside the enterprise's identity system.",
      "mitigations": [
        "Protect the SCIM token like an owner credential",
        "Review provisioning events in the audit log"
      ],
      "related": [
        "enterprise_scim:write"
      ],
      "docsUrl": "https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/provisioning-user-accounts-with-scim/configuring-scim-provisioning-for-users",
      "docsLabel": "GitHub Docs: Configuring SCIM provisioning for Enterprise Managed Users",
      "availability": {
        "on": [
          "emu",
          "ghes"
        ],
        "notes": {
          "ghes": "SCIM provisioning for an instance that uses SAML; managed users are Enterprise Cloud only"
        },
        "source": "https://docs.github.com/en/enterprise-server@latest/admin/managing-iam/provisioning-user-accounts-with-scim/configuring-scim-provisioning-for-users"
      },
      "detect": {
        "events": [
          "external_identity.provision",
          "external_identity.deprovision",
          "business.disable_open_scim",
          "external_group.add_member"
        ],
        "match": "exact"
      }
    },
    {
      "id": "organization-saml-sso",
      "name": "Organization SAML SSO enforcement",
      "kind": "policy",
      "scope": "organization",
      "tier": 0,
      "plane": "control",
      "why": "Decides whether the identity provider is the gate for the organization. Switching it off is a change to identity.",
      "summary": "Enables, disables or reconfigures SAML single sign-on enforcement for the organization.",
      "attackPath": "Disabling SSO enforcement removes the organization's central identity control point, letting compromised or stale credentials authenticate without the IdP's own MFA and conditional access policies.",
      "mitigations": [
        "Alert on any change to SSO configuration"
      ],
      "related": [],
      "docsUrl": "https://docs.github.com/en/organizations/managing-saml-single-sign-on-for-your-organization",
      "docsLabel": "GitHub Docs: Managing SAML SSO for your organization",
      "availability": {
        "on": [
          "enterprise-cloud"
        ],
        "source": "https://docs.github.com/en/enterprise-cloud@latest/admin/concepts/identity-and-access-management/identity-and-access-management-fundamentals"
      },
      "detect": {
        "events": [
          "org.disable_saml",
          "org.update_saml_provider_settings",
          "org.enable_saml"
        ],
        "match": "exact"
      }
    },
    {
      "id": "enterprise-audit-log-streaming",
      "name": "Audit log streaming",
      "kind": "policy",
      "scope": "enterprise",
      "tier": 1,
      "plane": "management",
      "why": "Grants no access, but switching it off or redirecting it hides everything that follows from the security team.",
      "summary": "Configures where enterprise audit log events are streamed, such as a SIEM, and can turn streaming off.",
      "attackPath": "An attacker who disables or redirects audit log streaming can operate afterwards without their actions reaching the security team's monitoring pipeline, a classic anti-forensics move.",
      "mitigations": [
        "Alert separately, for example through a redundant export, whenever streaming settings change"
      ],
      "related": [],
      "docsUrl": "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/streaming-the-audit-log-for-your-enterprise",
      "docsLabel": "GitHub Docs: Streaming the audit log for your enterprise",
      "availability": {
        "on": [
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/streaming-the-audit-log-for-your-enterprise"
      },
      "detect": {
        "events": [
          "audit_log_streaming.destroy",
          "audit_log_streaming.update",
          "audit_log_streaming.create"
        ],
        "match": "exact"
      }
    },
    {
      "id": "enterprise-2fa-enforcement",
      "name": "Enterprise 2FA requirement",
      "kind": "policy",
      "scope": "enterprise",
      "tier": 1,
      "plane": "management",
      "why": "Grants nothing directly, but switching it off reopens every organization to password-only account takeover.",
      "summary": "Controls whether two-factor authentication is required for every member across every organization in the enterprise.",
      "attackPath": "Disabling this requirement reopens every organization in the enterprise to password-only account takeover, undoing a control that otherwise covers the whole enterprise.",
      "mitigations": [
        "Require 2FA, and prefer passkeys or security keys"
      ],
      "related": [],
      "docsUrl": "https://docs.github.com/en/enterprise-cloud@latest/admin/enforcing-policies/enforcing-policies-for-your-enterprise/enforcing-policies-for-security-settings-in-your-enterprise",
      "docsLabel": "GitHub Docs: Enforcing policies for security settings in your enterprise",
      "availability": {
        "on": [
          "enterprise-cloud",
          "ghes"
        ],
        "notes": {
          "ghes": "with built-in or LDAP authentication"
        },
        "source": "https://docs.github.com/en/enterprise-cloud@latest/admin/enforcing-policies/enforcing-policies-for-your-enterprise/enforcing-policies-for-security-settings-in-your-enterprise"
      },
      "detect": {
        "events": [
          "business.disable_two_factor_requirement",
          "business.remove_disallowed_two_factor_method",
          "business.clear_disallowed_two_factor_methods"
        ],
        "match": "exact"
      }
    },
    {
      "id": "enterprise-ip-allow-list",
      "name": "IP allow list",
      "kind": "policy",
      "scope": "enterprise",
      "tier": 1,
      "plane": "management",
      "why": "Grants nothing directly, but adding a range removes the network barrier for stolen credentials used from it.",
      "summary": "Manages the IP ranges allowed to reach the enterprise's organizations.",
      "attackPath": "Adding an attacker-controlled IP range to the allow list removes a network barrier that would otherwise block credential-based access from outside the corporate network.",
      "mitigations": [
        "Alert on changes to the allow list"
      ],
      "related": [
        "organization_administration:write"
      ],
      "docsUrl": "https://docs.github.com/en/enterprise-cloud@latest/admin/configuring-settings/hardening-security-for-your-enterprise/restricting-network-traffic-to-your-enterprise-with-an-ip-allow-list",
      "docsLabel": "GitHub Docs: Restricting network traffic to your enterprise with an IP allow list",
      "availability": {
        "on": [
          "enterprise-cloud",
          "emu"
        ],
        "source": "https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/managing-allowed-ip-addresses-for-your-organization"
      },
      "detect": {
        "events": [
          "ip_allow_list_entry.create",
          "ip_allow_list_entry.update",
          "ip_allow_list.disable",
          "ip_allow_list.disable_for_installed_apps"
        ],
        "match": "exact"
      }
    },
    {
      "id": "enterprise-organization-creation",
      "name": "Organization creation and deletion policy",
      "kind": "policy",
      "scope": "enterprise",
      "tier": 1,
      "plane": "management",
      "why": "Decides who can create or delete organizations inside the enterprise, including unmonitored ones.",
      "summary": "Controls whether, and by whom, organizations can be created or deleted within the enterprise.",
      "attackPath": "An attacker can create a new, unmonitored organization inside the trusted enterprise to stage malicious repositories or Apps, or delete a legitimate organization outright.",
      "mitigations": [
        "Restrict organization creation to enterprise owners"
      ],
      "related": [],
      "docsUrl": "https://docs.github.com/en/enterprise-server@latest/admin/managing-accounts-and-repositories/managing-organizations-in-your-enterprise/preventing-users-from-creating-organizations",
      "docsLabel": "GitHub Docs: Preventing users from creating organizations",
      "availability": {
        "on": [
          "ghes"
        ],
        "source": "https://docs.github.com/en/enterprise-server@latest/admin/managing-accounts-and-repositories/managing-organizations-in-your-enterprise/preventing-users-from-creating-organizations"
      },
      "detect": {
        "events": [
          "org.create",
          "business.add_organization",
          "org.delete",
          "business.remove_organization"
        ],
        "match": "related"
      }
    },
    {
      "id": "organization-base-permission",
      "name": "Base permission: Write or Admin on every repository",
      "kind": "policy",
      "scope": "organization",
      "tier": 0,
      "plane": "control",
      "contextDependent": true,
      "why": "Set to Admin, every member becomes admin on every repository, the same as giving everyone All-repository admin. Set to Write, everyone can change workflows and read secrets everywhere, the same as All-repository write.",
      "summary": "The organization's base permission: the repository role every member gets on every repository by default.",
      "attackPath": "A single setting quietly gives the whole membership write or admin on every repository, including production. It is a common, easy-to-miss misconfiguration.",
      "mitigations": [
        "Set the base permission to Read or None",
        "Grant more per repository or per team instead"
      ],
      "related": [
        "organization_administration:write"
      ],
      "docsUrl": "https://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/managing-repository-roles/setting-base-permissions-for-an-organization",
      "docsLabel": "GitHub Docs: Setting base permissions for an organization",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/managing-repository-roles/setting-base-permissions-for-an-organization"
      },
      "detect": {
        "events": [
          "org.update_default_repository_permission",
          "business.update_default_repository_permission",
          "business.clear_default_repository_permission"
        ],
        "match": "exact"
      }
    },
    {
      "id": "organization-actions-policy",
      "name": "Organization Actions policy",
      "kind": "policy",
      "scope": "organization",
      "tier": 1,
      "plane": "management",
      "why": "Decides which actions may run, what GITHUB_TOKEN gets by default and which repositories can use runner groups, for every repository at once.",
      "summary": "Org-wide Actions settings: allowed actions and workflows, default GITHUB_TOKEN permissions, SHA pinning, fork pull request rules and runner group access.",
      "attackPath": "Loosening this policy, for example allowing every Marketplace action or raising the default GITHUB_TOKEN permission to read and write, widens the CI/CD attack surface for every repository in the organization at once.",
      "mitigations": [
        "Require SHA pinning and allow only selected actions",
        "Keep the default GITHUB_TOKEN permission read-only"
      ],
      "related": [
        "organization_administration:write"
      ],
      "docsUrl": "https://docs.github.com/en/organizations/managing-organization-settings/disabling-or-limiting-github-actions-for-your-organization",
      "docsLabel": "GitHub Docs: Disabling or limiting GitHub Actions for your organization",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/organizations/managing-organization-settings/disabling-or-limiting-github-actions-for-your-organization"
      },
      "detect": {
        "events": [
          "org.update_actions_settings",
          "org.set_default_workflow_permissions",
          "org.runner_group_updated",
          "business.update_actions_settings"
        ],
        "match": "exact"
      }
    },
    {
      "id": "environment-protection-rules",
      "name": "Environment protection rules",
      "kind": "policy",
      "scope": "repository",
      "tier": 1,
      "plane": "management",
      "why": "Decides who must approve a deployment and from which branches, which is the gate in front of production secrets.",
      "summary": "Required reviewers, wait timers and deployment branch policies for a repository's deployment environments.",
      "attackPath": "Removing required reviewers or loosening the deployment branch policy on a production environment lets an attacker's branch deploy straight to production without a second set of eyes.",
      "mitigations": [
        "Restrict deployments to protected branches",
        "Alert on changes to production environments"
      ],
      "related": [
        "administration:write",
        "environments:write"
      ],
      "docsUrl": "https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments",
      "docsLabel": "GitHub Docs: Managing environments for deployment",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "notes": {
          "free": "public repositories only",
          "team": "reviewers and wait timers on public repositories only; branch rules on private ones too"
        },
        "source": "https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments"
      },
      "detect": {
        "events": [
          "environment.remove_protection_rule",
          "environment.update_protection_rule",
          "environment.delete"
        ],
        "match": "exact"
      }
    },
    {
      "id": "account-2fa-disabled",
      "name": "Account without 2FA",
      "kind": "policy",
      "scope": "user",
      "tier": 1,
      "plane": "control",
      "contextDependent": true,
      "why": "Everything the account holds is one phished or reused password away. Its real tier is the highest role or token the account has.",
      "summary": "The account can be accessed with a password alone, with no second factor.",
      "attackPath": "A password-only account is one credential-stuffing or phishing hit away from full compromise of everything that identity holds. Every role and token it owns inherits this weakness.",
      "mitigations": [
        "Require 2FA at the organization or enterprise level",
        "Prefer passkeys or security keys over SMS and app codes"
      ],
      "related": [],
      "docsUrl": "https://docs.github.com/en/authentication/securing-your-account-with-two-factor-authentication-2fa",
      "docsLabel": "GitHub Docs: Securing your account with 2FA",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "ghes"
        ],
        "notes": {
          "ghes": "with built-in or LDAP authentication"
        },
        "source": "https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/understanding-iam-for-enterprises/abilities-and-restrictions-of-managed-user-accounts"
      },
      "detect": {
        "events": [
          "org.disable_two_factor_requirement",
          "business.disable_two_factor_requirement"
        ],
        "match": "related"
      }
    },
    {
      "id": "organization-pat-policy",
      "name": "Personal access token policy",
      "kind": "policy",
      "scope": "organization",
      "tier": 1,
      "plane": "management",
      "why": "Decides whether members' classic and fine-grained tokens can reach the organization at all, and whether fine-grained tokens need an owner's approval. Opening it lets any member's leaked token act on the organization's repositories.",
      "summary": "The organization setting that allows or restricts classic personal access tokens and fine-grained tokens, and whether fine-grained ones need approval.",
      "attackPath": "With classic tokens allowed and no approval for fine-grained ones, every token a member ever created works against the organization. A token leaked from a laptop or CI log then needs nothing else.",
      "mitigations": [
        "Restrict classic tokens and require approval for fine-grained ones"
      ],
      "related": [
        "organization_administration:write",
        "organization_personal_access_token_requests:write"
      ],
      "docsUrl": "https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/setting-a-personal-access-token-policy-for-your-organization",
      "docsLabel": "GitHub Docs: Setting a personal access token policy for your organization",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/setting-a-personal-access-token-policy-for-your-organization"
      },
      "detect": {
        "events": [
          "personal_access_token.access_restriction_disabled",
          "auto_approve_personal_access_token_requests.enable",
          "personal_access_token.expiration_limit_unset"
        ],
        "match": "exact"
      }
    },
    {
      "id": "organization-oauth-restrictions",
      "name": "OAuth app access restrictions",
      "kind": "policy",
      "scope": "organization",
      "tier": 1,
      "plane": "management",
      "why": "Decides which OAuth apps can use members' access to the organization. Turned off, any OAuth app a member authorizes reaches the organization's repositories with that member's access.",
      "summary": "The organization setting that limits organization access to OAuth apps an owner has approved.",
      "attackPath": "A consent-phishing OAuth app, or a compromised third-party app, gets a member's token. Without restrictions that token works on the organization straight away; with them, it does nothing until an owner approves the app.",
      "mitigations": [
        "Turn on OAuth app access restrictions",
        "Review approved OAuth apps and remove unused ones"
      ],
      "related": [
        "organization_administration:write"
      ],
      "docsUrl": "https://docs.github.com/en/organizations/managing-oauth-access-to-your-organizations-data/about-oauth-app-access-restrictions",
      "docsLabel": "GitHub Docs: About OAuth app access restrictions",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu"
        ],
        "source": "https://docs.github.com/en/organizations/managing-oauth-access-to-your-organizations-data/about-oauth-app-access-restrictions"
      },
      "detect": {
        "events": [
          "org.disable_oauth_app_restrictions",
          "org.oauth_app_access_approved"
        ],
        "match": "exact"
      }
    },
    {
      "id": "organization-app-requests",
      "name": "App access requests and installations",
      "kind": "policy",
      "scope": "organization",
      "tier": 2,
      "plane": "data",
      "why": "Decides who can ask for an OAuth app or GitHub App to be given access. A request still needs an owner, so this shapes the review queue rather than granting access.",
      "summary": "The organization setting that controls which users can request organization access for apps.",
      "attackPath": "Open requests let outside collaborators and members flood owners with app requests, which makes a malicious one easier to approve by mistake.",
      "mitigations": [
        "Limit app requests to members",
        "Review each request against a named owner and need"
      ],
      "related": [
        "organization_administration:write"
      ],
      "docsUrl": "https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/limiting-oauth-app-and-github-app-access-requests",
      "docsLabel": "GitHub Docs: Limiting OAuth app and GitHub App access requests and installations",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/limiting-oauth-app-and-github-app-access-requests"
      },
      "detect": {
        "events": [
          "integration_installation_request.create",
          "org.oauth_app_access_requested",
          "integration_installation.create"
        ],
        "match": "related"
      }
    },
    {
      "id": "actions-create-approve-prs",
      "name": "Allow GitHub Actions to create and approve pull requests",
      "kind": "policy",
      "scope": "organization",
      "tier": 1,
      "plane": "management",
      "why": "Turned on, a workflow's GITHUB_TOKEN can approve pull requests, and that approval counts towards required reviews. Anyone who can change a workflow can then get code merged without a person reviewing it.",
      "summary": "The workflow permissions setting that lets GITHUB_TOKEN create and approve pull requests. New organizations start with it off.",
      "attackPath": "An attacker with write access opens a pull request and a workflow that approves it. With the setting on, the approval satisfies the review rule and the change merges.",
      "mitigations": [
        "Turn the setting off at the enterprise or organization level",
        "Require reviews from code owners, which a workflow cannot be"
      ],
      "related": [
        "pull_requests:write",
        "organization_administration:write"
      ],
      "docsUrl": "https://docs.github.com/en/organizations/managing-organization-settings/disabling-or-limiting-github-actions-for-your-organization",
      "docsLabel": "GitHub Docs: Disabling or limiting GitHub Actions for your organization",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/organizations/managing-organization-settings/disabling-or-limiting-github-actions-for-your-organization"
      },
      "detect": {
        "events": [
          "org.set_workflow_permission_can_approve_pr",
          "business.set_workflow_permission_can_approve_pr",
          "repo.set_workflow_permission_can_approve_pr"
        ],
        "match": "exact"
      }
    },
    {
      "id": "member-repository-privileges",
      "name": "Member privileges: visibility changes, deletion and private forks",
      "kind": "policy",
      "scope": "organization",
      "tier": 1,
      "plane": "management",
      "why": "Decides whether repository admins, not only owners, can make repositories public, delete or transfer them, and whether private repositories can be forked. Each one moves code out of the organization's control.",
      "summary": "The organization settings for changing repository visibility, deleting or transferring repositories, and forking private repositories.",
      "attackPath": "With these left open, a stolen repository admin account can flip a private repository to public, transfer it away or delete it, and a member can fork private code to an account the organization does not control.",
      "mitigations": [
        "Limit visibility changes, deletion and transfer to organization owners",
        "Turn off forking of private repositories unless a team needs it"
      ],
      "related": [
        "organization_administration:write",
        "administration:write"
      ],
      "docsUrl": "https://docs.github.com/en/organizations/managing-organization-settings/restricting-repository-visibility-changes-in-your-organization",
      "docsLabel": "GitHub Docs: Restricting repository visibility changes in your organization",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/organizations/managing-organization-settings/restricting-repository-visibility-changes-in-your-organization"
      },
      "detect": {
        "events": [
          "repository_visibility_change.enable",
          "members_can_delete_repos.enable",
          "private_repository_forking.enable",
          "repo.access"
        ],
        "match": "exact"
      }
    },
    {
      "id": "outside-collaborator-invites",
      "name": "Who can invite outside collaborators",
      "kind": "policy",
      "scope": "organization",
      "tier": 1,
      "plane": "management",
      "why": "Decides whether repository admins can add outside collaborators, who keep their access outside the identity provider (see Outside collaborator).",
      "summary": "The organization setting that limits inviting outside collaborators to organization owners.",
      "attackPath": "With invites open to repository admins, one stolen admin account can add an outside account that survives offboarding and SSO.",
      "mitigations": [
        "Limit outside collaborator invites to organization owners"
      ],
      "related": [
        "organization_administration:write",
        "administration:write"
      ],
      "docsUrl": "https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-organization-settings/setting-permissions-for-adding-outside-collaborators",
      "docsLabel": "GitHub Docs: Setting permissions for adding outside collaborators",
      "availability": {
        "on": [
          "enterprise-cloud",
          "ghes"
        ],
        "source": "https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-organization-settings/setting-permissions-for-adding-outside-collaborators"
      },
      "detect": {
        "events": [
          "org.update_member_repository_invitation_permission",
          "business.update_member_repository_invitation_permission"
        ],
        "match": "exact"
      }
    },
    {
      "id": "idp-app-admin",
      "name": "Identity provider admin for the GitHub app",
      "kind": "external",
      "scope": "enterprise",
      "tier": 0,
      "plane": "control",
      "why": "Whoever administers the SAML or OIDC app, or SCIM provisioning, in the IdP decides who can sign in. With Enterprise Managed Users the IdP creates every account, so this is control over the enterprise from outside GitHub.",
      "summary": "Administrators of the GitHub application in Entra ID, Okta or another identity provider.",
      "attackPath": "An attacker with admin rights in the IdP assigns themselves to the GitHub app, or provisions a new account, and signs in. GitHub sees an ordinary SSO sign-in.",
      "mitigations": [
        "Treat IdP admins of the GitHub app as Tier 0 in the IdP's own model",
        "Alert on assignment changes to the GitHub app in the IdP"
      ],
      "related": [
        "enterprise_scim:write"
      ],
      "docsUrl": "https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/configuring-authentication-for-enterprise-managed-users/configuring-saml-single-sign-on-for-enterprise-managed-users",
      "docsLabel": "GitHub Docs: Configuring SAML single sign-on for Enterprise Managed Users",
      "availability": {
        "on": [
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "notes": {
          "enterprise-cloud": "with SAML SSO",
          "ghes": "with SAML or another external authentication"
        },
        "source": "https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/configuring-authentication-for-enterprise-managed-users/configuring-saml-single-sign-on-for-enterprise-managed-users"
      },
      "detect": {
        "events": [
          "business.update_saml_provider_settings",
          "org.update_saml_provider_settings",
          "external_identity.provision",
          "team_sync_tenant.update_okta_credentials"
        ],
        "match": "related"
      }
    },
    {
      "id": "cloud-oidc-trust",
      "name": "Cloud OIDC trust policy for GitHub Actions",
      "kind": "external",
      "scope": "repository",
      "tier": 1,
      "plane": "management",
      "contextDependent": true,
      "why": "Takes the tier of the cloud role it lets workflows assume. The subject (sub) condition decides which workflows can: a wildcard on the repository, branch or environment lets workflows nobody reviewed assume the role.",
      "summary": "The trust policy in AWS, Azure or Google Cloud that accepts GitHub's OIDC token for a cloud role.",
      "attackPath": "A trust policy that matches repo:org/* or any branch lets a workflow from any repository or pull request branch in the organization get cloud credentials, skipping environment reviewers.",
      "mitigations": [
        "Match the full subject, including the environment, in every trust policy",
        "Use environments with required reviewers for roles that can deploy"
      ],
      "related": [
        "id_token:write"
      ],
      "docsUrl": "https://docs.github.com/en/actions/reference/security/oidc",
      "docsLabel": "GitHub Docs: OpenID Connect reference",
      "availability": {
        "on": [
          "free",
          "team",
          "enterprise-cloud",
          "emu",
          "ghes"
        ],
        "source": "https://docs.github.com/en/actions/reference/security/oidc"
      }
    }
  ],
  "detectSource": "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise"
}
