CI/CD / Promotion and environment contracts / Lesson 8
Secrets and trust boundaries in delivery
Grant release authority only to code, identities, and environments that should hold it.
On this page
Lesson goals
- Trace who can influence a privileged job.
- Explain short-lived identity and the limits of secret masking.
Follow every executable input
A privileged delivery job executes more than its visible script. It may run checked-out source, build plugins, package lifecycle hooks, third-party actions, and restored cache content. If an untrusted proposal can alter any executable input, giving that job a release secret gives the proposal a route to that authority. Separate untrusted validation from privileged promotion. This is not solved merely by hiding the secret from the log: malicious code can transmit it elsewhere or perform an authorized action directly while the credential remains valid.
Match authority to one task
Parcelโs build job should not need production write access. A promotion job may need narrowly scoped access to a particular target and candidate, while a report job needs only report publication. Define identities per responsibility and environment, and give them the shortest useful lifetime. Repository read access, artifact upload, release approval, and runtime mutation are distinct powers. When a platform offers a default token, review its effective permissions instead of assuming the defaults are minimal or identical across organizations.
Understand short-lived federation
OIDC-based federation can exchange a platform-issued identity token for short-lived provider access after a trust relationship is configured. The provider must verify appropriate issuer, audience, and subject or equivalent claims. Replacing a long-lived secret with federation reduces one exposure window but does not make arbitrary workflow code trustworthy. A loose trust rule allowing every branch or repository can still grant excessive authority. The following record is a conceptual review checklist rather than a provider policy, and no credential is created.
identity checks:
issuer: expected CI identity service
audience: intended token consumer
subject: approved repository and environment
authorization:
target: one approved environment
action: one required promotion capability
Actual claim names, subject formats, and role policy syntax depend on the CI service and provider. This illustration contains no token, client secret, account identifier, or live endpoint.
Masking does not revoke disclosure
Secret masking can hide recognized strings in logs, but transformed, encoded, split, or accidentally embedded values may escape it. Avoid printing the environment, passing secrets as command-line arguments when safer channels exist, and packaging configuration files containing credentials. Treat logs and artifacts as separate disclosure channels. If exposure occurs, redacting a visible line does not invalidate a copied credential. Coordinate rotation or revocation through the credential owner and retain a redacted incident record of the affected identity and time window.
A privileged decision needs multiple predicates
The complete model below permits promotion only when source trust, environment approval, and candidate verification are all true. It intentionally refuses a fully tested but untrusted proposal. Real systems must obtain these facts through trusted control-plane evidence; a file in the proposal cannot assert its own trustworthiness. Review every false case, not just the happy path. Also verify that the runner cannot inherit authority from an earlier job through files, processes, or an overpowered host identity.
def promote(trusted_source, approved_environment, verified_candidate):
return all((trusted_source, approved_environment, verified_candidate))
print(promote(False, True, True))
print(promote(True, True, True))
False
True
This local boolean model performs no authentication or deployment. The names describe independent required observations, not user-supplied permissions.
Common errors and fixes
A fork proposal can run a deployment credential.
- Why it happens
- Untrusted executable inputs crossed into a privileged job.
- How to fix it
- Separate proposal testing from trusted candidate promotion.
- Prevent it next time
- Review source, plugins, caches, and runner identity together.
A masked token is considered safe after exposure.
- Why it happens
- Log appearance was confused with credential validity.
- How to fix it
- Revoke or rotate through the owner and inspect affected access.
- Prevent it next time
- Minimize lifetime and prevent printing sensitive material.
Federation trusts every repository branch.
- Why it happens
- Identity claims were accepted without a narrow trust rule.
- How to fix it
- Constrain trusted subjects and provider-side permissions.
- Prevent it next time
- Review issuer, audience, subject, and authorization as separate controls.
Check your understanding
1. A job never prints its secret, but runs a contributor-modified install hook. Is the secret protected?
Show worked solution
No. The hook executes within the jobโs authority and may exfiltrate the secret or use it directly. Run untrusted hooks without release authority, then promote a verified candidate through a separate trusted path that does not execute contributor-controlled scripts.
2. Does a five-minute credential remove the need for least privilege?
Show worked solution
No. A powerful five-minute credential can still perform a destructive action within seconds. Short lifetime limits persistence; narrow permissions limit capability. Both must be paired with trustworthy execution and target restrictions.
Key takeaways
- Trace influence before granting authority.
- Short lifetime, narrow scope, and trusted execution solve different problems.