The Credential Problem Nobody Talks About in Pipeline Tutorials

Every CI/CD tutorial ends with a working deployment. What they don't show is the secret sitting in that .yml file, who can read it, and what happens when it expires at 3am.
Every CI/CD tutorial ends the same way.
The pipeline runs. The deployment succeeds. The README says "done." And somewhere in that .yml file, between the checkout and deploy steps, there is a secret that will eventually find its way into a public repository, a shared Slack thread, or a container image cached on a public registry.
The tutorial never covers that part.
I've worked with pipelines on GitHub Actions, Azure DevOps, and AWS CodePipeline. Across all three, the moment credentials enter the picture, the tutorial stops being a tutorial and starts being a liability. Not because the author was careless — because secrets management is genuinely hard to explain in a demo context, and genuinely easy to skip when the goal is showing the pipeline working.
This is about the gap between "it works" and "it's secure."
The three credentials that trip people up
Most pipelines involve at least three categories of credential. Each one has a different failure mode.
SSH keys
SSH keys feel like the solved problem. Generate a key pair, add the public key to the target server, store the private key as a pipeline secret. Done.
Except: the private key is now stored in your CI/CD platform, probably as an environment variable, possibly with a passphrase and possibly without. It may be injected into the pipeline runner as a file during the build — which means it briefly lives on disk on a machine you don't fully control. If your pipeline definition has a debug step that echoes environment variables (which happens), that key is now in your build log.
The practical question nobody asks during setup: what happens when that key needs to rotate? In most setups, the answer is "manually update it in the pipeline settings, then update it on the server, and hope the window between the two doesn't cause a failed deployment at 3am." SSH key rotation is almost always unplanned.
Service principals
In Azure and AWS, pipelines authenticate to cloud APIs using service principals or IAM roles. The common tutorial pattern: create a service principal with Contributor access on the subscription, generate a client secret, paste it into the pipeline.
Contributor on a subscription means the pipeline can create, modify, and delete anything in that environment. That is, by any sensible definition, too much access. But it's easy to set up, it works immediately, and scoping it down correctly requires understanding the exact permissions each pipeline step actually needs — which takes longer than the pipeline itself.
The other problem with service principal secrets: they expire. Azure defaults to one or two years. AWS doesn't expire access keys by default, which is arguably worse. When a secret expires mid-cycle, the pipeline fails in a way that isn't immediately obvious. The error is typically an authentication failure — not "your credential expired six days ago."
Application secrets and API keys
Database connection strings, third-party API keys, encryption secrets — these are the credentials that end up in environment variables, .env files committed to the repository, or hardcoded into configuration because the developer needed it to work and the quick solution was never revisited.
GitHub's secret scanning catches some of this. It doesn't catch secrets rotated after the fact (the commit is still in history), secrets in formats the scanner doesn't recognise, or secrets injected through a configuration path that doesn't touch the repository at all.
Why tutorials don't cover this
A tutorial that correctly implements secrets management for a CI/CD pipeline would need to cover: vault integration or a managed secrets service, least-privilege role scoping, secret rotation policies, audit logging for secret access, and safe secret injection that doesn't expose values in logs.
That's not a tutorial. That's a security architecture engagement.
The tension is real. A tutorial that adds all of that is impossible to follow in an afternoon. A tutorial that skips it produces a working pipeline that isn't production-safe. Most tutorials choose the latter and add a footnote that says "in production, use a secrets manager."
The problem is that the footnote doesn't survive contact with a deadline.
Engineers who build pipelines from tutorials are not making a security mistake out of ignorance. They're making a pragmatic decision: the insecure pattern ships on time. The secure pattern requires time and infrastructure that the task budget doesn't include. And once the insecure pattern is running in production, it becomes very hard to justify the cost of fixing something that "works."
What actually closes the gap
Three practices that remain less common than they should be.
Workload identity instead of long-lived credentials. GitHub Actions, Azure DevOps, and AWS all support federated identity — the pipeline authenticates as itself to the cloud provider, which issues a short-lived token scoped to the duration of the run. No stored credentials. Nothing to rotate. Nothing to leak. Setting this up correctly takes longer than creating a service principal secret. But it permanently removes an entire category of credential management problem.
Least privilege, scoped to the pipeline step. Each step should have only the permissions it needs for that step. The unit test step doesn't need storage access. The production deploy step doesn't need read access to the dev database. This requires understanding what each step actually does rather than copying the pipeline — a higher bar than most tutorials set.
Secrets in a vault, not in environment variables. HashiCorp Vault, AWS Secrets Manager, Azure Key Vault — all three allow pipelines to retrieve secrets at runtime, audit which pipeline accessed which secret and when, and rotate secrets without touching the pipeline definition. The upfront cost is higher. The blast radius of a credential compromise is dramatically smaller.
The gap is a systems problem
The gap between "it works" and "it's secure" closes when secrets management is part of the pipeline design from the start — not a remediation task after an audit finds it.
That requires treating credentials as infrastructure. Not environment variables. Not footnotes.
Every pipeline has a credential story. Most of them end with "we'll fix it later."