Skip to content

Commit 23ad9a2

Browse files
committed
Security: Block raw DLL references, enforce NuGet-only dependencies
This change prevents users from adding .dll files to job packages. All external dependencies must be declared as NuGet packages in the .nuspec file and resolved via NuGetResolverService. Changes: 1. CodeExecutorService.cs (Core/Services) - Removed code that blindly loaded all .dll files from extracted packages - Added security check that rejects execution if any .dll files are found in the package - Removed secondary loop that pre-loaded package DLLs into the AppDomain - NuGet-resolved assemblies (via .nuspec) continue to work as before 2. JobManager.cs (Core) - Replaced the DLL scanning/loading loop with a security check - Throws InvalidOperationException if .dll files are found in the package - Logs a security-level error message identifying the rejected DLL files 3. NuGetPackageBuilderService.cs (Core/Services) - Added validation at the start of BuildPackageAsync() - Rejects the build if the source directory contains any .dll files - Returns a clear error message listing the offending files 4. PackageProcessorService.cs (Core/Services) - Added DLL detection to ValidateNuSpecAsync() - Packages containing .dll files now fail validation with a descriptive error 5. JobDetailsDialog.razor (Web/Components/Pages/Dialogs) - Added client-side validation during package upload (.nupkg/.zip) - Inspects zip archive entries for .dll files before uploading - Rejects upload with a user-friendly notification listing found DLLs Defense in depth: The restriction is enforced at every layer - package build, package upload, package validation, and package execution.
1 parent 7816844 commit 23ad9a2

5 files changed

Lines changed: 57 additions & 33 deletions

File tree

src/BlazorDataOrchestrator.Core/JobManager.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -494,12 +494,14 @@ public async Task RunJobAsync(int jobInstanceId)
494494

495495
var evaluator = CSScript.Evaluator;
496496

497-
// Add references to all DLLs found in the package
497+
// Security: Reject packages that contain .dll files.
498+
// Only NuGet package dependencies (resolved via .nuspec) are allowed.
498499
var dlls = Directory.GetFiles(tempDir, "*.dll", SearchOption.AllDirectories);
499-
foreach (var dll in dlls)
500+
if (dlls.Length > 0)
500501
{
501-
evaluator.ReferenceAssembly(dll);
502-
await LogAsync("RunJob", $"Added reference: {Path.GetFileName(dll)}", "Debug");
502+
var dllNames = string.Join(", ", dlls.Select(System.IO.Path.GetFileName));
503+
await LogAsync("RunJob", $"Security: Rejected package containing .dll files: {dllNames}", "Error");
504+
throw new InvalidOperationException($"Package contains .dll files which are not allowed. Use NuGet packages instead. Found: {dllNames}");
503505
}
504506

505507
// Load and execute

src/BlazorDataOrchestrator.Core/Services/CodeExecutorService.cs

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -177,19 +177,16 @@ private async Task<CodeExecutionResult> ExecuteCSharpAsync(string extractedPath,
177177
}
178178
}
179179

180-
// Add references to DLLs found in the package
180+
// Security: Reject packages that contain .dll files.
181+
// Only NuGet package dependencies (resolved via .nuspec) are allowed.
181182
var dlls = Directory.GetFiles(extractedPath, "*.dll", SearchOption.AllDirectories);
182-
foreach (var dll in dlls)
183+
if (dlls.Length > 0)
183184
{
184-
try
185-
{
186-
evaluator.ReferenceAssembly(dll);
187-
result.Logs.Add($"Added reference: {Path.GetFileName(dll)}");
188-
}
189-
catch
190-
{
191-
// Ignore DLLs that can't be loaded
192-
}
185+
var dllNames = string.Join(", ", dlls.Select(Path.GetFileName));
186+
result.Success = false;
187+
result.ErrorMessage = $"Package contains .dll files which are not allowed. Use NuGet packages instead. Found: {dllNames}";
188+
result.Logs.Add($"Security: Rejected package containing .dll files: {dllNames}");
189+
return result;
193190
}
194191

195192
// Add common references
@@ -234,24 +231,6 @@ private async Task<CodeExecutionResult> ExecuteCSharpAsync(string extractedPath,
234231
}
235232
}
236233

237-
// Also load DLLs from the package
238-
foreach (var dll in dlls)
239-
{
240-
try
241-
{
242-
var loadedAsm = Assembly.LoadFrom(dll);
243-
var asmName = loadedAsm.GetName().Name;
244-
if (asmName != null && !loadedAssemblies.ContainsKey(asmName))
245-
{
246-
loadedAssemblies[asmName] = loadedAsm;
247-
}
248-
}
249-
catch
250-
{
251-
// Ignore DLLs that can't be loaded
252-
}
253-
}
254-
255234
result.Logs.Add($"Pre-loaded {loadedAssemblies.Count} assemblies for runtime resolution.");
256235

257236
// Set up assembly resolve handler for the compiled script

src/BlazorDataOrchestrator.Core/Services/NuGetPackageBuilderService.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,21 @@ public async Task<PackageBuildResult> BuildPackageAsync(PackageBuildConfiguratio
125125
var csharpFolder = Path.Combine(config.CodeRootPath, "CodeCSharp");
126126
var pythonFolder = Path.Combine(config.CodeRootPath, "CodePython");
127127

128+
// Security: Reject source directories that contain .dll files.
129+
// Users must use NuGet package dependencies declared in .nuspec instead.
130+
if (Directory.Exists(config.CodeRootPath))
131+
{
132+
var dllFiles = Directory.GetFiles(config.CodeRootPath, "*.dll", SearchOption.AllDirectories);
133+
if (dllFiles.Length > 0)
134+
{
135+
var dllNames = string.Join(", ", dllFiles.Select(Path.GetFileName));
136+
result.Success = false;
137+
result.ErrorMessage = $"Source directory contains .dll files which are not allowed in packages. Use NuGet packages instead. Found: {dllNames}";
138+
result.Logs.Add($"Security: Rejected build due to .dll files: {dllNames}");
139+
return result;
140+
}
141+
}
142+
128143
// Copy JSON files from the root Code folder
129144
if (Directory.Exists(config.CodeRootPath))
130145
{

src/BlazorDataOrchestrator.Core/Services/PackageProcessorService.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,15 @@ public async Task<PackageValidationResult> ValidateNuSpecAsync(string extractedP
140140
}
141141
}
142142

143+
// Security: Reject packages containing .dll files.
144+
// Users must use NuGet package dependencies declared in .nuspec instead.
145+
var dllFiles = Directory.GetFiles(extractedPath, "*.dll", SearchOption.AllDirectories);
146+
if (dllFiles.Length > 0)
147+
{
148+
var dllNames = string.Join(", ", dllFiles.Select(Path.GetFileName));
149+
result.Errors.Add($"Package contains .dll files which are not allowed. Only NuGet package dependencies (declared in .nuspec) are permitted. Found: {dllNames}");
150+
}
151+
143152
result.IsValid = result.Errors.Count == 0;
144153
return result;
145154
}

src/BlazorOrchestrator.Web/Components/Pages/Dialogs/JobDetailsDialog.razor

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,25 @@ Content-Type: application/json
803803
await stream.CopyToAsync(memoryStream);
804804
memoryStream.Position = 0;
805805

806+
// Security: Validate that the package does not contain .dll files.
807+
// Users must use NuGet package dependencies declared in .nuspec instead.
808+
using (var archive = new System.IO.Compression.ZipArchive(memoryStream, System.IO.Compression.ZipArchiveMode.Read, leaveOpen: true))
809+
{
810+
var dllEntries = archive.Entries
811+
.Where(e => e.FullName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
812+
.Select(e => e.FullName)
813+
.ToList();
814+
815+
if (dllEntries.Count > 0)
816+
{
817+
var dllNames = string.Join(", ", dllEntries.Select(Path.GetFileName));
818+
NotificationService.Notify(NotificationSeverity.Error, "Upload Rejected",
819+
$"Package contains .dll files which are not allowed. Use NuGet packages instead. Found: {dllNames}");
820+
return;
821+
}
822+
}
823+
memoryStream.Position = 0;
824+
806825
// Upload package using JobManager - this updates Job.JobCodeFile automatically
807826
var blobName = await JobManager.UploadJobPackageAsync(JobId, memoryStream, SelectedFile.Name);
808827

0 commit comments

Comments
 (0)