Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
151836f
changed fault codes
arcuri82 Feb 5, 2026
36a437e
avoid SQLi in white-box with no SQL
arcuri82 Feb 5, 2026
d73e82e
fixed/improved SQLi construction
arcuri82 Feb 5, 2026
dbd532b
cleaning XSS
arcuri82 Feb 5, 2026
a28df94
clarification
arcuri82 Feb 6, 2026
04f1622
reset state
omursahin Feb 7, 2026
d304cf1
revert changes
omursahin Feb 7, 2026
ba08b7b
fixes
omursahin Feb 9, 2026
9998a7b
Merge branch 'master' into sqli-apps-reset-fix
arcuri82 Feb 11, 2026
0d93394
Merge branch 'master' into security-cleanup
arcuri82 Feb 11, 2026
0f82bd2
Merge pull request #1445 from WebFuzzing/sqli-apps-reset-fix
arcuri82 Feb 11, 2026
a03fb13
adding check on insertion ids
arcuri82 Feb 11, 2026
8368f84
refactored field name
arcuri82 Feb 11, 2026
63888cd
more refactoring
arcuri82 Feb 11, 2026
de21fb5
adding invariant
arcuri82 Feb 11, 2026
e73cf3a
starting with id shifts
arcuri82 Feb 12, 2026
dd0e694
handling of id shift
arcuri82 Feb 12, 2026
a74fb04
fixing tests after update
arcuri82 Feb 12, 2026
29e5eb5
fixed broken test after adding of invariants
arcuri82 Feb 12, 2026
437413f
Merge branch 'master' into security-cleanup
arcuri82 Feb 13, 2026
707663e
Merge branch 'master' into security-cleanup
arcuri82 Feb 13, 2026
55b888d
Merge branch 'master' into security-cleanup
arcuri82 Feb 13, 2026
95af587
updated tests
arcuri82 Feb 13, 2026
cdfd3b1
use `config.probOfSelectFromDatabase` instead of 0.5 to decide whethe…
man-zhang Feb 15, 2026
48ad96c
refactoring + relaxing check on un-flattened individuals
arcuri82 Feb 15, 2026
75dc7de
cleaned-up code for SQL validation
arcuri82 Feb 15, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.evomaster.core.problem.rest.data.RestIndividual;
import org.evomaster.core.search.Solution;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertFalse;
Expand All @@ -17,6 +18,7 @@ public static void initClass() throws Exception {
SpringTestBase.initClass(new Z3SolverController());
}

@Disabled("FIXME new invariants fail here... need to update solver code to handle them")
@Test
public void testRunEM() throws Throwable {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,8 @@ open class BodySQLiApplication: SwaggerConfiguration() {
@PostConstruct
fun init() {
connection = dataSource.connection
initializeTestData()
}

private fun initializeTestData() {
if (userRepository.count() == 0L) {
userRepository.save(UserEntity(null, "admin", "admin123"))
userRepository.save(UserEntity(null, "user1", "password1"))
}
}

/**
* Safe endpoint - No SQL Injection vulnerability
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,6 @@ open class PathSQLiApplication {
@PostConstruct
fun init() {
connection = dataSource.connection
initializeTestData()
}

private fun initializeTestData() {
if (userRepository.count() == 0L) {
userRepository.save(UserEntity(null, "admin", "admin123"))
userRepository.save(UserEntity(null, "user1", "password1"))
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,6 @@ open class QuerySQLiApplication: SwaggerConfiguration() {
@PostConstruct
fun init() {
connection = dataSource.connection
initializeTestData()
}

private fun initializeTestData() {
if (userRepository.count() == 0L) {
userRepository.save(UserEntity(null, "admin", "admin123"))
userRepository.save(UserEntity(null, "user1", "password1"))
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
insert into users (id, username, password) values (1,'admin', 'pass1');
insert into users (id, username, password) values (2,'user', 'user');
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package com.foo.spring.rest.mysql.sqli

import com.foo.spring.rest.mysql.SpringRestMySqlController
import com.foo.spring.rest.mysql.sqli.body.BodySQLiApplication
import org.evomaster.client.java.controller.api.dto.database.schema.DatabaseType
import org.evomaster.client.java.sql.DbSpecification

class SQLiMySQLBodyController : SpringRestMySqlController(BodySQLiApplication::class.java){
override fun pathToFlywayFiles() = "classpath:/schema/sqli"
override fun getDbSpecifications(): MutableList<DbSpecification>? {
return null
}
override fun getDbSpecifications(): MutableList<DbSpecification>? = mutableListOf(
DbSpecification(DatabaseType.MYSQL, dbConnection).withSchemas("test").withInitSqlOnResourcePath("/schema/sqli/data.sql"))

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package com.foo.spring.rest.mysql.sqli

import com.foo.spring.rest.mysql.SpringRestMySqlController
import com.foo.spring.rest.mysql.sqli.path.PathSQLiApplication
import org.evomaster.client.java.controller.api.dto.database.schema.DatabaseType
import org.evomaster.client.java.sql.DbSpecification

class SQLiMySQLPathController : SpringRestMySqlController(PathSQLiApplication::class.java){
override fun pathToFlywayFiles() = "classpath:/schema/sqli"
override fun getDbSpecifications(): MutableList<DbSpecification>? {
return null
}
override fun getDbSpecifications(): MutableList<DbSpecification>? = mutableListOf(
DbSpecification(DatabaseType.MYSQL, dbConnection).withSchemas("test").withInitSqlOnResourcePath("/schema/sqli/data.sql"))

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package com.foo.spring.rest.mysql.sqli

import com.foo.spring.rest.mysql.SpringRestMySqlController
import com.foo.spring.rest.mysql.sqli.query.QuerySQLiApplication
import org.evomaster.client.java.controller.api.dto.database.schema.DatabaseType
import org.evomaster.client.java.sql.DbSpecification

class SQLiMySQLQueryController : SpringRestMySqlController(QuerySQLiApplication::class.java){
override fun pathToFlywayFiles() = "classpath:/schema/sqli"
override fun getDbSpecifications(): MutableList<DbSpecification>? {
return null
}
override fun getDbSpecifications(): MutableList<DbSpecification>? = mutableListOf(
DbSpecification(DatabaseType.MYSQL, dbConnection).withSchemas("test").withInitSqlOnResourcePath("/schema/sqli/data.sql"))
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ class ForgottenAuthenticationDisableEMTest : SpringTestBase(){
setOption(args, "security", "true")
setOption(args, "schemaOracles", "false")
setOption(args, "useExperimentalOracles", "true")
setOption(args, "disabledOracleCodes", ExperimentalFaultCategory.SECURITY_FORGOTTEN_AUTHENTICATION.code.toString())
setOption(args, "disabledOracleCodes", ExperimentalFaultCategory.IGNORE_ANONYMOUS.code.toString())

val solution = initAndRun(args)

assertTrue(solution.individuals.size >= 1)

val faults = DetectedFaultUtils.getDetectedFaultCategories(solution)
assertFalse(ExperimentalFaultCategory.SECURITY_FORGOTTEN_AUTHENTICATION in faults)
assertFalse(ExperimentalFaultCategory.IGNORE_ANONYMOUS in faults)

}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ class StackTraceDisableEMTest : SpringTestBase(){

setOption(args, "security", "true")
setOption(args, "schemaOracles", "false")
setOption(args, "disabledOracleCodes", ExperimentalFaultCategory.SECURITY_STACK_TRACE.code.toString())
setOption(args, "disabledOracleCodes", ExperimentalFaultCategory.LEAKED_STACK_TRACES.code.toString())

val solution = initAndRun(args)

assertTrue(solution.individuals.size >= 1)

val faults = DetectedFaultUtils.getDetectedFaultCategories(solution)
assertFalse(ExperimentalFaultCategory.SECURITY_STACK_TRACE in faults)
assertFalse(ExperimentalFaultCategory.LEAKED_STACK_TRACES in faults)

}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package org.evomaster.e2etests.spring.openapi.v3.security.anonymouswrite

import com.foo.rest.examples.spring.openapi.v3.security.anonymouswrite.AnonymousWriteController
import com.foo.rest.examples.spring.openapi.v3.security.existenceleakage.ExistenceLeakageController
import com.webfuzzing.commons.faults.DefinedFaultCategory
import org.evomaster.core.problem.enterprise.DetectedFaultUtils
import org.evomaster.core.problem.enterprise.ExperimentalFaultCategory
import org.evomaster.core.problem.rest.data.HttpVerb
import org.evomaster.e2etests.spring.openapi.v3.SpringTestBase
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
Expand Down Expand Up @@ -45,11 +42,11 @@ class SecurityAnonymousWriteEMTest : SpringTestBase(){
assertEquals(1, faultsCategories.size)
assertEquals(3, faults.size)

assertTrue(ExperimentalFaultCategory.ANONYMOUS_WRITE in faultsCategories)
assertTrue(ExperimentalFaultCategory.ANONYMOUS_MODIFICATIONS in faultsCategories)

// PUT:/api/resources/201/{id}
assertTrue(faults.none {
it.category == ExperimentalFaultCategory.ANONYMOUS_WRITE
it.category == ExperimentalFaultCategory.ANONYMOUS_MODIFICATIONS
&& it.operationId == "PUT:/api/resources/201/{id}"
})
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.evomaster.e2etests.spring.openapi.v3.security.forgottenauthentication

import com.foo.rest.examples.spring.openapi.v3.security.forgottenauthentication.ForgottenAuthenticationController
import com.webfuzzing.commons.faults.FaultCategory
import org.evomaster.core.problem.enterprise.DetectedFaultUtils
import org.evomaster.core.problem.enterprise.ExperimentalFaultCategory
import org.evomaster.core.problem.rest.data.HttpVerb
Expand Down Expand Up @@ -45,7 +44,7 @@ class ForgottenAuthenticationEMTest : SpringTestBase(){

val faults = DetectedFaultUtils.getDetectedFaultCategories(solution)
assertEquals(1, faults.size)
assertEquals(ExperimentalFaultCategory.SECURITY_FORGOTTEN_AUTHENTICATION, faults.first())
assertEquals(ExperimentalFaultCategory.IGNORE_ANONYMOUS, faults.first())
}
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
package org.evomaster.e2etests.spring.openapi.v3.security.stacktrace

import com.foo.rest.examples.spring.openapi.v3.security.stacktrace.StackTraceController
import com.webfuzzing.commons.faults.DefinedFaultCategory
import com.webfuzzing.commons.faults.FaultCategory
import org.evomaster.core.problem.enterprise.DetectedFaultUtils
import org.evomaster.core.problem.enterprise.ExperimentalFaultCategory
import org.evomaster.core.problem.rest.data.HttpVerb
import org.evomaster.e2etests.spring.openapi.v3.SpringTestBase
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
Expand Down Expand Up @@ -47,11 +43,11 @@ class StackTraceEMTest : SpringTestBase(){
val faultsCategories = DetectedFaultUtils.getDetectedFaultCategories(solution)
val faults = DetectedFaultUtils.getDetectedFaults(solution)

assertTrue(ExperimentalFaultCategory.SECURITY_STACK_TRACE in faultsCategories)
assertTrue(ExperimentalFaultCategory.LEAKED_STACK_TRACES in faultsCategories)

// GET:/api/resources/null-pointer_not_stack_trace
assertTrue(faults.none {
it.category == ExperimentalFaultCategory.SECURITY_STACK_TRACE
it.category == ExperimentalFaultCategory.LEAKED_STACK_TRACES
&& it.operationId == "GET:/api/resources/null-pointer_not_stack_trace"
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ class StackTraceJSONEMTest : SpringTestBase(){
val faultsCategories = DetectedFaultUtils.getDetectedFaultCategories(solution)
val faults = DetectedFaultUtils.getDetectedFaults(solution)

assertTrue(ExperimentalFaultCategory.SECURITY_STACK_TRACE in faultsCategories)
assertTrue(ExperimentalFaultCategory.LEAKED_STACK_TRACES in faultsCategories)

assertTrue(faults.any {
it.category == ExperimentalFaultCategory.SECURITY_STACK_TRACE
it.category == ExperimentalFaultCategory.LEAKED_STACK_TRACES
&& it.operationId == "GET:/api/resources/null-pointer-json"
})

assertTrue(faults.any {
it.category == ExperimentalFaultCategory.SECURITY_STACK_TRACE
it.category == ExperimentalFaultCategory.LEAKED_STACK_TRACES
&& it.operationId == "GET:/api/resources/null-pointer-json-not-list"
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,6 @@ open class BodySQLiApplication: SwaggerConfiguration() {
@PostConstruct
fun init() {
connection = dataSource.connection
initializeTestData()
}

private fun initializeTestData() {
if (userRepository.count() == 0L) {
userRepository.save(UserEntity(null, "admin", "admin123"))
userRepository.save(UserEntity(null, "user1", "password1"))
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,6 @@ open class PathSQLiApplication: SwaggerConfiguration() {
@PostConstruct
fun init() {
connection = dataSource.connection
initializeTestData()
}

private fun initializeTestData() {
if (userRepository.count() == 0L) {
userRepository.save(UserEntity(null, "admin", "admin123"))
userRepository.save(UserEntity(null, "user1", "password1"))
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,6 @@ open class QuerySQLiApplication: SwaggerConfiguration() {
@PostConstruct
fun init() {
connection = dataSource.connection
initializeTestData()
}

private fun initializeTestData() {
if (userRepository.count() == 0L) {
userRepository.save(UserEntity(null, "admin", "admin123"))
userRepository.save(UserEntity(null, "user1", "password1"))
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
insert into users (id, username, password) values (1,'admin', 'pass1');
insert into users (id, username, password) values (2,'user', 'user');
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ abstract class SpringRestPostgresController(
.apply{withEnv("POSTGRES_HOST_AUTH_METHOD","trust")}


private var sqlConnection: Connection? = null
var sqlConnection: Connection? = null


init {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package com.foo.spring.rest.postgres.sqli

import com.foo.spring.rest.postgres.SpringRestPostgresController
import com.foo.spring.rest.postgres.sqli.body.BodySQLiApplication
import org.evomaster.client.java.controller.api.dto.database.schema.DatabaseType
import org.evomaster.client.java.sql.DbSpecification

class SQLiPostgresBodyController : SpringRestPostgresController(BodySQLiApplication::class.java){
override fun pathToFlywayFiles() = "classpath:/schema/sqli"
override fun getDbSpecifications(): MutableList<DbSpecification>? {
return null
}
override fun getDbSpecifications(): MutableList<DbSpecification>? = mutableListOf(
DbSpecification(
DatabaseType.POSTGRES,
sqlConnection
).withSchemas("public").withInitSqlOnResourcePath("/schema/sqli/data.sql"))
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package com.foo.spring.rest.postgres.sqli

import com.foo.spring.rest.postgres.SpringRestPostgresController
import com.foo.spring.rest.postgres.sqli.path.PathSQLiApplication
import org.evomaster.client.java.controller.api.dto.database.schema.DatabaseType
import org.evomaster.client.java.sql.DbSpecification

class SQLiPostgresPathController : SpringRestPostgresController(PathSQLiApplication::class.java){
override fun pathToFlywayFiles() = "classpath:/schema/sqli"
override fun getDbSpecifications(): MutableList<DbSpecification>? {
return null
}
override fun getDbSpecifications(): MutableList<DbSpecification>? = mutableListOf(
DbSpecification(
DatabaseType.POSTGRES,
sqlConnection
).withSchemas("public").withInitSqlOnResourcePath("/schema/sqli/data.sql"))
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package com.foo.spring.rest.postgres.sqli

import com.foo.spring.rest.postgres.SpringRestPostgresController
import com.foo.spring.rest.postgres.sqli.query.QuerySQLiApplication
import org.evomaster.client.java.controller.api.dto.database.schema.DatabaseType
import org.evomaster.client.java.sql.DbSpecification

class SQLiPostgresQueryController : SpringRestPostgresController(QuerySQLiApplication::class.java){
override fun pathToFlywayFiles() = "classpath:/schema/sqli"
override fun getDbSpecifications(): MutableList<DbSpecification>? {
return null
}
override fun getDbSpecifications(): MutableList<DbSpecification>? = mutableListOf(
DbSpecification(
DatabaseType.POSTGRES,
sqlConnection
).withSchemas("public").withInitSqlOnResourcePath("/schema/sqli/data.sql"))
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ class SQLiPostgresPathEMTest : SpringRestPostgresTestBase() {

runTestHandlingFlakyAndCompilation(
"SQLiPostgresPathEM",
100
200
) { args ->
setOption(args, "security", "true")
setOption(args, "sqli", "true")
//this is done to force a check on a specific invariant regarding existing data positioning
setOption(args, "probOfSelectFromDatabase", "0.9")

val solution = initAndRun(args)
assertTrue(solution.individuals.isNotEmpty())
Expand Down
3 changes: 1 addition & 2 deletions core/src/main/kotlin/org/evomaster/core/EMConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2830,10 +2830,9 @@ class EMConfig {
@DependsOnTrueFor("sqli")
var sqliBaselineMaxResponseTimeMs = 2000


@Regex(faultCodeRegex)
@Cfg("Disable oracles. Provide a comma-separated list of codes to disable. " +
"By default, all oracles are enabled."
"By default, all oracles are enabled. Codes are based on WFC (Web Fuzzing Commons)."
)
var disabledOracleCodes = ""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ object SqlWriter {
index == 0 && format.isJava() -> "List<InsertionDto> $insertionVar = sql($previousVar)"
index == 0 && format.isKotlin() -> "val $insertionVar = sql($previousVar)"
else -> ".and()"
} + ".insertInto(\"${evaluatedDbAction.sqlAction.table.name}\", ${evaluatedDbAction.sqlAction.geInsertionId()}L)")
} + ".insertInto(\"${evaluatedDbAction.sqlAction.table.name}\", ${evaluatedDbAction.sqlAction.insertionId}L)")

if (index == 0) {
lines.indent()
Expand Down
Loading