> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tracecat.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Secrets

> Create, scope, and reference Tracecat secrets in workflows and agents: store API keys safely and inject them into actions through expressions.

## Overview

Secrets store sensitive values. Create them in `/credentials`.

<img src="https://mintcdn.com/tracecat/9IEnC4OWdnuB3EvN/img/automations/create-secret.png?fit=max&auto=format&n=9IEnC4OWdnuB3EvN&q=85&s=865f6171d813b25bec0a715c20b214b6" alt="Create secret" width="3440" height="1906" data-path="img/automations/create-secret.png" />

## Using secrets in expressions

Access a secret in expressions with:

```yaml theme={null}
${{ SECRETS.<secret_name>.<key> }}
```

## Secret types

Tracecat supports these workspace secret types:

| Type           | Value     | Description                              |
| -------------- | --------- | ---------------------------------------- |
| Custom         | `custom`  | Arbitrary key-value credentials          |
| SSH key        | `ssh_key` | A single SSH private key                 |
| mTLS           | `mtls`    | A TLS client certificate and private key |
| CA certificate | `ca_cert` | A CA certificate bundle                  |

### Custom credentials

Custom credentials store arbitrary key-value pairs. Any keys can be used.

### Structured secret types

SSH key, mTLS, and CA certificate secrets use fixed key names.
The credentials UI renders a specialized form for each type (e.g. a PEM textarea for SSH keys instead of generic key-value inputs).

| Type           | Required keys                        |
| -------------- | ------------------------------------ |
| SSH key        | `PRIVATE_KEY`                        |
| mTLS           | `TLS_CERTIFICATE`, `TLS_PRIVATE_KEY` |
| CA certificate | `CA_CERTIFICATE`                     |

Structured secret types cannot have `optional_keys`. The key set is fixed by the type.

## SQL action credentials

`core.sql.execute_query` uses a secret named `sql` with one required key: `CONNECTION_URL`.

Set `CONNECTION_URL` as a SQLAlchemy database URL:

```text theme={null}
postgresql+psycopg://user:pass@db.example.com:5432/app
```

Common engine examples:

* PostgreSQL (psycopg3): `postgresql+psycopg://user:pass@db.example.com:5432/app`
* MySQL: `mysql+pymysql://user:pass@db.example.com:3306/app`
* ClickHouse: `clickhouse+http://user:pass@clickhouse.example.com:8123/default`

See SQLAlchemy Database URLs for supported dialect and driver formats:
[https://docs.sqlalchemy.org/20/core/engines.html#database-urls](https://docs.sqlalchemy.org/20/core/engines.html#database-urls)

## AWS credentials

### Protected secret names

`aws` and `amazon_s3` are **protected** secret names.
When a secret with either name contains `AWS_ROLE_ARN`, Tracecat automatically performs STS `AssumeRole` on the host before sandbox entry and injects temporary session credentials.
This applies to any registry action (built-in or custom) that declares a secret with one of these names.

`tools.aws_boto3` actions use the `aws` secret. `tools.amazon_s3` actions use the `amazon_s3` secret. Both follow the same key schema.

### Supported keys

* `AWS_ROLE_ARN` — recommended; Tracecat assumes the role on the host
* `AWS_ROLE_SESSION_NAME` — optional audit session label
* `AWS_ACCESS_KEY_ID`
* `AWS_SECRET_ACCESS_KEY`
* `AWS_SESSION_TOKEN`
* `AWS_REGION`

### Credential resolution order

1. `AWS_ROLE_ARN` (STS AssumeRole with auto-injected `TRACECAT_AWS_EXTERNAL_ID`)
2. `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY` + `AWS_SESSION_TOKEN`
3. `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY`

## Google credentials

Google Workspace actions resolve credentials from a chain and use the first credential that exists. An integration that is configured but not connected has no token, so the chain moves on to the next source. The chain is a priority order, not failover: an expired or revoked connection keeps its place, so re-authorize or disconnect it to move on.

### Credential resolution order

Workspace app actions (`tools.google_drive`, `tools.gmail`, `tools.google_sheets`, `tools.google_docs`, `tools.google_slides`, `tools.google_forms`):

1. The service's user OAuth integration (`authorization_code`), such as `google_drive` with `${{ SECRETS.google_drive_oauth.GOOGLE_DRIVE_USER_TOKEN }}`.
2. The service's service-account integration (`client_credentials`), such as `google_drive` with `${{ SECRETS.google_drive_oauth.GOOGLE_DRIVE_SERVICE_TOKEN }}`. Set a subject on the integration for domain-wide delegation.
3. The `google_api` credential, key `GOOGLE_API_CREDENTIALS`, with domain-wide delegation through `GOOGLE_API_SUBJECT`.
4. The `google` (Google Cloud) service-account integration, token `GOOGLE_SERVICE_TOKEN`.

Directory and Reports actions (`tools.google_directory`, `tools.google_reports`):

1. The `google_admin` user OAuth integration (`authorization_code`), `${{ SECRETS.google_admin_oauth.GOOGLE_ADMIN_USER_TOKEN }}`. The signed-in account must be a Workspace administrator.
2. The `google_admin` service-account integration (`client_credentials`), `${{ SECRETS.google_admin_oauth.GOOGLE_ADMIN_SERVICE_TOKEN }}`, with domain-wide delegation through its subject.
3. The `google_api` credential, key `GOOGLE_API_CREDENTIALS`, with domain-wide delegation through `GOOGLE_API_SUBJECT`.
4. The `google` (Google Cloud) service-account integration, token `GOOGLE_SERVICE_TOKEN`.

Alert Center actions (`tools.google_alert_center`) start at step 2: the Alert Center API requires a service account with domain-wide delegation.

### Supported keys

The `google_api` credential is a workspace secret with these keys:

* `GOOGLE_API_CREDENTIALS` — the service account JSON key, as a string
* `GOOGLE_API_SUBJECT` — optional; the user email to impersonate with domain-wide delegation

A `subject` key inside the JSON works too. `GOOGLE_API_SUBJECT` wins over it.

Service-account OAuth integrations take the JSON key as the client secret. The configure dialog has an assume user toggle that records the delegation subject, and one integration has one subject. To impersonate different users per action, call `tools.google_api.call_api` directly and pass `subject`; this needs the `google_api` credential.

## Secret environments

Use secret environments to organize credentials by the boundary that matters to
your workflow, not only by deployment stage. An environment can represent a
customer or tenant, an application identity and its permission set, a
deployment target, or another credential boundary.

Set a workflow's default environment in [Workflows](/automations/workflows).
When an action references a secret, Tracecat resolves it from that environment
unless the action overrides it. If neither is set, Tracecat uses `default`.

Use an action's [environment override](/automations/actions) to select a
different environment. The override can be a literal name or a template
expression that resolves at run time, so you can reuse one workflow for
different credential contexts.

Use environments to separate:

* CrowdStrike MSSP customers or tenant IDs, such as `customer_acme` and `customer_globex`
* Slack apps installed in different workspaces or granted different bot scopes
* Google service accounts with different OAuth scopes
* Sandbox and production credentials for the same provider

Use a template override when trigger data selects the credential context:

```yaml theme={null}
- ref: notify_customer
  action: tools.slack.post_message
  environment: ${{ TRIGGER.customer_environment }}
  args:
    channel: ${{ SECRETS.slack.ALERTS_CHANNEL }}
    text: "New finding: ${{ TRIGGER.finding_id }}"
```

In this example, the action resolves the `slack` secret from the environment
named by `TRIGGER.customer_environment`.

## Access secrets in agents

Agents can use secret expressions in tool arguments and integration configuration. Secret values are resolved during tool execution and are not sent to the LLM provider.

<CodeGroup>
  ```text theme={null}
  When you call Slack tools, use `${{ SECRETS.slack.SLACK_BOT_TOKEN }}`.
  When you call Jira tools, use `${{ SECRETS.jira.JIRA_API_TOKEN }}`.
  Do not print secret values in the final answer.
  ```
</CodeGroup>

## Custom registry actions

Authors of [Python UDFs](/custom-actions/python-udf) and [YAML templates](/custom-actions/yaml-template) declare required secrets in the registry (including OAuth and structured secret types). The same `${{ SECRETS... }}` syntax applies; see [Use OAuth tokens in expressions](/automations/integrations/oauth-integrations#use-oauth-tokens-in-expressions) on the OAuth page for token paths, `RegistryOAuthSecret` and YAML `type: oauth`, and Custom OAuth `provider_id` rules.

## Related pages

* See [Pre-built credentials](/automations/integrations/prebuilt-credentials) for provider-specific credential templates for built-in integrations.
* See [OAuth](/automations/integrations/oauth-integrations) for integrations that authenticate with OAuth flows.
* See [MCP](/automations/integrations/mcp-integrations) for MCP integrations and secure environment-based settings.
* See [Expressions](/automations/core-concepts/expressions) for how expressions work across triggers, actions, secrets, and variables.
