@@ -3,7 +3,6 @@ package secrets
33import (
44 "context"
55 "fmt"
6- "io/ioutil"
76 "os"
87 "path/filepath"
98 "strings"
@@ -50,7 +49,7 @@ func NewVaultManager(cfg Config) (*VaultManager, error) {
5049func authenticateVault (client * api.Client , cfg Config ) error {
5150 // Try token file first
5251 if tokenFile := cfg .Extra ["VAULT_TOKEN_FILE" ]; tokenFile != "" {
53- token , err := ioutil . ReadFile (tokenFile )
52+ token , err := readSecretFile (tokenFile )
5453 if err != nil {
5554 return fmt .Errorf ("failed to read token file %s: %w" , tokenFile , err )
5655 }
@@ -82,7 +81,7 @@ func authenticateVault(client *api.Client, cfg Config) error {
8281
8382// authenticateKubernetes performs Kubernetes-based authentication
8483func authenticateKubernetes (client * api.Client , tokenFile , role string ) error {
85- jwt , err := ioutil . ReadFile (tokenFile )
84+ jwt , err := readSecretFile (tokenFile )
8685 if err != nil {
8786 return fmt .Errorf ("failed to read service account token: %w" , err )
8887 }
@@ -201,3 +200,29 @@ func fileExists(filename string) bool {
201200 _ , err := os .Stat (filename )
202201 return err == nil
203202}
203+
204+ func readSecretFile (path string ) ([]byte , error ) {
205+ sanitized , err := sanitizePath (path )
206+ if err != nil {
207+ return nil , err
208+ }
209+ return os .ReadFile (sanitized )
210+ }
211+
212+ func sanitizePath (path string ) (string , error ) {
213+ trimmed := strings .TrimSpace (path )
214+ if trimmed == "" {
215+ return "" , fmt .Errorf ("path is empty" )
216+ }
217+
218+ cleaned := filepath .Clean (trimmed )
219+ if ! filepath .IsAbs (cleaned ) {
220+ return "" , fmt .Errorf ("path must be absolute: %s" , path )
221+ }
222+
223+ if strings .Contains (cleaned , ".." ) {
224+ return "" , fmt .Errorf ("path contains traversal: %s" , path )
225+ }
226+
227+ return cleaned , nil
228+ }
0 commit comments