{
  "profileId": "capitalguard.github-actions-ai-agent-security-gate",
  "version": "0.1.0",
  "status": "published",
  "publishedAt": "2026-07-17",
  "updatedAt": "2026-07-17",
  "canonicalUrl": "https://capitalguard.io/guides/github-actions-ai-agent-security-gate",
  "profileUrl": "https://capitalguard.io/profiles/github-actions-ai-agent-security-gate/v0.1.0/profile.json",
  "workflowUrl": "https://capitalguard.io/profiles/github-actions-ai-agent-security-gate/v0.1.0/workflow.yml",
  "publisher": "CapitalGuard Security Research",
  "license": "CC BY 4.0",
  "summary": "A conservative GitHub Actions profile for AI coding-agent checks: authorized scope, trusted triggers, read-only token, immutable action dependencies, no persisted checkout credential, untrusted-input isolation, narrow OIDC identity, and a separate human gate for high-impact actions.",
  "claimBoundary": "This profile reduces declared GitHub Actions exposure paths. It does not prove that an AI agent, workflow, runner, dependency, repository, or external system is safe.",
  "pinnedDependencies": [
    {
      "repository": "actions/checkout",
      "release": "v6",
      "commitSha": "df4cb1c069e1874edd31b4311f1884172cec0e10"
    },
    {
      "repository": "CapitalGuard-Security/capitalguard-action",
      "release": "v1",
      "commitSha": "33d6a70d997c67a53f74247f1bdc83dbeb7d9079"
    }
  ],
  "controls": [
    {
      "id": "CG-GHA-001",
      "title": "Authorized repository scope",
      "risk": "A security workflow can become an unapproved scan of code the operator does not own or control.",
      "requiredAction": "Record repository authorization and keep the workflow scoped to the repository that triggered the run.",
      "evidence": "authorization-confirmed is explicit and the job does not fetch another private repository.",
      "standardControl": "CGS-AUTH-001",
      "sourceIds": ["github-secure-use"]
    },
    {
      "id": "CG-GHA-002",
      "title": "Trusted trigger boundary",
      "risk": "An untrusted actor or event can start a privileged workflow before branch rules or review can intervene.",
      "requiredAction": "Use pull_request for untrusted changes. Restrict or prohibit pull_request_target and manual triggers where organizational execution protections are available.",
      "evidence": "Trigger list, actor policy, event policy, and any evaluated exceptions are retained.",
      "standardControl": "CGS-PRIV-001",
      "sourceIds": ["github-execution-protections"]
    },
    {
      "id": "CG-GHA-003",
      "title": "Read-only token",
      "risk": "A compromised action can inherit repository write authority through GITHUB_TOKEN.",
      "requiredAction": "Declare permissions at workflow or job level and grant contents: read unless a separately reviewed operation needs more.",
      "evidence": "The workflow contains an explicit minimal permissions block with no implicit write scope.",
      "standardControl": "CGS-PRIV-001",
      "sourceIds": ["github-secure-use"]
    },
    {
      "id": "CG-GHA-004",
      "title": "Immutable action dependencies",
      "risk": "A mutable tag can later point to different code while the workflow file appears unchanged.",
      "requiredAction": "Pin every third-party action to a verified full-length commit SHA and record the human-readable release in a comment.",
      "evidence": "All uses references are full 40-character commit SHAs from the intended upstream repositories.",
      "standardControl": "CGS-TRACE-001",
      "sourceIds": ["github-secure-use"]
    },
    {
      "id": "CG-GHA-005",
      "title": "No persisted checkout credential",
      "risk": "A later step can reuse the checkout credential even when that step does not need repository authentication.",
      "requiredAction": "Set persist-credentials: false and provide a separately scoped credential only to a reviewed step that needs it.",
      "evidence": "Checkout configuration and the absence of later ambient credential use are reviewable in the workflow.",
      "standardControl": "CGS-SEC-001",
      "sourceIds": ["github-secure-use"]
    },
    {
      "id": "CG-GHA-006",
      "title": "Untrusted input stays data",
      "risk": "Pull request text, branch names, or other attacker-controlled context can become shell code.",
      "requiredAction": "Pass untrusted context through action inputs or intermediate environment variables, never direct expression expansion inside a generated shell script.",
      "evidence": "Inline run blocks contain no direct executable interpolation of untrusted github context fields.",
      "standardControl": "CGS-INJ-001",
      "sourceIds": ["github-script-injection"]
    },
    {
      "id": "CG-GHA-007",
      "title": "OIDC is narrow and optional",
      "risk": "Identity permissions can be misunderstood as proof that the workflow logic or repository is safe.",
      "requiredAction": "Grant id-token: write only to the job that requests a signed preview or short-lived credential, validate claims server-side, and remove the permission when unused.",
      "evidence": "The receiving service validates issuer, audience, repository identity, workflow revision, signature, and expiry.",
      "standardControl": "CGS-ATTEST-001",
      "sourceIds": ["github-oidc"]
    },
    {
      "id": "CG-GHA-008",
      "title": "High-impact actions require a second gate",
      "risk": "A passing scan can be treated as permission to deploy, publish, rotate credentials, or change production.",
      "requiredAction": "Keep deployment and secret release in a separate protected environment with required review, restricted branches, and no self-approval where available.",
      "evidence": "Environment protections and the human decision are separate from the scanner result.",
      "standardControl": "CGS-HUMAN-001",
      "sourceIds": ["github-environments"]
    }
  ],
  "primarySources": [
    {
      "id": "github-secure-use",
      "title": "Secure use reference",
      "url": "https://docs.github.com/en/actions/reference/security/secure-use",
      "checkedAt": "2026-07-17"
    },
    {
      "id": "github-script-injection",
      "title": "Script injections",
      "url": "https://docs.github.com/en/actions/concepts/security/script-injections",
      "checkedAt": "2026-07-17"
    },
    {
      "id": "github-oidc",
      "title": "OpenID Connect",
      "url": "https://docs.github.com/en/actions/concepts/security/openid-connect",
      "checkedAt": "2026-07-17"
    },
    {
      "id": "github-environments",
      "title": "Deployments and environments",
      "url": "https://docs.github.com/en/actions/reference/workflows-and-actions/deployments-and-environments",
      "checkedAt": "2026-07-17"
    },
    {
      "id": "github-execution-protections",
      "title": "Workflow execution protections",
      "url": "https://docs.github.com/en/organizations/managing-organization-settings/actions-policies/workflow-execution-protections",
      "checkedAt": "2026-07-17"
    }
  ],
  "limitations": [
    "The public CapitalGuard Action reports aggregate exposure signals and intentionally withholds exact affected paths, proprietary scoring, prevention assets, and CapitalGuard Verified status.",
    "A signed preview proves the integrity and GitHub workflow identity of a fixed aggregate evidence receipt. It does not certify the repository or replace an authorized review.",
    "GitHub plan availability, repository visibility rules, public-preview features, and product behavior can change.",
    "Processes launched outside the workflow, compromised runners or hosts, and external systems outside the declared scope remain separate security boundaries."
  ]
}
