Guides / Use secrets
Verified against Flow 5.0.0-beta.39
A secret is a parameter whose value Flow hides in the webapp, in API reads and in task logs, and encrypts where it's stored. This guide covers where to keep a secret, how a task reads it, how to change it, and what Flow can't protect. It's for workflow authors.
| Where | Create it in | Tasks read it as | Use it when |
|---|---|---|---|
| A secured workspace parameter | Parameters in the side nav | $(workspace.params.<name>) |
Several workflows in one workspace use the same credential |
| A secured global parameter | Admin › Parameters | $(global.params.<name>) |
Every workspace uses it |
| A workflow parameter of type Password | The editor's Parameters tab | $(params.<name>) |
One workflow owns it, or a person supplies it at each run |
| A task field of type Password | The task's form | (the task reads its own field) | A task asks for a credential, such as Github Access Token |
| A parameter an integration shares | Integrations | $(workspace.params.github-token), $(workspace.params.slack-token) |
GitHub or Slack, which fill the credential when you connect them, or Google or Microsoft, which take it in a form. See Connect GitHub and Integrations |
Prefer a workspace or global secret over typing a value into a task field. The workflow then holds only a reference, so exporting or duplicating it copies no secret.
deploy-token. Tasks read it as $(workspace.params.deploy-token).Deploy token.The message Parameter Created appears. The table lists deploy-token with the value ****** and a purple Secured tag.

A secured global parameter is the same, from Admin › Parameters.
Reference the secret wherever a task takes text. This example calls a service with the token.
In the editor's Canvas tab, drag Execute Shell onto the canvas and select its edit icon.
In Task name, enter call-api.
Select Shell Script, enter the script below with your service's URL, and select Update:
curl -fsS -H "Authorization: Bearer $(workspace.params.deploy-token)" https://deploy.example.com/api/healthSelect Apply, link Start to call-api and call-api to End, and save a version.
On the Workflows page, select Run it, then Run and View.
The run's status is Succeeded. In the task's View Details, the script parameter reads ******: once the token was substituted in, the script became a secret too. Wherever the token appears in the task's log, Flow shows *****.
The editor keeps showing $(workspace.params.deploy-token), because the workflow stores the reference, never the value. In a Password field, a value that is exactly one reference also shows as written.
api-key and choose the Type Password.$(workspace.params.deploy-token).$(params.api-key) in your tasks.When someone selects Run it, Workflow Parameters asks for the value in a masked field. If the parameter has a stored default, the field starts empty with Leave blank to use the stored default.
Through the API, send a run parameter with type: secret to make it a secret. Its value must be a string, or the request fails with PARAM_SECRET_NOT_STRING.
******. In the API, it reads as *****, and an unset one reads as nothing.postgres://app:$(params.db-password)@db is masked like the password it contains.***** in task logs, results, status messages and manual task instructions.To change a secret in the webapp, select Edit on its row. The field shows the placeholder Set and Set. Type a new value to replace it.
Through the API, every layer that holds a secret reads a write the same way:
| You send | Flow |
|---|---|
*****, null, or no value |
Keeps the stored secret |
"" |
Clears it |
| Anything else | Replaces it |
On a JSON Merge Patch, such as PATCH /api/v2/parameters/{name} for a global parameter, null clears the secret instead: send ***** or leave the member out to keep it. On a run request, ***** for a secret keeps its declared default.
After you change a workspace or global secret, tasks that start from then on get the new value, within 10 seconds on every Flow instance. Tasks already started keep the value they started with.
Warning
A task's container receives every secret in plain text: as the environment variable PARAM_<NAME>, and wherever a reference was substituted into its script, command, arguments or environment. Anyone who can read the task's pod in Kubernetes can read them, and on the Tekton executor they're in the TaskRun object too. Use secrets only with task images you trust, because the image can send the value anywhere.
no such workspace param 'deploy-token'?*****?PARAM_<NAME>.