⚡️ A high-performance, zero allocation, dynamic JSON Threat Protection in pure Go. 🔥
Package gojtp provides a fast way to validate the dynamic JSON and protect against vulnerable JSON content-level attacks (JSON Threat Protection) based on configured properties.
It also validate the JSON and if JSON is Invalid it will return an error.
JSON requests are susceptible to attacks characterized by unusual inflation of elements and nesting levels. Attackers use recursive techniques to consume memory resources by using huge json files to overwhelm the parser and eventually crash the service.
JSON threat protection is terms that describe the way to minimize the risk from such attacks by defining few limits on the json structure like length and depth validation on a json, and helps protect your applications from such intrusions.
There are situations where you do not want to parse the JSON, but do want to ensure that the JSON is not going to cause a problem. Such as an API Gateway. It would be a PAIN for the gateway to have to know all JSON schema of all services it is protecting. There are XML validators that perform similar functions.
Installing To start using gojtp, install Go and run go get:
$ go get -u github.com/ankur-anand/gojtp
On linux-amd64
BenchmarkTestifyNoThreatInBytes-4 500000 2628 ns/op 0 B/op 0 allocs/op
JSON Used
{
"simple_string": "hello word",
"targets": [
{
"req_per_second": 5,
"duration_of_time": 1,
"utf8Key": "Hello, 世界",
"request": {
"endpoint": "https://httpbin.org/get",
"http_method": "GET",
"payload": {
"username": "ankur",
"password": "ananad"
},
"array_value": [
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstv"
],
"additional_header": [
{
"header_key": "uuid",
"header_value": [
"1",
"2"
]
}
]
}
},
{
"req_per_second": 10,
"duration_of_time": 1,
"request": {
"endpoint": "https://httpbin.org/post",
"http_method": "POST",
"payload": {
"username": "ankur",
"password": "ananad"
},
"additional_header": [
{
"header_key": "uuid",
"header_value": [
"1",
"2",
"3",
"4",
"5",
"Hello, 世界"
]
}
]
}
}
]
}
All the verifier Parameters are Optional
Check Godoc for all option
Example Verify
// with multiple config
_, _ = New(WithMaxArrayElementCount(6),
WithMaxContainerDepth(7),
WithMaxObjectKeyLength(20), WithMaxStringLength(50),
)
// with single config
_, _ = New(WithMaxStringLength(25))
The JTP returns following error messages on Validation failure:
Error Message |
---|
jtp.maxStringValueLengthReached.Max-[X]-Allowed.Found-[Y]. |
jtp.maxArrayElementCountReached.Max-[X]-Allowed.Found-[Y]. |
jtp.maxKeyLengthReached.Max-[X]-Allowed.Found-[Y] |
jtp.maxContainerDepthReached.Max-[X]-Allowed.Found-[Y] |
jtp.maxObjectEntryCountReached.Max-[X]-Allowed.Found-[Y] |
jtp.MalformedJSON |
package main
import (
"github.com/ankur-anand/gojtp"
"log"
)
func main() {
json := _getTestJsonBytes()
verifier1, err := New(WithMaxArrayElementCount(6),
WithMaxContainerDepth(7),
WithMaxObjectKeyLength(20), WithMaxStringLength(50),
)
ok, err := verifier1.VerifyBytes(json)
verifier2, err := New(WithMaxStringLength(25))
ok, err = verifier2.VerifyBytes(json)
fmt.Println(ok, err)
}
func _getTestJsonBytes() []byte {
return []byte(`{
"simple_string": "hello word",
"targets": [
{
"req_per_second": 5,
"duration_of_time": 1,
"utf8Key": "Hello, 世界",
"request": {
"endpoint": "https://httpbin.org/get",
"http_method": "GET",
"payload": {
"username": "ankur",
"password": "ananad"
},
"array_value": [
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstv"
],
"additional_header": [
{
"header_key": "uuid",
"header_value": [
"1",
"2"
]
}
]
}
},
{
"req_per_second": 10,
"duration_of_time": 1,
"request": {
"endpoint": "https://httpbin.org/post",
"http_method": "POST",
"payload": {
"username": "ankur",
"password": "ananad"
},
"additional_header": [
{
"header_key": "uuid",
"header_value": [
"1",
"2",
"3",
"4",
"5",
"Hello, 世界"
]
}
]
}
}
]
}
`)
}
Ankur Anand @in_aanand
GOJTP source code is available under the MIT License.
Based on Parser from tidwall.