77import java .util .List ;
88import org .junit .jupiter .api .Test ;
99
10- /** Security tests for JsonIdentifierExpression to ensure SQL injection prevention. */
1110public class JsonIdentifierExpressionSecurityTest {
1211
13- // ===== Valid Expressions =====
14-
1512 @ Test
16- void testValidExpression_SimpleField () {
13+ void testValidExpressionSimpleField () {
1714 assertDoesNotThrow (() -> JsonIdentifierExpression .of ("props" , "brand" ));
1815 }
1916
2017 @ Test
21- void testValidExpression_NestedField () {
18+ void testValidExpressionNestedField () {
2219 assertDoesNotThrow (() -> JsonIdentifierExpression .of ("props" , "seller" , "name" ));
2320 }
2421
2522 @ Test
26- void testValidExpression_DeeplyNested () {
23+ void testValidExpressionDeeplyNested () {
2724 assertDoesNotThrow (() -> JsonIdentifierExpression .of ("props" , "seller" , "address" , "city" ));
2825 }
2926
3027 @ Test
31- void testValidExpression_WithNumbers () {
28+ void testValidExpressionWithNumbers () {
3229 assertDoesNotThrow (() -> JsonIdentifierExpression .of ("props" , "field123" ));
33- assertDoesNotThrow (() -> JsonIdentifierExpression .of ("props" , "1st_choice " ));
30+ assertDoesNotThrow (() -> JsonIdentifierExpression .of ("props" , "field_1 " ));
3431 }
3532
3633 @ Test
37- void testValidExpression_WithUnderscore () {
34+ void testInvalidExpressionJsonPathStartsWithNumber () {
35+ SecurityException ex =
36+ assertThrows (
37+ SecurityException .class , () -> JsonIdentifierExpression .of ("props" , "1st_choice" ));
38+ assertTrue (ex .getMessage ().contains ("invalid characters" ));
39+ }
40+
41+ @ Test
42+ void testValidExpressionWithUnderscore () {
3843 assertDoesNotThrow (() -> JsonIdentifierExpression .of ("_internal" , "field" ));
3944 assertDoesNotThrow (() -> JsonIdentifierExpression .of ("props" , "_private" ));
4045 }
4146
4247 @ Test
43- void testValidExpression_UsingListConstructor () {
48+ void testValidExpressionUsingListConstructor () {
4449 assertDoesNotThrow (
4550 () -> JsonIdentifierExpression .of ("props" , List .of ("seller" , "address" , "city" )));
4651 }
4752
48- // ===== Invalid Column Names =====
49-
5053 @ Test
51- void testInvalidExpression_ColumnName_DropTable () {
54+ void testInvalidExpressionColumnNameDropTable () {
5255 SecurityException ex =
5356 assertThrows (
5457 SecurityException .class ,
@@ -57,49 +60,39 @@ void testInvalidExpression_ColumnName_DropTable() {
5760 }
5861
5962 @ Test
60- void testInvalidExpression_ColumnName_WithQuote () {
63+ void testInvalidExpressionColumnNameWithQuote () {
6164 SecurityException ex =
6265 assertThrows (
6366 SecurityException .class , () -> JsonIdentifierExpression .of ("props\" name" , "brand" ));
6467 assertTrue (ex .getMessage ().contains ("invalid" ));
6568 }
6669
6770 @ Test
68- void testInvalidExpression_ColumnName_WithSemicolon () {
71+ void testInvalidExpressionColumnNameWithSemicolon () {
6972 SecurityException ex =
7073 assertThrows (
7174 SecurityException .class , () -> JsonIdentifierExpression .of ("props;SELECT" , "brand" ));
7275 assertTrue (ex .getMessage ().contains ("invalid" ));
7376 }
7477
7578 @ Test
76- void testInvalidExpression_ColumnName_StartsWithNumber () {
79+ void testInvalidExpressionColumnNameStartsWithNumber () {
7780 SecurityException ex =
7881 assertThrows (
7982 SecurityException .class , () -> JsonIdentifierExpression .of ("123props" , "brand" ));
8083 assertTrue (ex .getMessage ().contains ("Must start with a letter or underscore" ));
8184 }
8285
8386 @ Test
84- void testInvalidExpression_ColumnName_WithHyphen () {
85- SecurityException ex =
86- assertThrows (
87- SecurityException .class , () -> JsonIdentifierExpression .of ("my-column" , "brand" ));
88- assertTrue (ex .getMessage ().contains ("invalid" ));
89- }
90-
91- @ Test
92- void testInvalidExpression_ColumnName_WithSpace () {
87+ void testInvalidExpressionColumnNameWithSpace () {
9388 SecurityException ex =
9489 assertThrows (
9590 SecurityException .class , () -> JsonIdentifierExpression .of ("my column" , "brand" ));
9691 assertTrue (ex .getMessage ().contains ("invalid" ));
9792 }
9893
99- // ===== Invalid JSON Paths =====
100-
10194 @ Test
102- void testInvalidExpression_JsonPath_WithQuote () {
95+ void testInvalidExpressionJsonPathWithQuote () {
10396 SecurityException ex =
10497 assertThrows (
10598 SecurityException .class ,
@@ -108,47 +101,43 @@ void testInvalidExpression_JsonPath_WithQuote() {
108101 }
109102
110103 @ Test
111- void testInvalidExpression_JsonPath_WithDoubleQuote () {
104+ void testInvalidExpressionJsonPathWithDoubleQuote () {
112105 SecurityException ex =
113106 assertThrows (
114107 SecurityException .class , () -> JsonIdentifierExpression .of ("props" , "name\" --" ));
115108 assertTrue (ex .getMessage ().contains ("invalid characters" ));
116109 }
117110
118111 @ Test
119- void testInvalidExpression_JsonPath_WithSemicolon () {
112+ void testInvalidExpressionJsonPathWithSemicolon () {
120113 SecurityException ex =
121114 assertThrows (
122115 SecurityException .class , () -> JsonIdentifierExpression .of ("props" , "field; DROP" ));
123116 assertTrue (ex .getMessage ().contains ("invalid characters" ));
124117 }
125118
126119 @ Test
127- void testInvalidExpression_JsonPath_WithHyphen () {
128- SecurityException ex =
129- assertThrows (
130- SecurityException .class , () -> JsonIdentifierExpression .of ("props" , "field-name" ));
131- assertTrue (ex .getMessage ().contains ("invalid characters" ));
120+ void testValidExpressionJsonPathWithHyphen () {
121+ assertDoesNotThrow (() -> JsonIdentifierExpression .of ("customAttribute" , "repo-url" ));
122+ assertDoesNotThrow (() -> JsonIdentifierExpression .of ("props" , "user-id" ));
132123 }
133124
134125 @ Test
135- void testInvalidExpression_JsonPath_WithDot () {
136- SecurityException ex =
137- assertThrows (
138- SecurityException .class , () -> JsonIdentifierExpression .of ("props" , "field.name" ));
139- assertTrue (ex .getMessage ().contains ("invalid characters" ));
126+ void testValidExpressionJsonPathWithDot () {
127+ assertDoesNotThrow (() -> JsonIdentifierExpression .of ("props" , "field.name" ));
128+ assertDoesNotThrow (() -> JsonIdentifierExpression .of ("props" , "user.address.city" ));
140129 }
141130
142131 @ Test
143- void testInvalidExpression_JsonPath_WithSpace () {
132+ void testInvalidExpressionJsonPathWithSpace () {
144133 SecurityException ex =
145134 assertThrows (
146135 SecurityException .class , () -> JsonIdentifierExpression .of ("props" , "field name" ));
147136 assertTrue (ex .getMessage ().contains ("invalid characters" ));
148137 }
149138
150139 @ Test
151- void testInvalidExpression_JsonPath_EmptyElement () {
140+ void testInvalidExpression_sonPathEmptyElement () {
152141 SecurityException ex =
153142 assertThrows (
154143 SecurityException .class ,
@@ -157,7 +146,7 @@ void testInvalidExpression_JsonPath_EmptyElement() {
157146 }
158147
159148 @ Test
160- void testInvalidExpression_JsonPath_TooDeep () {
149+ void testInvalidExpressionJsonPathTooDeep () {
161150 String [] deepPath = new String [11 ]; // Max is 10
162151 for (int i = 0 ; i < 11 ; i ++) {
163152 deepPath [i ] = "level" + i ;
@@ -167,10 +156,8 @@ void testInvalidExpression_JsonPath_TooDeep() {
167156 assertTrue (ex .getMessage ().contains ("exceeds maximum depth" ));
168157 }
169158
170- // ===== Real-world Attack Scenarios =====
171-
172159 @ Test
173- void testAttackScenario_SqlCommentInjection () {
160+ void testAttackScenarioSqlCommentInjection () {
174161 SecurityException ex =
175162 assertThrows (
176163 SecurityException .class ,
@@ -179,7 +166,7 @@ void testAttackScenario_SqlCommentInjection() {
179166 }
180167
181168 @ Test
182- void testAttackScenario_UnionSelect () {
169+ void testAttackScenarioUnionSelect () {
183170 SecurityException ex =
184171 assertThrows (
185172 SecurityException .class ,
@@ -190,7 +177,7 @@ void testAttackScenario_UnionSelect() {
190177 }
191178
192179 @ Test
193- void testAttackScenario_OrTrueInjection () {
180+ void testAttackScenarioOrTrueInjection () {
194181 SecurityException ex =
195182 assertThrows (
196183 SecurityException .class ,
@@ -199,7 +186,7 @@ void testAttackScenario_OrTrueInjection() {
199186 }
200187
201188 @ Test
202- void testAttackScenario_NestedInjection () {
189+ void testAttackScenarioNestedInjection () {
203190 SecurityException ex =
204191 assertThrows (
205192 SecurityException .class ,
@@ -208,7 +195,7 @@ void testAttackScenario_NestedInjection() {
208195 }
209196
210197 @ Test
211- void testAttackScenario_SpecialCharacterCombination () {
198+ void testAttackScenarioSpecialCharacterCombination () {
212199 SecurityException ex =
213200 assertThrows (
214201 SecurityException .class , () -> JsonIdentifierExpression .of ("props" , "field'\" `;DROP" ));
0 commit comments