Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions enforcer.go
Original file line number Diff line number Diff line change
Expand Up @@ -674,13 +674,17 @@ func (e *Enforcer) enforce(matcher string, explains *[]string, rvals ...interfac

if e.acceptJsonRequest {
// try to parse all request values from json to map[string]interface{}
// skip if there is an error
for i, rval := range rvals {
switch rval := rval.(type) {
case string:
var mapValue map[string]interface{}
mapValue, err = util.JsonToMap(rval)
if err == nil {
// Only attempt JSON parsing for strings that look like JSON objects or arrays
if len(rval) > 0 && (rval[0] == '{' || rval[0] == '[') {
var mapValue map[string]interface{}
mapValue, err = util.JsonToMap(rval)
if err != nil {
// Return a clear error when JSON-like string fails to parse
return false, fmt.Errorf("failed to parse JSON parameter at index %d: %w", i, err)
}
rvals[i] = mapValue
}
}
Expand Down
66 changes: 66 additions & 0 deletions enforcer_json_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package casbin

import (
"strings"
"testing"

"github.com/casbin/casbin/v3/model"
)

func TestInvalidJsonRequest(t *testing.T) {
modelText := `
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub.Name == " "
`

m, err := model.NewModelFromString(modelText)
if err != nil {
t.Fatalf("Failed to create model: %v", err)
}
e, err := NewEnforcer(m)
if err != nil {
t.Fatalf("Failed to create enforcer: %v", err)
}
e.EnableAcceptJsonRequest(true)

// Test with invalid JSON (contains \x escape sequence which is not valid in JSON)
invalidJSON := `{"Name": "\x20"}`
_, err = e.Enforce(invalidJSON, "obj", "read")
if err == nil {
t.Fatalf("Expected error for invalid JSON, got nil")
}
if !strings.Contains(err.Error(), "failed to parse JSON parameter") {
t.Fatalf("Expected error message to contain 'failed to parse JSON parameter', got: %v", err)
}

// Test with valid JSON - should work
validJSON := `{"Name": " "}`
res, err := e.Enforce(validJSON, "obj", "read")
if err != nil {
t.Fatalf("Valid JSON should not return error: %v", err)
}
if !res {
t.Fatalf("Expected true for valid JSON with matching Name")
}

// Test with plain string (doesn't start with { or [) - should not try to parse as JSON
plainString := "alice"
_, err = e.Enforce(plainString, "obj", "read")
// This will fail because plainString is not a struct with Name field,
// but it shouldn't fail with JSON parsing error
if err != nil && strings.Contains(err.Error(), "failed to parse JSON parameter") {
t.Fatalf("Plain string should not trigger JSON parsing error: %v", err)
}
}
Loading