windmill-labs/windmill · error

Invalid vault_id `{value}`: expected `label@filename` using

Error message

Invalid vault_id `{value}`: expected `label@filename` using only letters, digits and the characters `.`, `_`, `-`, `/`, `@`

What it means

validate_vault_id enforces the ansible-vault id format `label@filename` and a conservative character set: non-empty, only ASCII alphanumerics plus `.`, `_`, `-`, `/`, `@`. Anything else (spaces, unicode, empty string) is rejected with this message.

Source

Thrown at backend/parsers/windmill-parser-yaml/src/lib.rs:463

        }
    }

    Ok(DelegateWithSSHAuth { delegate_to_git_repo_details: None, git_ssh_identity })
}

/// Each `vault_id` entry is interpolated verbatim into the generated `ansible.cfg`
/// (`vault_identity_list = <a>,<b>,...`). A newline or other config-meaningful
/// character would let a script inject arbitrary `[defaults]` directives (e.g.
/// `library`, `action_plugins`) and execute attacker-controlled code on the worker,
/// and a `,` would smuggle in an extra entry. Restrict entries to the `label@source`
/// charset so neither is possible.
pub fn validate_vault_id(value: &str) -> anyhow::Result<()> {
    let is_valid = !value.is_empty()
        && value
            .chars()
            .all(|c| c.is_ascii_alphanumeric() || matches!(c, '.' | '_' | '-' | '/' | '@'));
    if !is_valid {
        return Err(anyhow!(
            "Invalid vault_id `{value}`: expected `label@filename` using only letters, digits and the characters `.`, `_`, `-`, `/`, `@`"
        ));
    }
    Ok(())
}

pub fn parse_ansible_reqs(
    inner_content: &str,
) -> anyhow::Result<(String, Option<AnsibleRequirements>, String)> {
    let mut logs = String::new();
    let docs = YamlLoader::load_from_str(inner_content)
        .map_err(|e| anyhow!("Failed to parse yaml: {}", e))?;

    let mut ret = AnsibleRequirements::default();

    if let Yaml::Hash(doc) = &docs[0] {
        if let Some(v) = doc.get(&Yaml::String("delegate_to_git_repo".to_string())) {
            ret.delegate_to_git_repo = extract_delegate_to_git_repo_details(v);

View on GitHub (pinned to e474e8803c)

Solutions

  1. Format the value as `label@filename` with no spaces.
  2. Remove or replace forbidden characters (spaces, colons, unicode) in label and filename.
  3. Check that the variable feeding the vault_id is actually set and non-empty.

Example fix

// before
vault_id: "my vault@file name"
// after
vault_id: "myvault@filename"
Defensive patterns

Strategy: validation

Validate before calling

fn valid_vault_id(v: &str) -> bool {
    !v.is_empty() && v.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '.' | '_' | '-' | '/' | '@'))
}

Type guard

fn is_valid_vault_id(s: &str) -> bool {
    !s.is_empty() && s.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '.' | '_' | '-' | '/' | '@'))
}

Try / catch

if let Err(e) = validate_vault_id(candidate) {
    eprintln!("{e}; using fallback");
    // sanitize: strip disallowed chars, rebuild label@filename
}

Prevention

When it happens

Trigger: parse_ansible_reqs, create_ansible_cfg, or build_ansible_cfg_override_envs calls validate_vault_id with a vault_id string containing forbidden characters — typically a space or empty value.

Common situations: Writing a vault id with a space after the `@`, using an environment variable that is unset/empty, or including special shell characters in the label.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/17262cf73e8c997e. Report an issue: GitHub.