Skip to content

feat(config)!: parse config first, then interpolate into string leaves#25905

Draft
pront wants to merge 1 commit into
masterfrom
pront/interpolation-after-parsing-v2
Draft

feat(config)!: parse config first, then interpolate into string leaves#25905
pront wants to merge 1 commit into
masterfrom
pront/interpolation-after-parsing-v2

Conversation

@pront

@pront pront commented Jul 20, 2026

Copy link
Copy Markdown
Member

Summary

Implements RFC #25603: Vector now parses configuration files into a typed value tree before performing environment variable (${VAR}) and SECRET[...] substitution.

Key changes:

  • Interpolation operates only on string-typed leaves in the parsed tree, closing a structural injection vulnerability where env var values containing YAML special characters could corrupt the parse
  • A JSON-Schema-driven coercion pass converts string scalars to the types declared by each component (int, bool, float), so count = "${MY_COUNT}" with MY_COUNT=42 works correctly
  • Removes the old pre-parse string-substitution path (src/config/vars.rs deleted)
  • set_env_var_interpolation() / env_var_interpolation_enabled() global OnceLock controls interpolation (same pattern as master's --dangerously-allow-env-var-interpolation flag)
  • The HTTP provider, validate, and vector config commands all use the same global flag consistently

Vector configuration

Before (TOML, now rejected):

[sources.in]
type = "demo_logs"
count = ${MY_COUNT}

After (TOML, quoted form works and coerces to int):

[sources.in]
type = "demo_logs"
count = "${MY_COUNT}"

YAML is unaffected: count: ${MY_COUNT} continues to work (YAML parses ${VAR} as a string scalar and the coercion pass converts it to the declared type).

How did you test this PR?

  • Unit tests in src/config/loading/interpolation.rs and schema_coercion.rs
  • Existing config loading unit tests pass
  • Manually validated with cargo run -- validate against YAML/TOML/JSON configs with env var and secret placeholders

Change Type

  • Bug fix
  • New feature
  • Dependencies
  • Non-functional (chore, refactoring, docs)
  • Performance

Is this a breaking change?

  • Yes
  • No

Does this PR include user facing changes?

  • Yes. Please add a changelog fragment based on our guidelines.
  • No. A maintainer will apply the no-changelog label to this PR.

References

Inverts the order of config loading and interpolation: Vector now parses
YAML/TOML/JSON into a typed value tree first, then substitutes
environment variables and secrets only into string-typed leaves.

This closes the structural injection bug where env var values containing
YAML/TOML special characters (quotes, `>`, escape sequences) could corrupt
the parse. Previously a value like `password: ${PASS}` with PASS=fo">bar
would silently produce malformed config; now the substitution operates on
an already-valid tree and the value is treated as a plain string.

Breaking change: `${VAR}` and `SECRET[...]` placeholders must appear
inside quoted strings. Unquoted usages in TOML/JSON now emit a hint
pointing to the required quoting. YAML configs are generally unaffected
because YAML string detection is implicit.

Authors: pront
@pront
pront force-pushed the pront/interpolation-after-parsing-v2 branch from c039afc to b5706ef Compare July 20, 2026 18:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Environment variable substitution and YAML special characters

1 participant