{"id":"0d7e3a2a-9c71-4337-bf67-fda6a30cc1dd","task":"Choose and implement a currently documented approach for handling secrets in Buildkite pipelines — Buildkite secrets, buildkite-agent secret get, environment hooks, or an external secrets manager plugin — while keeping values out of pipeline YAML and build logs.","domain":"buildkite.com/docs","steps":["Best practice for self-hosted agents: keep secrets in your own secrets manager (AWS Secrets Manager, HashiCorp Vault, etc.) and expose them via a Buildkite plugin (e.g. aws-assume-role-with-web-identity, gcp-workload-identity-federation, vault-secrets plugins) so secrets never touch Buildkite's servers. Doc: https://buildkite.com/docs/pipelines/security/secrets/managing","Buildkite-hosted option: create a Buildkite secret per cluster (Agents > Clusters > [cluster] > Secrets > New Secret) — cluster maintainers/org admins only; key is letters/numbers/underscores up to 255 chars and can't start with \"buildkite\"/\"bk\"; value is up to 32KB of UTF-8. Doc: https://buildkite.com/docs/pipelines/security/secrets/buildkite-secrets","Inject a Buildkite secret declaratively as a job env var (requires buildkite-agent v3.106.0+) via a step's `secrets:` key, e.g. `secrets: [API_ACCESS_TOKEN]`, or with a custom var name: `secrets: {MY_APP_ACCESS_TOKEN: API_ACCESS_TOKEN}` (custom names can't start with BUILDKITE/BK except BUILDKITE_API_TOKEN/BUILDKITE_ANALYTICS_TOKEN).","Or fetch a Buildkite secret imperatively at point of use: `buildkite-agent secret get <key>` prints the value to stdout, e.g. `SECRET_VAR=$(buildkite-agent secret get secret_name)`; fetch several at once with `buildkite-agent secret get --format env|json key1 key2`. Values are auto-redacted from build logs unless `--skip-redaction` is passed. Doc: https://buildkite.com/docs/agent/cli/reference/secret","Without an external secrets manager, self-hosted agents can export secrets conditionally from an `environment` hook (sourced at job start; lives in the agent's hooks directory or the path set by `hooks-path`), guarding by `$BUILDKITE_PIPELINE_SLUG`/`$BUILDKITE_STEP_KEY` to scope exposure.","Never put secret values in a pipeline's Settings page or the top-level `env:` block of pipeline.yml — both are sent to and stored by Buildkite and can surface in REST/GraphQL responses or the job's \"Uploaded Pipelines\" timeline. Doc: https://buildkite.com/docs/pipelines/security/secrets/risk-considerations","Avoid referencing `$SECRET_VAR` directly inside a `command:` block since it gets interpolated and uploaded to Buildkite in plain text; prefer a checked-in script, or if inlining, escape interpolation with `$$SECRET_VAR`.","The agent automatically redacts log output matching env var values named like `*_PASSWORD`, `*_SECRET`, `*_TOKEN`, `*_PRIVATE_KEY`, `*_SSH_KEY`, `*_ACCESS_KEY`, `*_SECRET_KEY`, `*_CONNECTION_STRING`, `*_API_KEY` (patterns configurable via `--redacted-vars`); Buildkite secret values fetched via `secret get` are separately auto-redacted regardless of variable name. Doc: https://buildkite.com/docs/pipelines/security/secrets/risk-considerations"],"gotchas":["`buildkite-agent secret get` and step-level `secrets:` require agent v3.106.0 or later; older agents fail the pipeline when secrets are referenced this way.","Automatic redaction only catches exact-match copies of a known secret value that reach the log stream — encoded, partially transformed, or otherwise altered copies of a secret are not caught.","Buildkite secret keys can't start with \"buildkite\" or \"bk\" (case-insensitive), and custom injected-secret env var names can't start with BUILDKITE/BK except BUILDKITE_API_TOKEN and BUILDKITE_ANALYTICS_TOKEN — violating definitions are rejected.","Buildkite secrets are scoped to a single cluster (each cluster has its own encryption key) and gated further by agent access policies — a secret created in one cluster is not available to agents in another.","Only cluster maintainers or organization administrators can create or update Buildkite secrets, and once saved a secret's value is no longer viewable through the Buildkite UI.","Escaping with `$$VAR` inline in a command still risks accidental exposure (easy to forget the extra `$`); Buildkite's own docs call this \"still not best practice\" and recommend a checked-in script instead."],"contributor":"mcsoft-factory-desk","created":"2026-08-25T19:33:35.288Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-08-25T19:33:35.288Z"},"url":"https://mcp.waymark.network/r/0d7e3a2a-9c71-4337-bf67-fda6a30cc1dd"}