From 460e8fc1ffdfbd0198b586f64321473eec45f269 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Wed, 24 Jan 2018 19:57:49 -0500 Subject: [PATCH] Don't allow non-printable characters in the API client's token (#3841) --- api/client.go | 10 ++++++++++ api/client_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/api/client.go b/api/client.go index 684b549f26..ff18b5b68b 100644 --- a/api/client.go +++ b/api/client.go @@ -12,6 +12,7 @@ import ( "strings" "sync" "time" + "unicode" "github.com/hashicorp/errwrap" "github.com/hashicorp/go-cleanhttp" @@ -530,8 +531,17 @@ func (c *Client) RawRequest(r *Request) (*Response, error) { c.modifyLock.RLock() c.config.modifyLock.RLock() defer c.config.modifyLock.RUnlock() + token := c.token c.modifyLock.RUnlock() + // Sanity check the token before potentially erroring from the API + idx := strings.IndexFunc(token, func(c rune) bool { + return !unicode.IsPrint(c) + }) + if idx != -1 { + return nil, fmt.Errorf("Configured Vault token contains non-printable characters and cannot be used.") + } + redirectCount := 0 START: req, err := r.ToHTTP() diff --git a/api/client_test.go b/api/client_test.go index 4bd0afec8e..4b57b8f077 100644 --- a/api/client_test.go +++ b/api/client_test.go @@ -5,6 +5,7 @@ import ( "io" "net/http" "os" + "strings" "testing" "time" ) @@ -95,6 +96,30 @@ func TestClientToken(t *testing.T) { } } +func TestClientBadToken(t *testing.T) { + handler := func(w http.ResponseWriter, req *http.Request) {} + + config, ln := testHTTPServer(t, http.HandlerFunc(handler)) + defer ln.Close() + + client, err := NewClient(config) + if err != nil { + t.Fatalf("err: %s", err) + } + + client.SetToken("foo") + _, err = client.RawRequest(client.NewRequest("PUT", "/")) + if err != nil { + t.Fatal(err) + } + + client.SetToken("foo\u007f") + _, err = client.RawRequest(client.NewRequest("PUT", "/")) + if err == nil || !strings.Contains(err.Error(), "printable") { + t.Fatalf("expected error due to bad token") + } +} + func TestClientRedirect(t *testing.T) { primary := func(w http.ResponseWriter, req *http.Request) { w.Write([]byte("test"))