diff --git a/signals/attachment_count.yml b/signals/attachments/attachment_count.yml
similarity index 100%
rename from signals/attachment_count.yml
rename to signals/attachments/attachment_count.yml
diff --git a/signals/attachment_filesizes.yml b/signals/attachments/attachment_filesizes.yml
similarity index 100%
rename from signals/attachment_filesizes.yml
rename to signals/attachments/attachment_filesizes.yml
diff --git a/signals/content/body_tracking_pixel.yml b/signals/content/body_tracking_pixel.yml
new file mode 100644
index 00000000000..63ea71b5eef
--- /dev/null
+++ b/signals/content/body_tracking_pixel.yml
@@ -0,0 +1,13 @@
+name: "Tracking pixel in HTML body"
+type: "query"
+source: |
+ (
+ // standard html
+ regex.contains(body.html.raw,
+ ']*?width="1(px)?"[^>]*?height="1(px)?"[^>]*?style="[^"]*(visibility:hidden|display:none)[^"]*"[^>]*?>'
+ )
+ // handle quoted printable variants
+ or regex.contains(body.html.raw,
+ ''
+ )
+ )
diff --git a/signals/headers/headers_fake_thread.yml b/signals/headers/headers_fake_thread.yml
new file mode 100644
index 00000000000..4573126026c
--- /dev/null
+++ b/signals/headers/headers_fake_thread.yml
@@ -0,0 +1,9 @@
+name: "Fake message thread"
+type: "query"
+source: |
+ type.inbound
+ and strings.istarts_with(subject.subject, "RE:")
+ and (
+ length(headers.references) == 0
+ or not any(headers.hops, any(.fields, strings.ilike(.name, "In-Reply-To")))
+ )
diff --git a/signals/headers/headers_gmail_autoforward.yml b/signals/headers/headers_gmail_autoforward.yml
new file mode 100644
index 00000000000..b8e4abf63ba
--- /dev/null
+++ b/signals/headers/headers_gmail_autoforward.yml
@@ -0,0 +1,7 @@
+name: "Gmail Auto-Forward"
+type: "query"
+source: |
+ any([headers.return_path.email],
+ strings.ilike(headers.return_path.local_part, "*+caf_=*") and type.inbound
+ )
+
diff --git a/signals/headers/headers_microsoft_scl.yml b/signals/headers/headers_microsoft_scl.yml
new file mode 100644
index 00000000000..6f501f14a24
--- /dev/null
+++ b/signals/headers/headers_microsoft_scl.yml
@@ -0,0 +1,8 @@
+name: "Microsoft SCL"
+type: "query"
+source: |
+ filter(
+ map(headers.hops,
+ map(filter(.fields, .name =~ "X-ms-exchange-organization-scl"), .value)
+ ), length(.) > 0
+ )
diff --git a/signals/headers/headers_mismatched_from_reply_to.yml b/signals/headers/headers_mismatched_from_reply_to.yml
new file mode 100644
index 00000000000..b6c05c0dace
--- /dev/null
+++ b/signals/headers/headers_mismatched_from_reply_to.yml
@@ -0,0 +1,7 @@
+name: "Mismatched From and Reply-to Doms"
+type: "query"
+source: |
+ any(headers.reply_to,
+ length(headers.reply_to) > 0
+ and all(headers.reply_to, .email.domain.root_domain != sender.email.domain.root_domain)
+ )
diff --git a/signals/headers/headers_mismatched_from_return_path.yml b/signals/headers/headers_mismatched_from_return_path.yml
new file mode 100644
index 00000000000..4557ab04dad
--- /dev/null
+++ b/signals/headers/headers_mismatched_from_return_path.yml
@@ -0,0 +1,8 @@
+name: "Mismatched From and Return-Path"
+type: "query"
+source: |
+ any([headers.return_path.email],
+ (headers.return_path.email is not null
+ and headers.return_path.email != sender.email.email
+ and type.inbound)
+ )
diff --git a/signals/headers/headers_phishing_simulation_cofense.yml b/signals/headers/headers_phishing_simulation_cofense.yml
new file mode 100644
index 00000000000..1a6427e8350
--- /dev/null
+++ b/signals/headers/headers_phishing_simulation_cofense.yml
@@ -0,0 +1,16 @@
+name: "Cofense PhishMe phishing simulation"
+type: "query"
+source: |
+ any(headers.ips, .ip in (
+ "13.113.166.58",
+ "35.182.57.68",
+ "52.1.96.230",
+ "52.20.128.29",
+ "52.20.155.14",
+ "52.28.182.143",
+ "52.28.252.18",
+ "52.29.24.224",
+ "52.29.5.79",
+ "52.5.119.169",
+ "52.62.59.61",
+ ))
diff --git a/signals/headers/headers_phishing_simulation_hoxhunt.yml b/signals/headers/headers_phishing_simulation_hoxhunt.yml
new file mode 100644
index 00000000000..97463d5042a
--- /dev/null
+++ b/signals/headers/headers_phishing_simulation_hoxhunt.yml
@@ -0,0 +1,4 @@
+name: "HoxHunt phishing simulation"
+type: "query"
+source: |
+ any(headers.hops, strings.ends_with(.signature.domain, ".hoxhuntsigning.com"))
diff --git a/signals/headers/headers_phishing_simulation_knowbe4.yml b/signals/headers/headers_phishing_simulation_knowbe4.yml
new file mode 100644
index 00000000000..9fc45b7a381
--- /dev/null
+++ b/signals/headers/headers_phishing_simulation_knowbe4.yml
@@ -0,0 +1,4 @@
+name: "KnowBe4 phishing simulation"
+type: "query"
+source: |
+ any(headers.ips, regex.match(.ip, '147\.10\.167\.([0-9]|[0-5][0-9]|6[0-3])', '23.21.109.(197|212)', '52.49.(201.246|235.189)'))
diff --git a/signals/headers/headers_undisclosed_recipients.yml b/signals/headers/headers_undisclosed_recipients.yml
new file mode 100644
index 00000000000..0f2e86ad8f3
--- /dev/null
+++ b/signals/headers/headers_undisclosed_recipients.yml
@@ -0,0 +1,6 @@
+name: "Undisclosed Recipients"
+type: "query"
+source: |
+ any([recipients.to, recipients.bcc, recipients.cc],
+ any(., .display_name =~ "Undisclosed recipients:")
+ )
diff --git a/signals/headers/headers_x_originating_ip.yml b/signals/headers/headers_x_originating_ip.yml
new file mode 100644
index 00000000000..07ee4ec53a1
--- /dev/null
+++ b/signals/headers/headers_x_originating_ip.yml
@@ -0,0 +1,4 @@
+name: "X-Originating-IP"
+type: "query"
+source: |
+ headers.x_originating_ip.ip