mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-05-25 01:57:02 +01:00
Fix GHSA-jg92-mrxq-vv75
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Extensions;
|
||||
|
||||
namespace MediaBrowser.Controller.ClientEvent
|
||||
{
|
||||
@@ -21,8 +22,15 @@ namespace MediaBrowser.Controller.ClientEvent
|
||||
/// <inheritdoc />
|
||||
public async Task<string> WriteDocumentAsync(string clientName, string clientVersion, Stream fileContents)
|
||||
{
|
||||
var fileName = $"upload_{clientName}_{clientVersion}_{DateTime.UtcNow:yyyyMMddHHmmss}_{Guid.NewGuid():N}.log";
|
||||
var safeClientName = PathHelper.GetSafeLeafFileName(clientName) ?? "unknown-client";
|
||||
var safeClientVersion = PathHelper.GetSafeLeafFileName(clientVersion) ?? "unknown-version";
|
||||
var fileName = $"upload_{safeClientName}_{safeClientVersion}_{DateTime.UtcNow:yyyyMMddHHmmss}_{Guid.NewGuid():N}.log";
|
||||
var logFilePath = Path.Combine(_applicationPaths.LogDirectoryPath, fileName);
|
||||
if (!PathHelper.IsContainedIn(_applicationPaths.LogDirectoryPath, logFilePath))
|
||||
{
|
||||
throw new ArgumentException("Path resolved to filename not in log directory");
|
||||
}
|
||||
|
||||
var fileStream = new FileStream(logFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.None);
|
||||
await using (fileStream.ConfigureAwait(false))
|
||||
{
|
||||
|
||||
44
tests/Jellyfin.Controller.Tests/ClientEventLoggerTests.cs
Normal file
44
tests/Jellyfin.Controller.Tests/ClientEventLoggerTests.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.ClientEvent;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Jellyfin.Controller.Tests
|
||||
{
|
||||
public class ClientEventLoggerTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("../../../../etc/passwd", "1.0")]
|
||||
[InlineData("..\\..\\windows\\system32", "1.0")]
|
||||
[InlineData("normal-client", "../../../etc/passwd")]
|
||||
[InlineData("/absolute/path", "1.0")]
|
||||
public async Task WriteDocumentAsync_TraversalInput_StaysInsideLogDirectory(string clientName, string clientVersion)
|
||||
{
|
||||
var logDir = Path.Combine(Path.GetTempPath(), "jellyfin-clientlog-test-" + Path.GetRandomFileName());
|
||||
Directory.CreateDirectory(logDir);
|
||||
try
|
||||
{
|
||||
var paths = new Mock<IServerApplicationPaths>();
|
||||
paths.Setup(p => p.LogDirectoryPath).Returns(logDir);
|
||||
|
||||
var logger = new ClientEventLogger(paths.Object);
|
||||
using var contents = new MemoryStream(Encoding.UTF8.GetBytes("payload"));
|
||||
|
||||
var fileName = await logger.WriteDocumentAsync(clientName, clientVersion, contents);
|
||||
|
||||
var resolved = Path.GetFullPath(Path.Combine(logDir, fileName));
|
||||
var rootWithSep = Path.GetFullPath(logDir) + Path.DirectorySeparatorChar;
|
||||
Assert.StartsWith(rootWithSep, resolved, StringComparison.Ordinal);
|
||||
Assert.True(File.Exists(resolved));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(logDir, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user