Moderate severityNVD Advisory· Published Feb 1, 2024· Updated Feb 13, 2025
Vault May Expose Sensitive Information When Configuring An Audit Log Device
CVE-2024-0831
Description
Vault and Vault Enterprise (“Vault”) may expose sensitive information when enabling an audit device which specifies the log_raw option, which may log sensitive information to other audit devices, regardless of whether they are configured to use log_raw.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/hashicorp/vaultGo | >= 1.15.0, < 1.15.5 | 1.15.5 |
Affected products
2- HashiCorp/Vault Enterprisev5Range: 1.15.0
Patches
12a72f2a8a5b5VAULT-23122: Audit fix for 'log_raw' issue (#24968) (#24974)
10 files changed · +461 −79
audit/entry_formatter.go+20 −4 modified@@ -80,7 +80,7 @@ func (f *EntryFormatter) Process(ctx context.Context, e *eventlogger.Event) (*ev return nil, fmt.Errorf("%s: event is nil: %w", op, event.ErrInvalidParameter) } - a, ok := e.Payload.(*auditEvent) + a, ok := e.Payload.(*AuditEvent) if !ok { return nil, fmt.Errorf("%s: cannot parse event payload: %w", op, event.ErrInvalidParameter) } @@ -155,10 +155,26 @@ func (f *EntryFormatter) Process(ctx context.Context, e *eventlogger.Event) (*ev result = append([]byte(f.prefix), result...) } - // Store the final format. - e.FormattedAs(f.config.RequiredFormat.String(), result) + // Copy some properties from the event (and audit event) and store the + // format for the next (sink) node to Process. + a2 := &AuditEvent{ + ID: a.ID, + Version: a.Version, + Subtype: a.Subtype, + Timestamp: a.Timestamp, + Data: data, // Use the cloned data here rather than a pointer to the original. + } + + e2 := &eventlogger.Event{ + Type: e.Type, + CreatedAt: e.CreatedAt, + Formatted: make(map[string][]byte), // we are about to set this ourselves. + Payload: a2, + } + + e2.FormattedAs(f.config.RequiredFormat.String(), result) - return e, nil + return e2, nil } // FormatRequest attempts to format the specified logical.LogInput into a RequestEntry.
audit/entry_formatter_test.go+408 −43 modified@@ -5,49 +5,23 @@ package audit import ( "context" + "encoding/json" + "errors" + "fmt" + "strings" "testing" "time" - "github.com/hashicorp/vault/internal/observability/event" - + "github.com/hashicorp/eventlogger" "github.com/hashicorp/vault/helper/namespace" - + "github.com/hashicorp/vault/internal/observability/event" + "github.com/hashicorp/vault/sdk/helper/jsonutil" + "github.com/hashicorp/vault/sdk/helper/salt" "github.com/hashicorp/vault/sdk/logical" - - "github.com/hashicorp/eventlogger" + "github.com/mitchellh/copystructure" "github.com/stretchr/testify/require" ) -// fakeEvent will return a new fake event containing audit data based on the -// specified subtype, format and logical.LogInput. -func fakeEvent(tb testing.TB, subtype subtype, format format, input *logical.LogInput) *eventlogger.Event { - tb.Helper() - - date := time.Date(2023, time.July, 11, 15, 49, 10, 0o0, time.Local) - - auditEvent, err := NewEvent(subtype, - WithID("123"), - WithNow(date), - ) - require.NoError(tb, err) - require.NotNil(tb, auditEvent) - require.Equal(tb, "123", auditEvent.ID) - require.Equal(tb, "v0.1", auditEvent.Version) - require.Equal(tb, subtype, auditEvent.Subtype) - require.Equal(tb, date, auditEvent.Timestamp) - - auditEvent.Data = input - - e := &eventlogger.Event{ - Type: eventlogger.EventType(event.AuditType), - CreatedAt: auditEvent.Timestamp, - Formatted: make(map[string][]byte), - Payload: auditEvent, - } - - return e -} - // TestNewEntryFormatter ensures we can create new EntryFormatter structs. func TestNewEntryFormatter(t *testing.T) { tests := map[string]struct { @@ -297,7 +271,7 @@ func TestEntryFormatter_Process(t *testing.T) { tc := tc t.Run(name, func(t *testing.T) { t.Parallel() - e := fakeEvent(t, tc.Subtype, tc.RequiredFormat, tc.Data) + e := fakeEvent(t, tc.Subtype, tc.Data) require.NotNil(t, e) ss := newStaticSalt(t) @@ -317,18 +291,16 @@ func TestEntryFormatter_Process(t *testing.T) { } processed, err := f.Process(ctx, e) - b, found := e.Format(string(tc.RequiredFormat)) switch { case tc.IsErrorExpected: require.Error(t, err) require.EqualError(t, err, tc.ExpectedErrorMessage) require.Nil(t, processed) - require.False(t, found) - require.Nil(t, b) default: require.NoError(t, err) require.NotNil(t, processed) + b, found := processed.Format(string(tc.RequiredFormat)) require.True(t, found) require.NotNil(t, b) } @@ -381,20 +353,413 @@ func BenchmarkAuditFileSink_Process(b *testing.B) { require.NotNil(b, sink) // Generate the event - event := fakeEvent(b, RequestType, JSONFormat, in) - require.NotNil(b, event) + e := fakeEvent(b, RequestType, in) + require.NotNil(b, e) b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { - event, err = formatter.Process(ctx, event) + e2, err := formatter.Process(ctx, e) if err != nil { panic(err) } - _, err := sink.Process(ctx, event) + _, err = sink.Process(ctx, e2) if err != nil { panic(err) } } }) } + +// TestEntryFormatter_Process_JSON ensures that the JSON output we get matches what +// we expect for the specified LogInput. +func TestEntryFormatter_Process_JSON(t *testing.T) { + ss := newStaticSalt(t) + + expectedResultStr := fmt.Sprintf(testFormatJSONReqBasicStrFmt, ss.salt.GetIdentifiedHMAC("foo")) + + issueTime, _ := time.Parse(time.RFC3339, "2020-05-28T13:40:18-05:00") + cases := map[string]struct { + Auth *logical.Auth + Req *logical.Request + Err error + Prefix string + ExpectedStr string + }{ + "auth, request": { + &logical.Auth{ + ClientToken: "foo", + Accessor: "bar", + DisplayName: "testtoken", + EntityID: "foobarentity", + NoDefaultPolicy: true, + Policies: []string{"root"}, + TokenType: logical.TokenTypeService, + LeaseOptions: logical.LeaseOptions{ + TTL: time.Hour * 4, + IssueTime: issueTime, + }, + }, + &logical.Request{ + Operation: logical.UpdateOperation, + Path: "/foo", + Connection: &logical.Connection{ + RemoteAddr: "127.0.0.1", + }, + WrapInfo: &logical.RequestWrapInfo{ + TTL: 60 * time.Second, + }, + Headers: map[string][]string{ + "foo": {"bar"}, + }, + }, + errors.New("this is an error"), + "", + expectedResultStr, + }, + "auth, request with prefix": { + &logical.Auth{ + ClientToken: "foo", + Accessor: "bar", + EntityID: "foobarentity", + DisplayName: "testtoken", + NoDefaultPolicy: true, + Policies: []string{"root"}, + TokenType: logical.TokenTypeService, + LeaseOptions: logical.LeaseOptions{ + TTL: time.Hour * 4, + IssueTime: issueTime, + }, + }, + &logical.Request{ + Operation: logical.UpdateOperation, + Path: "/foo", + Connection: &logical.Connection{ + RemoteAddr: "127.0.0.1", + }, + WrapInfo: &logical.RequestWrapInfo{ + TTL: 60 * time.Second, + }, + Headers: map[string][]string{ + "foo": {"bar"}, + }, + }, + errors.New("this is an error"), + "@cee: ", + expectedResultStr, + }, + } + + for name, tc := range cases { + cfg, err := NewFormatterConfig(WithHMACAccessor(false)) + require.NoError(t, err) + formatter, err := NewEntryFormatter(cfg, ss, WithPrefix(tc.Prefix)) + require.NoError(t, err) + + in := &logical.LogInput{ + Auth: tc.Auth, + Request: tc.Req, + OuterErr: tc.Err, + } + + // Create an audit event and more generic eventlogger.event to allow us + // to process (format). + auditEvent, err := NewEvent(RequestType) + require.NoError(t, err) + auditEvent.Data = in + + e := &eventlogger.Event{ + Type: eventlogger.EventType(event.AuditType.String()), + CreatedAt: time.Now(), + Formatted: make(map[string][]byte), + Payload: auditEvent, + } + + e2, err := formatter.Process(namespace.RootContext(nil), e) + require.NoErrorf(t, err, "bad: %s\nerr: %s", name, err) + + jsonBytes, ok := e2.Format(JSONFormat.String()) + require.True(t, ok) + require.Positive(t, len(jsonBytes)) + + if !strings.HasPrefix(string(jsonBytes), tc.Prefix) { + t.Fatalf("no prefix: %s \n log: %s\nprefix: %s", name, expectedResultStr, tc.Prefix) + } + + expectedJSON := new(RequestEntry) + + if err := jsonutil.DecodeJSON([]byte(expectedResultStr), &expectedJSON); err != nil { + t.Fatalf("bad json: %s", err) + } + expectedJSON.Request.Namespace = &Namespace{ID: "root"} + + actualJSON := new(RequestEntry) + if err := jsonutil.DecodeJSON(jsonBytes[len(tc.Prefix):], &actualJSON); err != nil { + t.Fatalf("bad json: %s", err) + } + + expectedJSON.Time = actualJSON.Time + + expectedBytes, err := json.Marshal(expectedJSON) + if err != nil { + t.Fatalf("unable to marshal json: %s", err) + } + + if !strings.HasSuffix(strings.TrimSpace(string(jsonBytes)), string(expectedBytes)) { + t.Fatalf("bad: %s\nResult:\n\n%q\n\nExpected:\n\n%q", name, string(jsonBytes), string(expectedBytes)) + } + } +} + +// TestEntryFormatter_Process_JSONx ensures that the JSONx output we get matches what +// we expect for the specified LogInput. +func TestEntryFormatter_Process_JSONx(t *testing.T) { + s, err := salt.NewSalt(context.Background(), nil, nil) + require.NoError(t, err) + tempStaticSalt := &staticSalt{salt: s} + + fooSalted := s.GetIdentifiedHMAC("foo") + issueTime, _ := time.Parse(time.RFC3339, "2020-05-28T13:40:18-05:00") + + cases := map[string]struct { + Auth *logical.Auth + Req *logical.Request + Err error + Prefix string + Result string + ExpectedStr string + }{ + "auth, request": { + &logical.Auth{ + ClientToken: "foo", + Accessor: "bar", + DisplayName: "testtoken", + EntityID: "foobarentity", + NoDefaultPolicy: true, + Policies: []string{"root"}, + TokenType: logical.TokenTypeService, + LeaseOptions: logical.LeaseOptions{ + TTL: time.Hour * 4, + IssueTime: issueTime, + }, + }, + &logical.Request{ + ID: "request", + ClientToken: "foo", + ClientTokenAccessor: "bar", + Operation: logical.UpdateOperation, + Path: "/foo", + Connection: &logical.Connection{ + RemoteAddr: "127.0.0.1", + }, + WrapInfo: &logical.RequestWrapInfo{ + TTL: 60 * time.Second, + }, + Headers: map[string][]string{ + "foo": {"bar"}, + }, + PolicyOverride: true, + }, + errors.New("this is an error"), + "", + "", + fmt.Sprintf(`<json:object name="auth"><json:string name="accessor">bar</json:string><json:string name="client_token">%s</json:string><json:string name="display_name">testtoken</json:string><json:string name="entity_id">foobarentity</json:string><json:boolean name="no_default_policy">true</json:boolean><json:array name="policies"><json:string>root</json:string></json:array><json:string name="token_issue_time">2020-05-28T13:40:18-05:00</json:string><json:number name="token_ttl">14400</json:number><json:string name="token_type">service</json:string></json:object><json:string name="error">this is an error</json:string><json:object name="request"><json:string name="client_token">%s</json:string><json:string name="client_token_accessor">bar</json:string><json:object name="headers"><json:array name="foo"><json:string>bar</json:string></json:array></json:object><json:string name="id">request</json:string><json:object name="namespace"><json:string name="id">root</json:string></json:object><json:string name="operation">update</json:string><json:string name="path">/foo</json:string><json:boolean name="policy_override">true</json:boolean><json:string name="remote_address">127.0.0.1</json:string><json:number name="wrap_ttl">60</json:number></json:object><json:string name="type">request</json:string>`, + fooSalted, fooSalted), + }, + "auth, request with prefix": { + &logical.Auth{ + ClientToken: "foo", + Accessor: "bar", + DisplayName: "testtoken", + NoDefaultPolicy: true, + EntityID: "foobarentity", + Policies: []string{"root"}, + TokenType: logical.TokenTypeService, + LeaseOptions: logical.LeaseOptions{ + TTL: time.Hour * 4, + IssueTime: issueTime, + }, + }, + &logical.Request{ + ID: "request", + ClientToken: "foo", + ClientTokenAccessor: "bar", + Operation: logical.UpdateOperation, + Path: "/foo", + Connection: &logical.Connection{ + RemoteAddr: "127.0.0.1", + }, + WrapInfo: &logical.RequestWrapInfo{ + TTL: 60 * time.Second, + }, + Headers: map[string][]string{ + "foo": {"bar"}, + }, + PolicyOverride: true, + }, + errors.New("this is an error"), + "", + "@cee: ", + fmt.Sprintf(`<json:object name="auth"><json:string name="accessor">bar</json:string><json:string name="client_token">%s</json:string><json:string name="display_name">testtoken</json:string><json:string name="entity_id">foobarentity</json:string><json:boolean name="no_default_policy">true</json:boolean><json:array name="policies"><json:string>root</json:string></json:array><json:string name="token_issue_time">2020-05-28T13:40:18-05:00</json:string><json:number name="token_ttl">14400</json:number><json:string name="token_type">service</json:string></json:object><json:string name="error">this is an error</json:string><json:object name="request"><json:string name="client_token">%s</json:string><json:string name="client_token_accessor">bar</json:string><json:object name="headers"><json:array name="foo"><json:string>bar</json:string></json:array></json:object><json:string name="id">request</json:string><json:object name="namespace"><json:string name="id">root</json:string></json:object><json:string name="operation">update</json:string><json:string name="path">/foo</json:string><json:boolean name="policy_override">true</json:boolean><json:string name="remote_address">127.0.0.1</json:string><json:number name="wrap_ttl">60</json:number></json:object><json:string name="type">request</json:string>`, + fooSalted, fooSalted), + }, + } + + for name, tc := range cases { + cfg, err := NewFormatterConfig( + WithOmitTime(true), + WithHMACAccessor(false), + WithFormat(JSONxFormat.String()), + ) + require.NoError(t, err) + formatter, err := NewEntryFormatter(cfg, tempStaticSalt, WithPrefix(tc.Prefix)) + require.NoError(t, err) + require.NotNil(t, formatter) + + in := &logical.LogInput{ + Auth: tc.Auth, + Request: tc.Req, + OuterErr: tc.Err, + } + + // Create an audit event and more generic eventlogger.event to allow us + // to process (format). + auditEvent, err := NewEvent(RequestType) + require.NoError(t, err) + auditEvent.Data = in + + e := &eventlogger.Event{ + Type: eventlogger.EventType(event.AuditType.String()), + CreatedAt: time.Now(), + Formatted: make(map[string][]byte), + Payload: auditEvent, + } + + e2, err := formatter.Process(namespace.RootContext(nil), e) + require.NoErrorf(t, err, "bad: %s\nerr: %s", name, err) + + jsonxBytes, ok := e2.Format(JSONxFormat.String()) + require.True(t, ok) + require.Positive(t, len(jsonxBytes)) + + if !strings.HasPrefix(string(jsonxBytes), tc.Prefix) { + t.Fatalf("no prefix: %s \n log: %s\nprefix: %s", name, tc.Result, tc.Prefix) + } + + if !strings.HasSuffix(strings.TrimSpace(string(jsonxBytes)), string(tc.ExpectedStr)) { + t.Fatalf( + "bad: %s\nResult:\n\n%q\n\nExpected:\n\n%q", + name, strings.TrimSpace(string(jsonxBytes)), string(tc.ExpectedStr)) + } + } +} + +// TestEntryFormatter_Process_NoMutation tests that the event returned by an +// EntryFormatter.Process method is not the same as the one that it accepted. +func TestEntryFormatter_Process_NoMutation(t *testing.T) { + // Create the formatter node. + cfg, err := NewFormatterConfig() + require.NoError(t, err) + ss := newStaticSalt(t) + formatter, err := NewEntryFormatter(cfg, ss) + require.NoError(t, err) + require.NotNil(t, formatter) + + in := &logical.LogInput{ + Auth: &logical.Auth{ + ClientToken: "foo", + Accessor: "bar", + EntityID: "foobarentity", + DisplayName: "testtoken", + NoDefaultPolicy: true, + Policies: []string{"root"}, + TokenType: logical.TokenTypeService, + }, + Request: &logical.Request{ + Operation: logical.UpdateOperation, + Path: "/foo", + Connection: &logical.Connection{ + RemoteAddr: "127.0.0.1", + }, + WrapInfo: &logical.RequestWrapInfo{ + TTL: 60 * time.Second, + }, + Headers: map[string][]string{ + "foo": {"bar"}, + }, + }, + } + + e := fakeEvent(t, RequestType, in) + + e2, err := formatter.Process(namespace.RootContext(nil), e) + require.NoError(t, err) + require.NotNil(t, e2) + + // Ensure the pointers are different. + require.NotEqual(t, e2, e) + + // Do the same for the audit event in the payload. + a, ok := e.Payload.(*AuditEvent) + require.True(t, ok) + require.NotNil(t, a) + + a2, ok := e2.Payload.(*AuditEvent) + require.True(t, ok) + require.NotNil(t, a2) + + require.NotEqual(t, a2, a) +} + +// hashExpectedValueForComparison replicates enough of the audit HMAC process on a piece of expected data in a test, +// so that we can use assert.Equal to compare the expected and output values. +func (f *EntryFormatter) hashExpectedValueForComparison(input map[string]any) map[string]any { + // Copy input before modifying, since we may re-use the same data in another test + copied, err := copystructure.Copy(input) + if err != nil { + panic(err) + } + copiedAsMap := copied.(map[string]any) + + s, err := f.salter.Salt(context.Background()) + if err != nil { + panic(err) + } + + err = hashMap(s.GetIdentifiedHMAC, copiedAsMap, nil) + if err != nil { + panic(err) + } + + return copiedAsMap +} + +// fakeEvent will return a new fake event containing audit data based on the +// specified subtype, format and logical.LogInput. +func fakeEvent(tb testing.TB, subtype subtype, input *logical.LogInput) *eventlogger.Event { + tb.Helper() + + date := time.Date(2023, time.July, 11, 15, 49, 10, 0o0, time.Local) + + auditEvent, err := NewEvent(subtype, + WithID("123"), + WithNow(date), + ) + require.NoError(tb, err) + require.NotNil(tb, auditEvent) + require.Equal(tb, "123", auditEvent.ID) + require.Equal(tb, "v0.1", auditEvent.Version) + require.Equal(tb, subtype, auditEvent.Subtype) + require.Equal(tb, date, auditEvent.Timestamp) + + auditEvent.Data = input + + e := &eventlogger.Event{ + Type: eventlogger.EventType(event.AuditType), + CreatedAt: auditEvent.Timestamp, + Formatted: make(map[string][]byte), + Payload: auditEvent, + } + + return e +}
audit/event.go+5 −5 modified@@ -12,8 +12,8 @@ import ( // NewEvent should be used to create an audit event. The subtype field is needed // for audit events. It will generate an ID if no ID is supplied. Supported // options: WithID, WithNow. -func NewEvent(s subtype, opt ...Option) (*auditEvent, error) { - const op = "audit.newEvent" +func NewEvent(s subtype, opt ...Option) (*AuditEvent, error) { + const op = "audit.NewEvent" // Get the default options opts, err := getOpts(opt...) @@ -30,7 +30,7 @@ func NewEvent(s subtype, opt ...Option) (*auditEvent, error) { } } - audit := &auditEvent{ + audit := &AuditEvent{ ID: opts.withID, Timestamp: opts.withNow, Version: version, @@ -44,8 +44,8 @@ func NewEvent(s subtype, opt ...Option) (*auditEvent, error) { } // validate attempts to ensure the audit event in its present state is valid. -func (a *auditEvent) validate() error { - const op = "audit.(auditEvent).validate" +func (a *AuditEvent) validate() error { + const op = "audit.(AuditEvent).validate" if a == nil { return fmt.Errorf("%s: event is nil: %w", op, event.ErrInvalidParameter)
audit/event_test.go+16 −16 modified@@ -29,21 +29,21 @@ func TestAuditEvent_new(t *testing.T) { Subtype: subtype(""), Format: format(""), IsErrorExpected: true, - ExpectedErrorMessage: "audit.newEvent: audit.(auditEvent).validate: audit.(subtype).validate: '' is not a valid event subtype: invalid parameter", + ExpectedErrorMessage: "audit.NewEvent: audit.(AuditEvent).validate: audit.(subtype).validate: '' is not a valid event subtype: invalid parameter", }, "empty-Option": { Options: []Option{}, Subtype: subtype(""), Format: format(""), IsErrorExpected: true, - ExpectedErrorMessage: "audit.newEvent: audit.(auditEvent).validate: audit.(subtype).validate: '' is not a valid event subtype: invalid parameter", + ExpectedErrorMessage: "audit.NewEvent: audit.(AuditEvent).validate: audit.(subtype).validate: '' is not a valid event subtype: invalid parameter", }, "bad-id": { Options: []Option{WithID("")}, Subtype: ResponseType, Format: JSONFormat, IsErrorExpected: true, - ExpectedErrorMessage: "audit.newEvent: error applying options: id cannot be empty", + ExpectedErrorMessage: "audit.NewEvent: error applying options: id cannot be empty", }, "good": { Options: []Option{ @@ -108,66 +108,66 @@ func TestAuditEvent_new(t *testing.T) { // TestAuditEvent_Validate exercises the validation for an audit event. func TestAuditEvent_Validate(t *testing.T) { tests := map[string]struct { - Value *auditEvent + Value *AuditEvent IsErrorExpected bool ExpectedErrorMessage string }{ "nil": { Value: nil, IsErrorExpected: true, - ExpectedErrorMessage: "audit.(auditEvent).validate: event is nil: invalid parameter", + ExpectedErrorMessage: "audit.(AuditEvent).validate: event is nil: invalid parameter", }, "default": { - Value: &auditEvent{}, + Value: &AuditEvent{}, IsErrorExpected: true, - ExpectedErrorMessage: "audit.(auditEvent).validate: missing ID: invalid parameter", + ExpectedErrorMessage: "audit.(AuditEvent).validate: missing ID: invalid parameter", }, "id-empty": { - Value: &auditEvent{ + Value: &AuditEvent{ ID: "", Version: version, Subtype: RequestType, Timestamp: time.Now(), Data: nil, }, IsErrorExpected: true, - ExpectedErrorMessage: "audit.(auditEvent).validate: missing ID: invalid parameter", + ExpectedErrorMessage: "audit.(AuditEvent).validate: missing ID: invalid parameter", }, "version-fiddled": { - Value: &auditEvent{ + Value: &AuditEvent{ ID: "audit_123", Version: "magic-v2", Subtype: RequestType, Timestamp: time.Now(), Data: nil, }, IsErrorExpected: true, - ExpectedErrorMessage: "audit.(auditEvent).validate: event version unsupported: invalid parameter", + ExpectedErrorMessage: "audit.(AuditEvent).validate: event version unsupported: invalid parameter", }, "subtype-fiddled": { - Value: &auditEvent{ + Value: &AuditEvent{ ID: "audit_123", Version: version, Subtype: subtype("moon"), Timestamp: time.Now(), Data: nil, }, IsErrorExpected: true, - ExpectedErrorMessage: "audit.(auditEvent).validate: audit.(subtype).validate: 'moon' is not a valid event subtype: invalid parameter", + ExpectedErrorMessage: "audit.(AuditEvent).validate: audit.(subtype).validate: 'moon' is not a valid event subtype: invalid parameter", }, "default-time": { - Value: &auditEvent{ + Value: &AuditEvent{ ID: "audit_123", Version: version, Subtype: ResponseType, Timestamp: time.Time{}, Data: nil, }, IsErrorExpected: true, - ExpectedErrorMessage: "audit.(auditEvent).validate: event timestamp cannot be the zero time instant: invalid parameter", + ExpectedErrorMessage: "audit.(AuditEvent).validate: event timestamp cannot be the zero time instant: invalid parameter", }, "valid": { - Value: &auditEvent{ + Value: &AuditEvent{ ID: "audit_123", Version: version, Subtype: ResponseType,
audit/sink_wrapper.go+2 −2 modified@@ -12,7 +12,7 @@ import ( ) // SinkWrapper is a wrapper for any kind of Sink Node that processes events -// containing an auditEvent payload. +// containing an AuditEvent payload. type SinkWrapper struct { Name string Sink eventlogger.Node @@ -23,7 +23,7 @@ type SinkWrapper struct { // once this method returns. func (s *SinkWrapper) Process(ctx context.Context, e *eventlogger.Event) (*eventlogger.Event, error) { defer func() { - auditEvent, ok := e.Payload.(*auditEvent) + auditEvent, ok := e.Payload.(*AuditEvent) if ok { metrics.MeasureSince([]string{"audit", s.Name, auditEvent.Subtype.MetricTag()}, e.CreatedAt) }
audit/types.go+2 −2 modified@@ -35,8 +35,8 @@ type subtype string // format defines types of format audit events support. type format string -// auditEvent is the audit event. -type auditEvent struct { +// AuditEvent is the audit event. +type AuditEvent struct { ID string `json:"id"` Version string `json:"version"` Subtype subtype `json:"subtype"` // the subtype of the audit event.
changelog/24968.txt+3 −0 added@@ -0,0 +1,3 @@ +```release-note:bug +audit: Fix bug where use of 'log_raw' option could result in other devices logging raw audit data +```
internal/observability/event/sink_socket.go+1 −2 modified@@ -10,9 +10,8 @@ import ( "sync" "time" - "github.com/hashicorp/go-multierror" - "github.com/hashicorp/eventlogger" + "github.com/hashicorp/go-multierror" ) var _ eventlogger.Node = (*SocketSink)(nil)
internal/observability/event/sink_stdout.go+3 −3 modified@@ -28,7 +28,7 @@ func NewStdoutSinkNode(format string) *StdoutSink { } // Process persists the provided eventlogger.Event to the standard output stream. -func (s *StdoutSink) Process(ctx context.Context, event *eventlogger.Event) (*eventlogger.Event, error) { +func (s *StdoutSink) Process(ctx context.Context, e *eventlogger.Event) (*eventlogger.Event, error) { const op = "event.(StdoutSink).Process" select { @@ -37,11 +37,11 @@ func (s *StdoutSink) Process(ctx context.Context, event *eventlogger.Event) (*ev default: } - if event == nil { + if e == nil { return nil, fmt.Errorf("%s: event is nil: %w", op, ErrInvalidParameter) } - formattedBytes, found := event.Format(s.requiredFormat) + formattedBytes, found := e.Format(s.requiredFormat) if !found { return nil, fmt.Errorf("%s: unable to retrieve event formatted as %q", op, s.requiredFormat) }
internal/observability/event/sink_syslog.go+1 −2 modified@@ -7,9 +7,8 @@ import ( "context" "fmt" - gsyslog "github.com/hashicorp/go-syslog" - "github.com/hashicorp/eventlogger" + gsyslog "github.com/hashicorp/go-syslog" ) var _ eventlogger.Node = (*SyslogSink)(nil)
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-vgh3-mwxq-rcp8ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-0831ghsaADVISORY
- developer.hashicorp.com/vault/docs/upgrading/upgrade-to-1.15.xghsaWEB
- discuss.hashicorp.com/t/hcsec-2024-01-vault-may-expose-sensitive-information-when-configuring-an-audit-log-device/62311ghsaWEB
- github.com/hashicorp/vault/commit/2a72f2a8a5b57de88c22a2a94c4a5f08c6f3770bghsaWEB
- security.netapp.com/advisory/ntap-20240223-0005ghsaWEB
- security.netapp.com/advisory/ntap-20240223-0005/mitre
News mentions
0No linked articles in our index yet.