diff --git a/Makefile b/Makefile
index 380b9e0c79..474c2c0f99 100644
--- a/Makefile
+++ b/Makefile
@@ -42,6 +42,18 @@ CSC = mcs $(SDK)
CSFLAGS = -nologo -warn:4 -codepage:utf8 -langversion:5 -unsafe -warnaserror
DEFINE = TRACE
COMMON_LIBS = System.dll System.Core.dll System.Numerics.dll thirdparty/download/ICSharpCode.SharpZipLib.dll thirdparty/download/FuzzyLogicLibrary.dll thirdparty/download/MaxMind.Db.dll thirdparty/download/Eluant.dll thirdparty/download/rix0rrr.BeaconLib.dll
+
+# List of .NET assemblies that we can guarantee exist
+# OpenRA.Game.dll is a harmless false positive that we can ignore
+WHITELISTED_OPENRA_ASSEMBLIES = $(game_TARGET) $(utility_TARGET) $(pdefault_TARGET) $(mod_common_TARGET) $(mod_cnc_TARGET) $(mod_d2k_TARGET) OpenRA.Game.dll
+
+# These are explicitly shipped alongside our core files by the packaging script
+WHITELISTED_THIRDPARTY_ASSEMBLIES = ICSharpCode.SharpZipLib.dll FuzzyLogicLibrary.dll MaxMind.Db.dll Eluant.dll rix0rrr.BeaconLib.dll Open.Nat.dll SDL2-CS.dll OpenAL-CS.dll
+
+# These are shipped in our custom minimal mono runtime and also available in the full system-installed .NET/mono stack
+# This list *must* be kept in sync with the files packaged by the AppImageSupport repository
+WHITELISTED_CORE_ASSEMBLIES = mscorlib.dll System.dll System.Configuration.dll System.Core.dll System.Numerics.dll System.Security.dll System.Xml.dll Mono.Security.dll
+
NUNIT_LIBS_PATH :=
NUNIT_LIBS := $(NUNIT_LIBS_PATH)nunit.framework.dll
@@ -164,6 +176,9 @@ check-scripts:
@luac -p $(shell find lua/* -iname '*.lua')
check: utility stylecheck mods
+ @echo
+ @echo "Checking runtime assemblies..."
+ @mono --debug OpenRA.Utility.exe all --check-runtime-assemblies $(WHITELISTED_OPENRA_ASSEMBLIES) $(WHITELISTED_THIRDPARTY_ASSEMBLIES) $(WHITELISTED_CORE_ASSEMBLIES)
@echo
@echo "Checking for explicit interface violations..."
@mono --debug OpenRA.Utility.exe all --check-explicit-interfaces
diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index 6d430e9415..e8d7017d4f 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -612,6 +612,7 @@
+
diff --git a/OpenRA.Mods.Common/UtilityCommands/CheckRuntimeAssembliesCommand.cs b/OpenRA.Mods.Common/UtilityCommands/CheckRuntimeAssembliesCommand.cs
new file mode 100644
index 0000000000..df60a527fe
--- /dev/null
+++ b/OpenRA.Mods.Common/UtilityCommands/CheckRuntimeAssembliesCommand.cs
@@ -0,0 +1,58 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
+ * This file is part of OpenRA, which is free software. It is made
+ * available to you under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version. For more
+ * information, see COPYING.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+
+namespace OpenRA.Mods.Common.UtilityCommands
+{
+ public class CheckRuntimeAssembliesCommand : IUtilityCommand
+ {
+ string IUtilityCommand.Name { get { return "--check-runtime-assemblies"; } }
+
+ bool IUtilityCommand.ValidateArguments(string[] args)
+ {
+ return true;
+ }
+
+ [Desc("ASSEMBLY [ASSEMBLY ...]", "Check the runtime dependencies of the mod against a given whitelist of " +
+ "assembly (dll and exe) names and generate an error if any unlisted files are required.")]
+ void IUtilityCommand.Run(Utility utility, string[] args)
+ {
+ var whitelist = args
+ .Skip(1)
+ .Select(a => Path.GetFileName(a))
+ .ToArray();
+
+ // Load the renderer assembly so we can check its dependencies
+ Assembly.LoadFile(Platform.ResolvePath(Path.Combine(".", "OpenRA.Platforms.Default.dll")));
+
+ var missing = new List();
+ foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
+ {
+ var assemblyName = Path.GetFileName(a.Location);
+ if (!whitelist.Contains(assemblyName))
+ missing.Add(assemblyName);
+ }
+
+ if (missing.Any())
+ {
+ Console.WriteLine("error: The following assemblies are referenced but not whitelisted:");
+ foreach (var m in missing)
+ Console.WriteLine(" " + m);
+ Environment.Exit(1);
+ }
+ }
+ }
+}