Skip to content

bug: Vault secret shell escaping incomplete — $(), semicolons, and pipes are interpreted #430

@stack72

Description

@stack72

Summary

The shell escaping fix in commit 878e8de for vault secrets is incomplete. While backtick command substitution is properly escaped, three other shell metacharacter classes are still interpreted when vault secrets are injected into sh -c commands:

Metacharacter Vault secret value Expected output Actual behavior
$() value$(whoami)end literal value$(whoami)end $(whoami) is expanded
; value; echo injected literal value; echo injected ; splits into two commands
| value| cat /etc/passwd literal value| cat /etc/passwd | pipes to second command
` value`whoami`end literal value`whoami`end correctly escaped (passes)

Reproduction

For each case:

  1. Create a vault and store a secret with metacharacters:
    swamp vault create local_encryption test-vault
    swamp vault put test-vault "METACHAR_SECRET=value$(whoami)end"
    
  2. Install a model that echoes the secret:
    globalArguments:
      run: "echo ${{ vault.get('test-vault', 'METACHAR_SECRET') }}"
  3. Execute the model:
    swamp model method run vault-echo-metachar execute
    
  4. The output contains the expanded/injected result instead of the literal string.

Expected behavior

All shell metacharacters in vault secret values should be properly escaped before being passed to sh -c. The resolved secret should appear literally in the output, regardless of what characters it contains.

Root cause

The escaping fix from 878e8de handles backticks but does not escape $, ;, or |. The secret value likely needs to be single-quoted or fully shell-escaped before interpolation into the sh -c command string.

Security impact

An attacker who can write to a vault (or a user who stores a password containing shell metacharacters) can achieve arbitrary command execution through the shell interpolation path. This is particularly dangerous because vault secrets are expected to contain arbitrary values.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    betaIssues required to close out before public betabugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions