0.57 Upgrade Guide

An upgrade guide that addresses breaking changes in 0.57.0

by

Vector breaking changes

  1. Environment variable interpolation disabled by default
  2. Template confinement for sink routing templates

Vector upgrade guide

Environment variable interpolation disabled by default

Environment variable interpolation in configuration files is now disabled by default. Previously, Vector automatically interpolated ${VAR} references found in config files.

The --disable-env-var-interpolation flag and VECTOR_DISABLE_ENV_VAR_INTERPOLATION environment variable have also been removed and should no longer be used.

Action needed

If your configuration relies on ${VAR} interpolation, pass --dangerously-allow-env-var-interpolation or set VECTOR_DANGEROUSLY_ALLOW_ENV_VAR_INTERPOLATION=true to restore the previous behavior:

Old (interpolation was on by default)
vector --config vector.yaml
New
vector --config vector.yaml --dangerously-allow-env-var-interpolation

If you’d rather not carry the --dangerously-allow-env-var-interpolation flag, you can keep your existing ${VAR}-based configs by interpolating them yourself with a pre-processing tool such as envsubst before handing the result to Vector. Note that envsubst only expands plain $VAR and ${VAR} references; it does not understand Vector’s extended syntax such as ${VAR:-default} or ${VAR:?error}, which will be passed through unchanged. See the environment variables reference for more details.

If you’re using environment variable interpolation specifically to inject secrets (API keys, passwords, tokens), the secrets backend is the recommended replacement rather than envsubst or the --dangerously-allow-env-var-interpolation flag. It retrieves secrets from a dedicated provider (file, exec, AWS Secrets Manager, etc.) at load time instead of relying on process environment variables.

Template confinement for sink routing templates

Sinks that accept {{ field }} references in routing templates (for example, object keys, file paths, HTTP headers, or table/stream names) now enforce a confinement boundary: the rendered value must stay within the literal prefix declared in the template. Templates with no literal prefix (e.g. key_prefix: "{{ host }}/") are rejected at startup. The file sink is the only exception: its base_dir config field can provide an explicit confinement root for path templates with no usable literal prefix.

This affects the following sinks: aws_s3, azure_blob, gcp_cloud_storage, webhdfs, file, elasticsearch, kafka, http, axiom, opentelemetry, splunk_hec_logs, splunk_hec_metrics, humio_logs, humio_metrics, loki, clickhouse, doris, redis, amqp, pulsar, mqtt, nats, greptimedb_logs, aws_cloudwatch_logs, gcp_stackdriver_logs, and prometheus_remote_write.

HTTP-family sinks have additional restrictions on URI and header templates to prevent request smuggling.

Templates are confined as soon as they have a literal prefix. For example, a kafka sink with topic: "logs-{{ log_topic }}" is already confined by the logs- prefix and requires no changes. The confinement check will fail on fully dynamic templates like topic: "{{ log_topic }}". To fix or restore the previous behavior, consult the “Action needed” sections below.

To verify your configuration after upgrading, run vector validate as it builds each sink as part of validation. An unconfined template will make the command fail validation. Due to a known issue, vector validate --no-environment skips this check; drop the flag if you want confinement errors to be caught.

For example, a kafka sink with topic: "{{ log_topic }}" fails validation:

$ vector validate /tmp/vector_test_unconfined.yaml
√ Loaded ["/tmp/vector_test_unconfined.yaml"]
√ Transforms configuration

Component errors
----------------
x Sink "kafka_out": template references event fields (["log_topic"]) but has no literal string prefix to derive a confinement base from. Add a static prefix to your template, or set `dangerously_allow_unconfined_template_resolution: true` to opt out.

While topic: "logs-{{ log_topic }}" passes:

$ vector validate /tmp/vector_test_confined.yaml
√ Loaded ["/tmp/vector_test_confined.yaml"]
√ Transforms configuration
√ Component configuration

Watch the component_errors_total{error_type="confinement_failed"} metric after upgrading; it increments (and the offending event is dropped) whenever a rendered template value falls outside its confinement boundary at runtime.

You can restore the previous unconfined behavior by setting dangerously_allow_unconfined_template_resolution: true, which also sets the vector_security_confinement_disabled{component_type=...} metric to 1.

Action needed (file sink)

For the file sink, set the new base_dir config field to define the confinement root explicitly:

Old (file sink)
sinks:
  my_file:
    type: file
    path: "{{ host }}/log.txt"
New (file sink)
sinks:
  my_file:
    type: file
    path: "{{ host }}/log.txt"
    base_dir: "/var/log/vector"

This will prevent writes outside /var/log/vector.

If you want to rely on the previous behavior, which is susceptible to file traversal injection attacks like .host = "../../../etc/shadow", you may also add the dangerously_allow_unconfined_template_resolution parameter.

Old (file sink)
sinks:
  my_file:
    type: file
    path: "{{ host }}/log.txt"
New (file sink)
sinks:
  my_file:
    type: file
    path: "{{ host }}/log.txt"
    dangerously_allow_unconfined_template_resolution: true

Action needed (all affected sinks)

For all affected sinks, you can add a static prefix directly to the template instead. For example, for the aws_s3 sink:

Old
sinks:
  my_s3:
    type: aws_s3
    bucket: my-bucket
    key_prefix: "{{ host }}/"
New
sinks:
  my_s3:
    type: aws_s3
    bucket: my-bucket
    key_prefix: "logs/{{ host }}/"

To keep the unconfined behavior and accept the associated risks, set the dangerously_allow_unconfined_template_resolution parameter instead.

Old
sinks:
  my_s3:
    type: aws_s3
    bucket: my-bucket
    key_prefix: "{{ host }}/"
New
sinks:
  my_s3:
    type: aws_s3
    bucket: my-bucket
    key_prefix: "{{ host }}/"
    dangerously_allow_unconfined_template_resolution: true