Skip to content

XSS Starter#1383

Merged
arcuri82 merged 23 commits intomasterfrom
xss-starter
Nov 26, 2025
Merged

XSS Starter#1383
arcuri82 merged 23 commits intomasterfrom
xss-starter

Conversation

@omursahin
Copy link
Copy Markdown
Collaborator

No description provided.

@omursahin omursahin requested a review from arcuri82 November 6, 2025 11:55
// Simple XSS payloads inspired by big-list-of-naughty-strings
// https://github.com/minimaxir/big-list-of-naughty-strings/blob/master/blns.txt
val XSS_PAYLOADS = listOf(
"javascript:alert('XSS')",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these examples are fine, but not the first javascript:alert('XSS'). it can be used in manual testing, but for automated API testing, might lead to too many false positives. remove it and keep the rest

var payloadInjected = false

// Attempt to inject payload into parameters
actionCopy.parameters.filter { it is BodyParam || it is QueryParam || it is PathParam }.forEach { param ->
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this check necessary? i mean, why skipping HeaderParam? i guess we could skip the filter isn't it?

actionCopy.parameters.filter { it is BodyParam || it is QueryParam || it is PathParam }.forEach { param ->

// Skip if PathParam and payload contains "/" (would break URL structure)
if(param is PathParam && payload.contains("/")){
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in theory, this should be possible, but we need to fix it. leave the comment: TODO this in theory should be fine if properly escape entries in RestPath

return@forEach
}

val genes = param.primaryGene().flatView()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better to use GeneUtils.getAllStringFields. also should check for staticCheckIfImpactPhenotype()


try {
// Check if constraints (min-max length) allow the payload
if(payload.length >= gene.minLength && payload.length <= gene.maxLength){
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are duplicating logic here. better to use gene.setFromStringValue and see whether it returns true/false

getAction.parameters.filter { it is BodyParam || it is QueryParam || it is PathParam }.forEach { param ->
val genes = param.primaryGene().flatView()

genes.forEach { gene ->
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see previous comments

}
} catch(e: Exception){
// Constraints might not allow the payload
log.debug("Failed to inject XSS payload into GET ${gene.name}: ${e.message}")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warn


val added = archive.addIfNeeded(evaluatedIndividual)
evaluatedIndividual.individual.seeMainExecutableActions().forEach {
println("$action - ${it.verb} ${it.path} -> ${it.auth.name} - ${added}")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was this a debug log you forgot to remove?


import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fine now, but not longer add new tests to spring-rest-openapi-v2. do for -v3, as -v2 will be refactored out into external driver (long story...)

]
)
@GetMapping(path = ["/user/{username}"], produces = [MediaType.TEXT_HTML_VALUE])
open fun getUserProfile(@PathVariable username: String): String {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these examples are fine... but remember XSS in APIs is not only when response are in HTML, but also in JSON (or XML). eg, think about SPA where the HTML is built on browser. add at least one test where response is JSON

@omursahin omursahin requested a review from arcuri82 November 24, 2025 20:40
// XSS-like payloads are injected or when user input is not properly sanitized. The try-catch block ensures
// that these exceptions do not interrupt the main processing loop.

log.warn("Failed to evaluate constructed individual in handleStackTraceCheck")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a +e.getMessage() to this warn log

payload: String
): RestIndividual? {

val getIndividuals = RestIndividualSelectorUtils.findIndividuals(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add //TODO to properly handle POST, we need first to finish the work on CallGraphService

@omursahin omursahin requested a review from arcuri82 November 25, 2025 14:32
@arcuri82 arcuri82 merged commit 39d2fcb into master Nov 26, 2025
13 checks passed
@arcuri82 arcuri82 deleted the xss-starter branch April 13, 2026 06:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants