diff --git a/Frontmatter.Test/YamlAliasTests.cs b/Frontmatter.Test/YamlAliasTests.cs
new file mode 100644
index 0000000..d485c1e
--- /dev/null
+++ b/Frontmatter.Test/YamlAliasTests.cs
@@ -0,0 +1,70 @@
+// Copyright (c) 2023-2026 ktsu-dev contributors
+
+namespace ktsu.Frontmatter.Test;
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+///
+/// Regression tests for YAML aliases. An alias inside its own anchor used to overflow the stack, which
+/// killed the process, and nested aliases used to expand exponentially.
+///
+[TestClass]
+public class YamlAliasTests
+{
+ // Six levels of ten aliases each expand to a million values.
+ private static readonly string AliasBomb = string.Join("\n",
+ "a: &a [x, x, x, x, x, x, x, x, x, x]",
+ "b: &b [*a, *a, *a, *a, *a, *a, *a, *a, *a, *a]",
+ "c: &c [*b, *b, *b, *b, *b, *b, *b, *b, *b, *b]",
+ "d: &d [*c, *c, *c, *c, *c, *c, *c, *c, *c, *c]",
+ "e: &e [*d, *d, *d, *d, *d, *d, *d, *d, *d, *d]",
+ "f: &f [*e, *e, *e, *e, *e, *e, *e, *e, *e, *e]");
+
+ [TestMethod]
+ public void TryParseYamlObject_SequenceContainsItsOwnAlias_ReturnsFalse()
+ {
+ Assert.IsFalse(YamlSerializer.TryParseYamlObject("a: &x [1, *x]", out Dictionary? result));
+ Assert.IsNull(result);
+ }
+
+ [TestMethod]
+ public void TryParseYamlObject_MappingContainsItsOwnAlias_ReturnsFalse()
+ {
+ Assert.IsFalse(YamlSerializer.TryParseYamlObject("a: &x {b: *x}", out Dictionary? result));
+ Assert.IsNull(result);
+ }
+
+ [TestMethod]
+ public void TryParseYamlObject_NestedAliasesExpandPastTheLimit_ReturnsFalse() =>
+ Assert.IsFalse(YamlSerializer.TryParseYamlObject(AliasBomb, out _));
+
+ [TestMethod]
+ public void TryParseYamlObject_AliasUsedTwiceWithoutACycle_ExpandsBothUses()
+ {
+ Assert.IsTrue(YamlSerializer.TryParseYamlObject("a: &x [p, q]\nb: *x\nc: [*x, *x]", out Dictionary? result));
+
+ CollectionAssert.AreEqual(new object[] { "p", "q" }, ((List