Any developer can connect a third-party service to your source control or build system in minutes, and that service then holds standing access to code, secrets and pipelines that nobody approved or reviews. OWASP lists this as CICD-SEC-8 Ungoverned Usage of 3rd Party Services in the Top 10 CI/CD Security Risks. This guide explains what the risk covers, the integration methods it applies to, how to put approval, inventory, scoping and deprovisioning around them, what evidence an assessor should ask for, and how the risk maps to NIST, CIS, ISO and MITRE ATT&CK. It is written for platform engineers, DevSecOps leads, GitHub and GitLab organisation owners, and the people who own CI/CD service identities. It goes deeper than the Top 10 CI/CD Security Risks overview.
Key takeaways
- The attack surface includes what you connected. OWASP defines the CI/CD attack surface as your own assets plus every third-party service granted access to them.
- Connecting is easy, governing is not. A GitHub App, OAuth app, token, SSH key or webhook takes seconds to set up and can grant anything from read access to one repository to administration of the whole organisation.
- Build-time integrations run with the pipeline's power. An action, orb or plugin added in one or two lines of pipeline configuration executes with full access to the secrets and resources of that stage.
- Govern the full lifecycle. OWASP's four controls are approval before access, visibility over integrations and their permissions, ongoing scoping to what is actually used, and periodic deprovisioning.
- Every integration is a non-human identity. Each one holds an app installation, OAuth grant, token or key that must have an owner, a scope, an expiry and a revocation plan.
What it is and who it applies to
OWASP's definition is that ungoverned third-party risk relies on "the extreme ease with which a 3rd party service can be granted access to resources in CI/CD systems", which expands the organisation's attack surface. The impact statement is blunt: given how permissive third parties tend to be, organisations are "only as secure as the 3rd parties they implement". OWASP also gives the propagation path that makes this a CI/CD problem rather than a procurement problem: a third party with write permission on a repository can be used to push code, which triggers a build, which runs the attacker's code on the build system.
The OWASP entry names five ways to connect a third party to GitHub, and every major platform has equivalents:
- GitHub App: installed on an organisation or selected repositories with fine-grained permissions; acts as itself.
- OAuth app: acts on behalf of the user who authorised it, inheriting that user's repository access.
- Access token: a personal access token (classic or fine-grained) handed to the service.
- SSH key: a user key or a repository deploy key given to the service.
- Webhook: event payloads, sometimes containing code metadata, sent to the third party's endpoint.
On the build side OWASP points to marketplace actions in GitHub Actions and Orbs in CircleCI; Jenkins plugins, GitLab CI includes and Azure DevOps extensions follow the same pattern. Hosted CI services themselves are third parties too: the CircleCI breach forced customers to treat every secret stored on the platform as exposed.
The risk applies to any organisation using SaaS source control or CI, and most acutely to those that let any member authorise OAuth apps or install marketplace integrations. It overlaps with OWASP CI/CD Top 10 CICD-SEC-3 Dependency Chain Abuse Guide (malicious packages) but is distinct: CICD-SEC-8 is about services and integrations you grant access to, not code you import.
Structure and key requirements
OWASP structures the recommendations around the third-party usage lifecycle. The table turns each stage into concrete platform controls.
| Lifecycle stage | OWASP requirement | Platform controls (examples) |
|---|---|---|
| Approval | Vet third parties before they are granted access; permissions aligned with least privilege | GitHub OAuth app access restrictions; "Require administrator approval" for fine-grained PATs; only organisation owners install GitHub Apps; Actions policy "Allow select actions and reusable workflows"; Jenkins plugin installs limited to administrators |
| Integration | Continuous visibility of every integration: method, permissions granted, permissions actually used | Inventory of GitHub Apps, OAuth apps, PATs, deploy keys, webhooks, actions, orbs and plugins per organisation; audit log streaming to the SIEM |
| Visibility over ongoing usage | Scope each third party to the resources it needs; remove unused permissions; build-time integrations run in a scoped context with limited secrets and strict ingress and egress filters | "Only select repositories" on app installations; read-only deploy keys; restrictive default GITHUB_TOKEN permissions; per-job secrets; egress allowlists on runners |
| Deprovisioning | Periodically review all integrations and remove those no longer in use | Quarterly review; suspend then uninstall apps; revoke OAuth grants and tokens; delete orphaned webhooks and keys |
Integration methods differ sharply in how governable they are, which drives the decision on what to allow.
| Method | Acts as | Scoping available | Governance notes |
|---|---|---|---|
| GitHub App | The app itself | Per-permission, per-repository ("Only select repositories") | Preferred for vendors. Owners can review permissions, change repository access, suspend or uninstall |
| OAuth app | The authorising user | Coarse OAuth scopes; inherits all the user's access | Without access restrictions, any app a member authorises can reach the organisation's private resources |
| Fine-grained PAT | The user | Per-repository, per-permission, with expiry | Subject to organisation approval and maximum lifetime policy (default maximum 366 days) |
| Classic PAT | The user | Broad scopes, no expiry requirement | Not subject to approval; restrict at organisation level where possible |
| Deploy key | A key bound to one repository | Read-only by default, write optional | Usually not passphrase protected; easy to forget on servers |
| Webhook | Outbound only | Event selection | Payloads can leak metadata; protect with a webhook secret and HTTPS endpoints |
| Action, orb or plugin | Runs inside your pipeline | Whatever the job has | Pin to a full-length commit SHA; allowlist; run in a job with minimal secrets |
Decision guidance: prefer a GitHub App (or the platform's equivalent such as a GitLab group access token or project-scoped service account) over an OAuth app or user token, because it can be scoped per repository and survives staff leaving. Allow OAuth apps only after enabling access restrictions. Small organisations can usually run a single allowlist owned by the platform team and review it quarterly. Large organisations with many business units need an intake workflow, risk tiers (read-only, write to code, admin or secrets access) and delegated reviewers, with the highest tier requiring security sign-off and a vendor assessment under the Third-Party Risk Management Guide process.
Identity and NHI requirements
Every third-party integration is a non-human identity that you did not create and cannot fully see. The access token, app private key or OAuth refresh token often lives in the vendor's infrastructure, so your controls are on the grant, not the secret. The GitHub OAuth token breach of 2022 shows the consequence: attackers used OAuth user tokens held by the Heroku and Travis CI integrations to list and clone private repositories across dozens of organisations, including npm's.
- Owner: each integration has a named internal owner and a business purpose recorded in the inventory.
- Identity type: app identities rather than user-bound OAuth grants or PATs; where a user identity is unavoidable, use a dedicated machine account with only the repositories needed, not an engineer's account.
- Scope: per-repository installation, minimal permissions, read-only by default. Review "permissions granted" against "permissions used", which OWASP calls out explicitly.
- Lifetime: short-lived tokens where the platform supports them (GitHub App installation tokens are short-lived; fine-grained PATs with an enforced maximum lifetime); no classic PATs for vendors.
- Revocation plan: for each vendor, a documented list of what to revoke and rotate if the vendor reports a breach, tested once a year.
- Secrets inside the pipeline: third-party actions and orbs should run in jobs that hold only the secrets they need, which is the OWASP CI/CD Top 10 CICD-SEC-5 Insufficient PBAC Guide control applied to vendor code.
For the vendor-side view of the same problem see the OWASP NHI Top 10 NHI3 Vulnerable Third-Party NHI Guide, and for SaaS-wide OAuth governance the SaaS and OAuth App Governance Guide.
Implementation steps
- Discover (weeks 1 to 2). Export every integration from each SCM and CI system: installed GitHub Apps and their repository access, authorised OAuth apps, approved and pending fine-grained PATs, deploy keys, organisation and repository webhooks, actions referenced in workflows, orbs, Jenkins plugins and GitLab integrations. Record method, permissions granted, last use and owner.
- Classify and remove the obvious (week 3). Tier each integration by permission (read, write to code, admin, secrets). Suspend integrations with no owner or no use in 90 days rather than deleting them, so they can be restored if something breaks.
- Turn on approval gates (week 4). Enable OAuth app access restrictions, require administrator approval for fine-grained PATs, restrict classic PAT access, set a maximum token lifetime, and restrict who can install apps. Announce the change first: enabling OAuth restrictions immediately cuts unapproved OAuth apps off from private resources, so pre-approve the apps you want to keep.
- Lock down build-time integrations (weeks 4 to 6). Set the Actions policy to allow only GitHub-owned, verified-creator or explicitly listed actions and reusable workflows. Pin every third-party action to a full-length commit SHA and use a lockfile where the platform supports it. Pilot on a few repositories in report-only mode (a scanner such as OpenSSF Scorecard or a workflow linter) before enforcing organisation-wide.
- Scope down (weeks 6 to 10). Move app installations to "Only select repositories", reduce permissions to what audit logs show is used, switch default
GITHUB_TOKENpermissions to read-only, and move third-party steps into jobs with minimal secrets and egress allowlists. - Operate. Publish an intake form, route requests by tier, and run a quarterly access review that ends in removal, not just attestation. Stream SCM and CI audit logs to the SIEM.
- Rollback. Keep the pre-change export. If a gate breaks a critical pipeline, approve the specific integration rather than disabling the restriction: GitHub notes that disabling and later re-enabling OAuth restrictions automatically restores access for previously approved apps, which makes a blanket rollback broader than intended.
Evidence and assessment
An assessor, internal auditor or customer due-diligence review should be able to see the following.
- Inventory: a current list of every integration per system with method, permission tier, repositories in scope, owner, approval record and last-used date.
- Policy settings: screenshots or API exports showing OAuth app restrictions enabled, PAT approval and lifetime policy, Actions allowlist policy, and app installation rights limited to owners.
- Review records: the last two quarterly reviews with integrations removed or scoped down, not only "no change".
- Pipeline evidence: a scan showing third-party actions pinned to SHAs and jobs that run vendor code without production secrets.
- Breach readiness: per-vendor revocation runbooks, and evidence of a past exercise, ideally linked to the Supply Chain Compromise Response Playbook.
Detection: alert on new app installations, OAuth app approvals, new deploy keys with write access, new organisation webhooks, permission increases on existing apps, and integrations cloning many repositories in a short period (the pattern seen in the 2022 OAuth token theft). Watch for actions referenced by tag or branch in new workflow commits.
Metrics:
- Percentage of integrations with a named owner and approval record (target 100%).
- Percentage of app installations scoped to selected repositories rather than all repositories.
- Number of OAuth apps and classic PATs with organisation access (trend to zero for vendors).
- Percentage of third-party action references pinned to a full commit SHA.
- Mean time from vendor breach notification to full revocation and rotation.
- Integrations removed per quarterly review.
Mapping to other frameworks
| Framework | Reference | Relevance to CICD-SEC-8 |
|---|---|---|
| NIST CSF 2.0 | GV.SC-04, GV.SC-06, GV.SC-07, GV.SC-10, ID.AM-04, DE.CM-06 | Suppliers known and prioritised, due diligence before onboarding, supplier risk managed through the relationship, offboarding provisions, inventory of supplier services, monitoring of provider activity |
| NIST CSF 2.0 | PR.AA-05 | Access permissions managed with least privilege, applied to integration grants |
| NIST SP 800-53 Rev. 5 | SA-9, SR-3, SR-6, AC-6, AC-20, CM-8 | External system services, supply chain controls, supplier assessments, least privilege, use of external systems, component inventory |
| NIST SP 800-218 (SSDF) | PO.3, PW.4 (PW.4.1, PW.4.4) | Supporting toolchains; acquiring and verifying third-party components across their life cycle |
| CIS Controls v8.1 | Control 15 Service Provider Management; Control 16 Application Software Security | Inventory, assessment, monitoring and decommissioning of service providers; secure development pipeline |
| ISO/IEC 27001:2022 Annex A | 5.19, 5.20, 5.21, 5.22, 8.30 | Supplier relationships, security in supplier agreements, ICT supply chain, monitoring and change of supplier services, outsourced development |
| MITRE ATT&CK v20 | T1199 Trusted Relationship; T1195.001 Compromise Software Dependencies and Development Tools; T1528 Steal Application Access Token; T1550.001 Application Access Token; T1098.001 Additional Cloud Credentials | Entry through a connected vendor, compromised actions or plugins, theft and reuse of integration tokens, persistence through added app credentials |
Common pitfalls
- Trusting a mutable reference. Workflows that call an action by tag run whatever the tag points to today. In the tj-actions/changed-files compromise (CVE-2025-30066) the attacker moved the version tags to a malicious commit and secrets were printed into workflow logs.
- Running a vendor script with every secret in scope. The Codecov breach modified the Bash Uploader so that every pipeline running it sent its environment variables to the attacker from 31 January 2021 until a customer noticed a checksum mismatch on 1 April.
- Leaving OAuth apps unrestricted. Without access restrictions, any OAuth app a member authorises can reach the organisation's private resources, and nobody approved it.
- Granting "All repositories" by default. Vendors ask for organisation-wide installs because it is easier to support; one vendor compromise then reaches every repository. OWASP's DeepSource reference describes exactly this through a compromised GitHub App.
- Reviews that never remove anything. Attestation-only reviews leave trial integrations, departed vendors and orphaned deploy keys in place for years.
- No plan for a vendor breach. When CircleCI disclosed in January 2023, customers had to find and rotate every stored secret, token and SSH key at short notice; those without an inventory could not know what to rotate.
Practitioner checklist
- Inventory every GitHub App, OAuth app, token, deploy key, webhook, action, orb and plugin with owner, permissions and last use.
- Enable OAuth app access restrictions and pre-approve only the apps you need.
- Require administrator approval and a maximum lifetime for fine-grained PATs; restrict classic PATs.
- Restrict app installation to organisation owners and default installs to "Only select repositories".
- Allowlist actions and reusable workflows, and pin third-party actions to full-length commit SHAs.
- Run vendor code in jobs with minimal secrets, read-only default tokens and egress filtering.
- Alert on new installations, approvals, permission increases, write deploy keys and mass cloning.
- Keep a revocation and rotation runbook per vendor and exercise it once a year.
- Review quarterly and remove anything without an owner or recent use.
Standards and references
- OWASP: CICD-SEC-8 Ungoverned Usage of 3rd Party Services
- OWASP: Top 10 CI/CD Security Risks
- GitHub Docs: About OAuth app access restrictions
- GitHub Docs: Setting a personal access token policy for your organization
- GitHub Docs: Reviewing and modifying installed GitHub Apps
- GitHub Docs: Secure use reference for GitHub Actions
- NIST: SP 800-218 Secure Software Development Framework
- MITRE ATT&CK: Trusted Relationship
Related NHI Mgmt Group resources: CI/CD Pipeline Identity Security Guide · GitHub and GitHub Actions Security Guide · SaaS and OAuth App Governance Guide · OWASP CI/CD Top 10 CICD-SEC-9 Improper Artifact Integrity Validation Guide · CI/CD Security Guide