Skip to content

Commit

Permalink
fix: ignore byte array fields and add ddwaf:ignore struct tag (#68)
Browse files Browse the repository at this point in the history
Co-authored-by: Romain Marcadier <[email protected]>
  • Loading branch information
eliottness and RomainMuller authored Feb 9, 2024
1 parent 3ac659c commit f547dc1
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 7 deletions.
2 changes: 1 addition & 1 deletion _tools/libddwaf-updater/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func main() {
written += wrote
}

fmt.Println("All done! Don't forget to check in changes to include/ and internal/lib/, check the libddwaf upgrade guide to update bindings!")
fmt.Println("All done! Don't forget to check in changes to internal/lib/ and internal/log/ddhaf.h, check the libddwaf upgrade guide to update bindings!")
}

// createEmbedSource creates the embed source file for the given target.
Expand Down
1 change: 1 addition & 0 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func (d RunAddressData) isEmpty() bool {
// matches as a JSON string (usually opaquely used) along with the corresponding actions in any. In case of an error,
// matches and actions can still be returned, for instance in the case of a timeout error. Errors can be tested against
// the RunError type.
// Struct fields having the tag `ddwaf:"ignore"` will not be encoded and sent to the WAF
func (context *Context) Run(addressData RunAddressData, timeout time.Duration) (res Result, err error) {
if addressData.isEmpty() {
return
Expand Down
16 changes: 13 additions & 3 deletions encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ const (
ObjectTooDeep
)

const (
AppsecFieldTag = "ddwaf"
AppsecFieldTagValueIgnore = "ignore"
)

type native interface {
int64 | uint64 | uintptr
}
Expand Down Expand Up @@ -159,8 +164,11 @@ func (encoder *encoder) encode(value reflect.Value, obj *wafObject, depth int) e
// Strings
case kind == reflect.String: // string type
encoder.encodeString(value.String(), obj)
case value.Type() == reflect.TypeOf([]byte(nil)): // byte array -> string
encoder.encodeString(string(value.Bytes()), obj)

case value.Type() == reflect.TypeOf([]byte(nil)):
// Byte Arrays are skipped voluntarily because they are often used
// to do partial parsing which leads to false positives
return nil

// Containers (internal nodes of the tree)

Expand Down Expand Up @@ -240,7 +248,9 @@ func (encoder *encoder) encodeStruct(value reflect.Value, obj *wafObject, depth

fieldType := typ.Field(i)
fieldName, usable := getFieldNameFromType(fieldType)
if !usable {
if tag, ok := fieldType.Tag.Lookup(AppsecFieldTag); !usable || ok && tag == AppsecFieldTagValueIgnore {
// Either the struct field is ignored by json marshaling so can we,
// or the field was explicitly set with `ddwaf:ignore`
continue
}

Expand Down
36 changes: 33 additions & 3 deletions encoder_decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ func TestEncodeDecode(t *testing.T) {
Input: "hello, waf",
},
{
Name: "byte-slice",
Input: []byte("hello, waf"),
Output: "hello, waf",
Name: "byte-slice",
Input: []byte("hello, waf"),
DecodeError: errUnsupportedValue,
},
{
Name: "nil-byte-slice",
Expand Down Expand Up @@ -253,6 +253,23 @@ func TestEncodeDecode(t *testing.T) {
"A": "A",
},
},
{
Name: "struct-with-ignored-values",
Input: struct {
Public string `ddwaf:"ignore"`
private string
a string
A string
}{
Public: "Public",
private: "private",
a: "a",
A: "A",
},
Output: map[string]any{
"A": "A",
},
},
{
Name: "struct-with-unsupported-values",
Input: struct {
Expand All @@ -268,6 +285,19 @@ func TestEncodeDecode(t *testing.T) {
},
DecodeError: errUnsupportedValue,
},
{
Name: "struct-with-unsupported-ignored-values",
Input: struct {
Public string
A chan any `ddwaf:"ignore"`
}{
Public: "Public",
A: make(chan any),
},
Output: map[string]any{
"Public": "Public",
},
},
} {
t.Run(tc.Name, func(t *testing.T) {
if tc.Output == nil {
Expand Down

0 comments on commit f547dc1

Please sign in to comment.