Variable protection
Process variables often carry sensitive data, such as card numbers or personal details. By default, variable values are exported to secondary storage, such as Elasticsearch, OpenSearch, or an RDBMS, where anyone with access to that storage or to the search APIs can read them.
With variable protection, you mark individual variables as sensitive so their values aren't exported to secondary storage. You keep using the variables in your process, and you can still see which variables exist and which are protected.
Variable protection is available from 8.11.0-alpha1 as an alpha feature. In this release, protection is incomplete, and values can still appear in other places. Before you use it for sensitive data, review the known issues and planned changes.
Redact variable values
The REDACT protection mode irrecoverably replaces the value of a variable before it is exported to secondary storage. Searching or reading the variable through the API returns the redacted value, not the original.
The variable itself stays visible in secondary storage, but Camunda redacts its value. You can still access other variable properties, such as name, variableKey, scopeKey, processInstanceKey, tenantId, and metadata.protectionModes.
The original value isn't removed from the engine. Components that work with primary storage still receive it, for example a job worker that activates a job and gets the process variables.
Protect a variable when you create a process instance
To protect a variable, send a POST /v2/process-instances request. In variablesMetadata, add an entry for the variable name and set its protectionModes to ["REDACT"]. For all request fields, see create process instance.
The following request creates a process instance with two variables and protects cardNumber:
{
"processDefinitionId": "payment-process",
"variables": {
"cardNumber": "5500000000000004",
"amount": 120
},
"variablesMetadata": {
"cardNumber": {
"protectionModes": ["REDACT"]
}
}
}
| Property | Description |
|---|---|
variables | The variables to set on the process instance, as a map from variable name to value. |
variablesMetadata | Optional. A map from variable name to its metadata. Variables without an entry aren't protected. Every name must also be in variables, otherwise the request is rejected with a bad request error. |
variablesMetadata.<name>.protectionModes | The protection modes to apply to the variable. Set it to ["REDACT"]. |
Update variables
You can also protect a variable, or change its protection, when you update variables on an element instance. Send a PUT /v2/element-instances/{elementInstanceKey}/variables request and add variablesMetadata next to variables, the same way as when you create a process instance.
If you don't add an entry for a variable, its protection doesn't change. A protected variable stays protected, and an unprotected variable stays unprotected. For all request fields, see update element instance variables.
The following request sets a new value for cardNumber and protects it:
{
"variables": {
"cardNumber": "4111111111111111"
},
"variablesMetadata": {
"cardNumber": {
"protectionModes": ["REDACT"]
}
}
}
The following table shows the result for each combination of existing variable state and request. Not all update cases are finalized. See known issues.
| Variable before the request | You send | What happens |
|---|---|---|
| Doesn't exist | A value, no variablesMetadata entry | The variable is created. Its value isn't redacted. |
| Doesn't exist | A value, REDACT | The variable is created. Its value is redacted. |
| Exists, not protected | The same value, REDACT | The variable is now redacted. Only its metadata changes, not its value. |
| Exists, not protected | A new value, REDACT | The variable gets the new value, and it's redacted. |
| Exists, protected | A new value, no variablesMetadata entry | The variable gets the new value, and it stays redacted. |
| Exists, protected | The same value, no variablesMetadata entry | Nothing changes. |
| Exists, protected | The same value, REDACT | Nothing changes. |
| Exists, protected | Any value, an empty protectionModes list | The redaction is removed. |
| Any | A variablesMetadata entry for a name that isn't in variables | The request is rejected with a bad request error. |
See redacted variables in search results
When you send a POST /v2/variables/search request, the response replaces the value of every protected variable. To tell which variables are protected, check the metadata.protectionModes property of each variable. For request and response details, see search variables.
The following endpoints return metadata.protectionModes:
| Endpoint | API specification |
|---|---|
POST /v2/variables/search | Search variables |
GET /v2/variables/{variableKey} | Get variable |
POST /v2/user-tasks/{userTaskKey}/variables/search | Search user task variables |
POST /v2/user-tasks/{userTaskKey}/effective-variables/search | Search user task effective variables |
For the process instance created above, the search response looks like this:
{
"items": [
{
"value": "null",
"isTruncated": false,
"name": "cardNumber",
"tenantId": "<default>",
"variableKey": 2251799813685328,
"scopeKey": 2251799813685327,
"processInstanceKey": 2251799813685327,
"rootProcessInstanceKey": 2251799813685327,
"metadata": {
"protectionModes": ["REDACT"]
}
},
{
"value": "120",
"isTruncated": false,
"name": "amount",
"tenantId": "<default>",
"variableKey": 2251799813685346,
"scopeKey": 2251799813685345,
"processInstanceKey": 2251799813685345,
"rootProcessInstanceKey": 2251799813685345,
"metadata": {
"protectionModes": []
}
}
]
}
| Property | Protected variable (cardNumber) | Unprotected variable (amount) |
|---|---|---|
value | "null" | "120" |
metadata.protectionModes | ["REDACT"] | [] |
To list only protected or only unprotected variables, use the protectionMode filter in the variables search request. For all request and response fields, see the search variables API specification.
The redacted value is currently the string "null". Check metadata.protectionModes to detect a protected variable. See known issues.
Known issues and planned changes
The following limitations apply to 8.11.0-alpha1. They are planned to be addressed in later 8.11 releases.
Redaction doesn't cover every place a value can appear
Variable values can be carried by many records and endpoints beyond variable search. In 8.11.0-alpha1, don't rely on REDACT to keep a value out of the following places:
- Responses and records that contain variable lists, such as job activation, job completion, user task completion, message publication and correlation, signal broadcast, and process instance results.
- Records that quote a variable value in free text, such as incident error messages, job error messages, and decision evaluation failure messages.
- Values derived from a variable, such as decision inputs and outputs, FEEL expression results, message correlation keys, and multi-instance input collections.
- The process instance creation request and response.
Consider these limitations when you decide which variables to protect. For example, avoid using a protected variable as a message correlation key or as the input of a decision.
Update behavior is not finalized
Some cases of updating variables aren't finalized, for example removing protection from a variable. They can change before the final release.
The redacted value is the string "null"
In 8.11.0-alpha1, the search response returns a redacted value as the string "null". This placeholder might change in a later release. Don't rely on the value to detect redaction. Use metadata.protectionModes instead, so your integration keeps working after any change.