Skip to content

Commit f07d781

Browse files
Copilotnomeguy
andcommitted
Add comprehensive cross-platform compatibility integration test
Co-authored-by: nomeguy <85475922+nomeguy@users.noreply.github.com>
1 parent 619c686 commit f07d781

File tree

1 file changed

+181
-0
lines changed

1 file changed

+181
-0
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
// Copyright 2024 The casbin Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package org.casbin.jcasbin.main;
16+
17+
import org.casbin.jcasbin.util.ExpressionEvaluator;
18+
import org.junit.Test;
19+
20+
import static org.junit.Assert.*;
21+
22+
/**
23+
* Integration test to demonstrate the fix for the eval() function issue.
24+
* This test validates that the expression evaluator prevents the use of
25+
* aviatorscript-specific syntax mentioned in the issue, ensuring
26+
* cross-platform compatibility.
27+
*/
28+
public class EvalCrossPlatformTest {
29+
30+
/**
31+
* Test that aviatorscript-specific syntax mentioned in the issue is blocked.
32+
* Issue mentioned: seq.list(), string.startsWith(), string.endsWith(), include(seq.list(),xx)
33+
*/
34+
@Test
35+
public void testAviatorScriptSyntaxFromIssue_IsBlocked() {
36+
// All these expressions from the issue description should be blocked
37+
38+
// 1. seq.list() syntax
39+
try {
40+
ExpressionEvaluator.validateExpression("seq.list('A', 'B')");
41+
fail("seq.list() should be blocked");
42+
} catch (IllegalArgumentException e) {
43+
assertTrue("Should mention non-standard operations",
44+
e.getMessage().contains("non-standard Casbin operations"));
45+
}
46+
47+
// 2. string.startsWith() syntax
48+
try {
49+
ExpressionEvaluator.validateExpression("string.startsWith(r.obj, '/data')");
50+
fail("string.startsWith() should be blocked");
51+
} catch (IllegalArgumentException e) {
52+
assertTrue("Should mention non-standard operations",
53+
e.getMessage().contains("non-standard Casbin operations"));
54+
}
55+
56+
// 3. string.endsWith() syntax
57+
try {
58+
ExpressionEvaluator.validateExpression("string.endsWith(r.obj, '.txt')");
59+
fail("string.endsWith() should be blocked");
60+
} catch (IllegalArgumentException e) {
61+
assertTrue("Should mention non-standard operations",
62+
e.getMessage().contains("non-standard Casbin operations"));
63+
}
64+
65+
// 4. include(seq.list(),xx) syntax
66+
try {
67+
ExpressionEvaluator.validateExpression("include(seq.list('admin', 'user'), r.sub.role)");
68+
fail("include(seq.list(),xx) should be blocked");
69+
} catch (IllegalArgumentException e) {
70+
assertTrue("Should mention non-standard operations",
71+
e.getMessage().contains("non-standard Casbin operations"));
72+
}
73+
}
74+
75+
/**
76+
* Test that standard Casbin expressions work correctly.
77+
* These should be portable across all Casbin implementations.
78+
*/
79+
@Test
80+
public void testStandardCasbinExpressions_AreAllowed() {
81+
// All these standard expressions should work
82+
String[] standardExpressions = {
83+
// Property access
84+
"r.sub.name == 'alice'",
85+
"r.sub.age > 18",
86+
"r.obj == '/data1'",
87+
"r.act == 'read'",
88+
89+
// Logical operators
90+
"r.sub.age > 18 && r.sub.age < 60",
91+
"r.sub.name == 'alice' || r.sub.name == 'bob'",
92+
"!(r.sub.blocked == true)",
93+
94+
// Comparison operators
95+
"r.sub.level >= 5",
96+
"r.sub.score != 0",
97+
"r.domain == 'domain1'",
98+
99+
// Arithmetic operations
100+
"r.sub.age + 10 > 28",
101+
"r.sub.count * 2 <= 100",
102+
103+
// Registered functions (these are part of standard Casbin)
104+
"keyMatch(r.obj, '/api/*')",
105+
"regexMatch(r.obj, '^/data[0-9]+$')",
106+
"custom(r.obj)"
107+
};
108+
109+
for (String expr : standardExpressions) {
110+
try {
111+
ExpressionEvaluator.validateExpression(expr);
112+
// Success - standard expression is allowed
113+
} catch (IllegalArgumentException e) {
114+
fail("Standard expression should be allowed: " + expr + " - Error: " + e.getMessage());
115+
}
116+
}
117+
}
118+
119+
/**
120+
* Test that the solution achieves cross-platform compatibility.
121+
* The same expressions should work identically on Go, Node.js, Python, etc.
122+
*/
123+
@Test
124+
public void testCrossPlatformCompatibility() {
125+
// These expressions use only standard operators that are available
126+
// in all Casbin implementations
127+
128+
String[] crossPlatformExpressions = {
129+
// Instead of seq.list('A', 'B'), use standard comparisons:
130+
"r.sub.role == 'admin' || r.sub.role == 'moderator'",
131+
132+
// Instead of string.startsWith(), use keyMatch or regexMatch:
133+
"keyMatch(r.obj, '/api/*')",
134+
"regexMatch(r.obj, '^/api/')",
135+
136+
// Instead of string.endsWith(), use regexMatch:
137+
"regexMatch(r.obj, '\\\\.txt$')",
138+
139+
// Instead of include(seq.list(),xx), use logical OR:
140+
"r.sub.dept == 'engineering' || r.sub.dept == 'sales'"
141+
};
142+
143+
for (String expr : crossPlatformExpressions) {
144+
try {
145+
ExpressionEvaluator.validateExpression(expr);
146+
// Success - cross-platform compatible expression
147+
} catch (IllegalArgumentException e) {
148+
fail("Cross-platform expression should be allowed: " + expr);
149+
}
150+
}
151+
}
152+
153+
/**
154+
* Test that security is improved by blocking operations beyond Casbin spec.
155+
*/
156+
@Test
157+
public void testSecurityImprovement_BlocksUnsafeOperations() {
158+
// These operations go beyond Casbin specification and could be security risks
159+
String[] unsafeOperations = {
160+
"new java.io.File('/etc/passwd')",
161+
"import java.lang.System",
162+
"let x = System.getProperty('user.home')",
163+
"fn hack() { return 'exploit' }",
164+
"lambda(x) -> System.exit(0)",
165+
"for (i = 0; i < 1000000; i++)", // potential DoS
166+
"while (true)", // infinite loop
167+
"math.random()" // non-deterministic
168+
};
169+
170+
for (String expr : unsafeOperations) {
171+
try {
172+
ExpressionEvaluator.validateExpression(expr);
173+
fail("Unsafe operation should be blocked: " + expr);
174+
} catch (IllegalArgumentException e) {
175+
// Success - unsafe operation is blocked
176+
assertTrue("Should indicate non-standard operations",
177+
e.getMessage().contains("non-standard Casbin operations"));
178+
}
179+
}
180+
}
181+
}

0 commit comments

Comments
 (0)