Skip to content
Open
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
10 changes: 10 additions & 0 deletions src/main/kotlin/net/portswigger/mcp/config/McpConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ class McpConfig(storage: PersistedObject, private val logging: Logging) {
}
}

private var _filterConfigCredentials by storage.boolean(true)
var filterConfigCredentials: Boolean
get() = _filterConfigCredentials
set(value) {
if (_filterConfigCredentials != value) {
_filterConfigCredentials = value
notifyHistoryAccessChanged()
}
}

fun addAutoApproveTarget(target: String): Boolean {
val currentTargets = getAutoApproveTargetsList()
if (target.trim().isNotEmpty() && !currentTargets.contains(target.trim())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ class ServerConfigurationPanel(
config.requireHistoryAccessApproval
) { config.alwaysAllowWebSocketHistory = it }
add(alwaysAllowWebSocketHistoryCheckBox)
add(createVerticalStrut(Design.Spacing.MD))

val filterConfigCredentialsCheckBox = createCheckBoxWithSubtitle(
"Filter config credentials",
"Hides sensitive data in config files (Platform Authentication, socks proxy, etc.)",
config.filterConfigCredentials
) { config.filterConfigCredentials = it }
add(filterConfigCredentialsCheckBox)

add(validationErrorLabel)
}
Expand Down
42 changes: 42 additions & 0 deletions src/main/kotlin/net/portswigger/mcp/security/SecurityUtils.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
package net.portswigger.mcp.security

import java.awt.Frame
import net.portswigger.mcp.config.McpConfig
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.*

@Serializable
data class SecurityConfig(
val options: Map<String, Map<String, JsonElement>>
)

/**
* Finds the Burp Suite main frame or the largest available frame as fallback
Expand All @@ -17,4 +25,38 @@ fun findBurpFrame(): Frame? {
} ?: Frame.getFrames()
.filter { it.isVisible && it.isDisplayable }
.maxByOrNull { it.width * it.height }
}

fun filterConfigCredentials(json: String): String {
return try {
val jsonElement = Json.parseToJsonElement(json)
val filteredElement = filterJsonElement(jsonElement)
Json.encodeToString(filteredElement)
} catch (e: Exception) {
throw RuntimeException("Failed to filter credentials", e)
}
}

private fun filterJsonElement(element: JsonElement): JsonElement {
return when (element) {
is JsonObject -> filterJsonObject(element)
is JsonArray -> filterJsonArray(element)
else -> element
}
}

private fun filterJsonObject(obj: JsonObject): JsonObject {
val filteredMap = obj.mapValues { (key, value) ->
when {
value is JsonPrimitive && value.isString && key == "password" ->
JsonPrimitive("*****")
else -> filterJsonElement(value)
}
}
return JsonObject(filteredMap)
}

private fun filterJsonArray(array: JsonArray): JsonArray {
val filteredList = array.map { element -> filterJsonElement(element) }
return JsonArray(filteredList)
}
15 changes: 13 additions & 2 deletions src/main/kotlin/net/portswigger/mcp/tools/Tools.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import net.portswigger.mcp.schema.toSerializableForm
import net.portswigger.mcp.security.HistoryAccessSecurity
import net.portswigger.mcp.security.HistoryAccessType
import net.portswigger.mcp.security.HttpRequestSecurity
import net.portswigger.mcp.security.filterConfigCredentials
import java.awt.KeyboardFocusManager
import java.util.regex.Pattern
import javax.swing.JTextArea
Expand Down Expand Up @@ -147,14 +148,24 @@ fun Server.registerTools(api: MontoyaApi, config: McpConfig) {
"output_project_options",
"Outputs current project-level configuration in JSON format. You can use this to determine the schema for available config options."
) {
api.burpSuite().exportProjectOptionsAsJson()
val json = api.burpSuite().exportProjectOptionsAsJson()
if (config.filterConfigCredentials == true) {
filterConfigCredentials(json)
} else {
json
}
}

mcpTool(
"output_user_options",
"Outputs current user-level configuration in JSON format. You can use this to determine the schema for available config options."
) {
api.burpSuite().exportUserOptionsAsJson()
val json = api.burpSuite().exportUserOptionsAsJson()
if (config.filterConfigCredentials == true) {
filterConfigCredentials(json)
} else {
json
}
}

val toolingDisabledMessage =
Expand Down
Loading