{"record":{"id":"2b9ceef8a5fc76a6","repo":"hashicorp/packer","slug":"signing-mode-q-requires-an-ambient-oidc-token-se","errorCode":null,"errorMessage":"signing_mode %q requires an ambient OIDC token; set SIGSTORE_ID_TOKEN, use a CI-provided OIDC token, or switch to signing_mode=\"none\" or a key-backed mode","messagePattern":"signing_mode %q requires an ambient OIDC token; set SIGSTORE_ID_TOKEN, use a CI-provided OIDC token, or switch to signing_mode=\"none\" or a key-backed mode","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/attestation/sign_keyless.go","lineNumber":316,"sourceCode":"\n\treturn append([]byte(nil), p.certDER...), nil\n}\n\nfunc resolveAmbientIDToken(ctx context.Context, env map[string]string) (string, error) {\n\tif token := strings.TrimSpace(env[\"SIGSTORE_ID_TOKEN\"]); token != \"\" {\n\t\treturn token, nil\n\t}\n\tif token := strings.TrimSpace(env[\"CI_JOB_JWT_V2\"]); token != \"\" {\n\t\treturn token, nil\n\t}\n\tif token := strings.TrimSpace(env[\"CI_JOB_JWT\"]); token != \"\" {\n\t\treturn token, nil\n\t}\n\tif token, err := resolveGitHubActionsIDToken(ctx, env); err == nil && token != \"\" {\n\t\treturn token, nil\n\t}\n\n\treturn \"\", fmt.Errorf(\"signing_mode %q requires an ambient OIDC token; set SIGSTORE_ID_TOKEN, use a CI-provided OIDC token, or switch to signing_mode=\\\"none\\\" or a key-backed mode\", SigningModeKeyless)\n}\n\nfunc resolveGitHubActionsIDToken(ctx context.Context, env map[string]string) (string, error) {\n\trequestURL := strings.TrimSpace(env[\"ACTIONS_ID_TOKEN_REQUEST_URL\"])\n\trequestToken := strings.TrimSpace(env[\"ACTIONS_ID_TOKEN_REQUEST_TOKEN\"])\n\tif requestURL == \"\" || requestToken == \"\" {\n\t\treturn \"\", nil\n\t}\n\n\tparsedURL, err := url.Parse(requestURL)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"parse GitHub OIDC request URL: %w\", err)\n\t}\n\tquery := parsedURL.Query()\n\tif query.Get(\"audience\") == \"\" {\n\t\tquery.Set(\"audience\", \"sigstore\")\n\t\tparsedURL.RawQuery = query.Encode()\n\t}","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/hashicorp/packer/blob/eb36e3c3e48a036f3e8cc94087636ee72e1303c9/internal/attestation/sign_keyless.go#L298-L334","documentation":"resolveAmbientIDToken could not find any ambient OIDC token for keyless signing. It checks SIGSTORE_ID_TOKEN, GitLab's CI_JOB_JWT_V2/CI_JOB_JWT, and GitHub Actions' OIDC endpoint (ACTIONS_ID_TOKEN_REQUEST_URL/TOKEN); when none yield a token, keyless signing cannot obtain a Fulcio certificate and fails with this actionable message.","triggerScenarios":"newKeylessSigner runs with signing_mode=\"keyless\" when: SIGSTORE_ID_TOKEN is unset/blank, CI_JOB_JWT(_V2) are unset, and either ACTIONS_ID_TOKEN_REQUEST_URL/ACTIONS_ID_TOKEN_REQUEST_TOKEN are unset or the GitHub OIDC request fails/returns empty (its errors are swallowed here).","commonSituations":"Running keyless signing locally without exporting SIGSTORE_ID_TOKEN (e.g. from `fulcio` or an OIDC flow); a GitHub Actions job missing `permissions: id-token: write` so the runtime env vars are absent; self-hosted runners without OIDC configured; GitLab CI with older JWT variables only partially set.","solutions":["Set SIGSTORE_ID_TOKEN to a valid OIDC ID token whose issuer/identity match the configured keyless_identity and keyless_oidc_issuer.","On GitHub Actions, add `permissions: id-token: write` to the workflow so ACTIONS_ID_TOKEN_REQUEST_URL/TOKEN are injected.","Switch to signing_mode=\"none\" or a key-backed mode if no OIDC identity is available.","If on GitHub Actions with permissions set, check why the OIDC request failed — the underlying error is suppressed; run resolveGitHubActionsIDToken directly to see it."],"exampleFix":"// before (GitHub Actions workflow)\njobs:\n  sign:\n    steps:\n      - run: packer ...\n// after\njobs:\n  sign:\n    permissions:\n      id-token: write\n    steps:\n      - run: packer ...","handlingStrategy":"validation","validationCode":"func ambientTokenAvailable(env map[string]string) bool {\n    if strings.TrimSpace(env[\"SIGSTORE_ID_TOKEN\"]) != \"\" {\n        return true\n    }\n    if strings.TrimSpace(env[\"CI_JOB_JWT_V2\"]) != \"\" || strings.TrimSpace(env[\"CI_JOB_JWT\"]) != \"\" {\n        return true\n    }\n    return strings.TrimSpace(env[\"ACTIONS_ID_TOKEN_REQUEST_URL\"]) != \"\" &&\n        strings.TrimSpace(env[\"ACTIONS_ID_TOKEN_REQUEST_TOKEN\"]) != \"\"\n}\nif !ambientTokenAvailable(cfg.Env) {\n    return fmt.Errorf(\"no ambient OIDC token; set SIGSTORE_ID_TOKEN or run in CI with OIDC enabled\")\n}","typeGuard":"func hasCIContext(env map[string]string) bool {\n    return strings.TrimSpace(env[\"ACTIONS_ID_TOKEN_REQUEST_URL\"]) != \"\" ||\n        strings.TrimSpace(env[\"CI_JOB_JWT\"]) != \"\"\n}","tryCatchPattern":"signer, err := newKeylessSigner(ctx, cfg)\nif err != nil && strings.Contains(err.Error(), \"requires an ambient OIDC token\") {\n    return fmt.Errorf(\"keyless signing unavailable outside OIDC-enabled CI; switch signing_mode or export SIGSTORE_ID_TOKEN: %w\", err)\n}","preventionTips":["Export SIGSTORE_ID_TOKEN before running keyless signing locally.","Add `permissions: id-token: write` to GitHub Actions workflows that sign.","Prefer signing_mode=\"none\" or key-backed modes outside OIDC-enabled CI.","Check env vars are non-blank, not just present (whitespace-only values are rejected)."],"tags":["go","oidc","keyless-signing","ci","environment"],"backgroundTag":"missing-oidc-token","analyzedSha":"eb36e3c3e48a036f3e8cc94087636ee72e1303c9","analyzedAt":"2026-09-05T13:20:43.127Z","contentChangedAt":"2026-09-05T13:20:43.127Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}