diff --git a/app/Exports/ZipExportModels/ZipExportAttachment.php b/app/Exports/ZipExportModels/ZipExportAttachment.php
index d6d674a91..d79a16cc1 100644
--- a/app/Exports/ZipExportModels/ZipExportAttachment.php
+++ b/app/Exports/ZipExportModels/ZipExportAttachment.php
@@ -5,7 +5,7 @@ namespace BookStack\Exports\ZipExportModels;
 use BookStack\Exports\ZipExportFiles;
 use BookStack\Uploads\Attachment;
 
-class ZipExportAttachment implements ZipExportModel
+class ZipExportAttachment extends ZipExportModel
 {
     public ?int $id = null;
     public string $name;
diff --git a/app/Exports/ZipExportModels/ZipExportImage.php b/app/Exports/ZipExportModels/ZipExportImage.php
index 73fe3bbf5..540d3d4e5 100644
--- a/app/Exports/ZipExportModels/ZipExportImage.php
+++ b/app/Exports/ZipExportModels/ZipExportImage.php
@@ -4,7 +4,7 @@ namespace BookStack\Exports\ZipExportModels;
 
 use BookStack\Activity\Models\Tag;
 
-class ZipExportImage implements ZipExportModel
+class ZipExportImage extends ZipExportModel
 {
     public string $name;
     public string $file;
diff --git a/app/Exports/ZipExportModels/ZipExportModel.php b/app/Exports/ZipExportModels/ZipExportModel.php
index e1cb616de..26b994c01 100644
--- a/app/Exports/ZipExportModels/ZipExportModel.php
+++ b/app/Exports/ZipExportModels/ZipExportModel.php
@@ -2,10 +2,19 @@
 
 namespace BookStack\Exports\ZipExportModels;
 
-use BookStack\App\Model;
-use BookStack\Exports\ZipExportFiles;
+use JsonSerializable;
 
-interface ZipExportModel
+abstract class ZipExportModel implements JsonSerializable
 {
-//    public static function fromModel(Model $model, ZipExportFiles $files): self;
+    /**
+     * Handle the serialization to JSON.
+     * For these exports, we filter out optional (represented as nullable) fields
+     * just to clean things up and prevent confusion to avoid null states in the
+     * resulting export format itself.
+     */
+    public function jsonSerialize(): array
+    {
+        $publicProps = get_object_vars(...)->__invoke($this);
+        return array_filter($publicProps, fn ($value) => $value !== null);
+    }
 }
diff --git a/app/Exports/ZipExportModels/ZipExportPage.php b/app/Exports/ZipExportModels/ZipExportPage.php
index 6589ce60a..c7a950354 100644
--- a/app/Exports/ZipExportModels/ZipExportPage.php
+++ b/app/Exports/ZipExportModels/ZipExportPage.php
@@ -6,7 +6,7 @@ use BookStack\Entities\Models\Page;
 use BookStack\Entities\Tools\PageContent;
 use BookStack\Exports\ZipExportFiles;
 
-class ZipExportPage implements ZipExportModel
+class ZipExportPage extends ZipExportModel
 {
     public ?int $id = null;
     public string $name;
diff --git a/app/Exports/ZipExportModels/ZipExportTag.php b/app/Exports/ZipExportModels/ZipExportTag.php
index 636c9ff6d..09ae9f06c 100644
--- a/app/Exports/ZipExportModels/ZipExportTag.php
+++ b/app/Exports/ZipExportModels/ZipExportTag.php
@@ -4,7 +4,7 @@ namespace BookStack\Exports\ZipExportModels;
 
 use BookStack\Activity\Models\Tag;
 
-class ZipExportTag implements ZipExportModel
+class ZipExportTag extends ZipExportModel
 {
     public string $name;
     public ?string $value = null;
diff --git a/app/Exports/ZipExportReferences.php b/app/Exports/ZipExportReferences.php
index 89deb7eda..76a7fedbe 100644
--- a/app/Exports/ZipExportReferences.php
+++ b/app/Exports/ZipExportReferences.php
@@ -44,11 +44,14 @@ class ZipExportReferences
                 // TODO - Handle found link to $model
                 //   - Validate we can see/access $model, or/and that it's
                 //     part of the export in progress.
+
+                // TODO - Add images after the above to files
                 return '[CAT]';
             });
             // TODO - markdown
         }
 
+//        dd('end');
         // TODO - Parse chapter desc html
         // TODO - Parse book desc html
     }
diff --git a/app/Exports/ZipReferenceParser.php b/app/Exports/ZipReferenceParser.php
index 6ca826bc3..820920da2 100644
--- a/app/Exports/ZipReferenceParser.php
+++ b/app/Exports/ZipReferenceParser.php
@@ -4,9 +4,11 @@ namespace BookStack\Exports;
 
 use BookStack\App\Model;
 use BookStack\Entities\Queries\EntityQueries;
+use BookStack\References\ModelResolvers\AttachmentModelResolver;
 use BookStack\References\ModelResolvers\BookLinkModelResolver;
 use BookStack\References\ModelResolvers\ChapterLinkModelResolver;
 use BookStack\References\ModelResolvers\CrossLinkModelResolver;
+use BookStack\References\ModelResolvers\ImageModelResolver;
 use BookStack\References\ModelResolvers\PageLinkModelResolver;
 use BookStack\References\ModelResolvers\PagePermalinkModelResolver;
 
@@ -24,8 +26,8 @@ class ZipReferenceParser
             new PageLinkModelResolver($queries->pages),
             new ChapterLinkModelResolver($queries->chapters),
             new BookLinkModelResolver($queries->books),
-            // TODO - Image
-            // TODO - Attachment
+            new ImageModelResolver(),
+            new AttachmentModelResolver(),
         ];
     }
 
diff --git a/app/References/ModelResolvers/AttachmentModelResolver.php b/app/References/ModelResolvers/AttachmentModelResolver.php
new file mode 100644
index 000000000..e870d515b
--- /dev/null
+++ b/app/References/ModelResolvers/AttachmentModelResolver.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace BookStack\References\ModelResolvers;
+
+use BookStack\Uploads\Attachment;
+
+class AttachmentModelResolver implements CrossLinkModelResolver
+{
+    public function resolve(string $link): ?Attachment
+    {
+        $pattern = '/^' . preg_quote(url('/attachments'), '/') . '\/(\d+)/';
+        $matches = [];
+        $match = preg_match($pattern, $link, $matches);
+        if (!$match) {
+            return null;
+        }
+
+        $id = intval($matches[1]);
+
+        return Attachment::query()->find($id);
+    }
+}
diff --git a/app/References/ModelResolvers/ImageModelResolver.php b/app/References/ModelResolvers/ImageModelResolver.php
new file mode 100644
index 000000000..331dd593b
--- /dev/null
+++ b/app/References/ModelResolvers/ImageModelResolver.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace BookStack\References\ModelResolvers;
+
+use BookStack\Uploads\Image;
+
+class ImageModelResolver implements CrossLinkModelResolver
+{
+    public function resolve(string $link): ?Image
+    {
+        $pattern = '/^' . preg_quote(url('/uploads/images'), '/') . '\/(.+)/';
+        $matches = [];
+        $match = preg_match($pattern, $link, $matches);
+        if (!$match) {
+            return null;
+        }
+
+        $path = $matches[1];
+
+        // Strip thumbnail element from path if existing
+        $originalPathSplit = array_filter(explode('/', $path), function (string $part) {
+            $resizedDir = (str_starts_with($part, 'thumbs-') || str_starts_with($part, 'scaled-'));
+            $missingExtension = !str_contains($part, '.');
+
+            return !($resizedDir && $missingExtension);
+        });
+
+        // Build a database-format image path and search for the image entry
+        $fullPath = '/uploads/images/' . ltrim(implode('/', $originalPathSplit), '/');
+
+        return Image::query()->where('path', '=', $fullPath)->first();
+    }
+}