Skip to content

Commit fe8cf29

Browse files
Merge pull request from GHSA-wg4c-c9g9-rxhx
Fix issues 1 through 5 from GHSL-2021-050
2 parents 890a490 + 1f3aa3f commit fe8cf29

File tree

3 files changed

+61
-9
lines changed

3 files changed

+61
-9
lines changed

Jellyfin.Api/Controllers/HlsSegmentController.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,13 @@ public ActionResult GetHlsAudioSegmentLegacy([FromRoute, Required] string itemId
6161
{
6262
// TODO: Deprecate with new iOS app
6363
var file = segmentId + Path.GetExtension(Request.Path);
64-
file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file);
64+
var transcodePath = _serverConfigurationManager.GetTranscodePath();
65+
file = Path.GetFullPath(Path.Combine(transcodePath, file));
66+
var fileDir = Path.GetDirectoryName(file);
67+
if (string.IsNullOrEmpty(fileDir) || !fileDir.StartsWith(transcodePath))
68+
{
69+
return BadRequest("Invalid segment.");
70+
}
6571

6672
return FileStreamResponseHelpers.GetStaticFileResult(file, MimeTypes.GetMimeType(file)!, false, HttpContext);
6773
}
@@ -81,7 +87,13 @@ public ActionResult GetHlsAudioSegmentLegacy([FromRoute, Required] string itemId
8187
public ActionResult GetHlsPlaylistLegacy([FromRoute, Required] string itemId, [FromRoute, Required] string playlistId)
8288
{
8389
var file = playlistId + Path.GetExtension(Request.Path);
84-
file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file);
90+
var transcodePath = _serverConfigurationManager.GetTranscodePath();
91+
file = Path.GetFullPath(Path.Combine(transcodePath, file));
92+
var fileDir = Path.GetDirectoryName(file);
93+
if (string.IsNullOrEmpty(fileDir) || !fileDir.StartsWith(transcodePath) || Path.GetExtension(file) != ".m3u8")
94+
{
95+
return BadRequest("Invalid segment.");
96+
}
8597

8698
return GetFileResult(file, file);
8799
}
@@ -130,7 +142,12 @@ public ActionResult GetHlsVideoSegmentLegacy(
130142
var file = segmentId + Path.GetExtension(Request.Path);
131143
var transcodeFolderPath = _serverConfigurationManager.GetTranscodePath();
132144

133-
file = Path.Combine(transcodeFolderPath, file);
145+
file = Path.GetFullPath(Path.Combine(transcodeFolderPath, file));
146+
var fileDir = Path.GetDirectoryName(file);
147+
if (string.IsNullOrEmpty(fileDir) || !fileDir.StartsWith(transcodeFolderPath))
148+
{
149+
return BadRequest("Invalid segment.");
150+
}
134151

135152
var normalizedPlaylistId = playlistId;
136153

Jellyfin.Api/Controllers/ImageByNameController.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,19 @@ public ActionResult GetGeneralImage([FromRoute, Required] string name, [FromRout
7474
: type;
7575

7676
var path = BaseItem.SupportedImageExtensions
77-
.Select(i => Path.Combine(_applicationPaths.GeneralPath, name, filename + i))
77+
.Select(i => Path.GetFullPath(Path.Combine(_applicationPaths.GeneralPath, name, filename + i)))
7878
.FirstOrDefault(System.IO.File.Exists);
7979

8080
if (path == null)
8181
{
8282
return NotFound();
8383
}
8484

85+
if (!path.StartsWith(_applicationPaths.GeneralPath))
86+
{
87+
return BadRequest("Invalid image path.");
88+
}
89+
8590
var contentType = MimeTypes.GetMimeType(path);
8691
return File(System.IO.File.OpenRead(path), contentType);
8792
}
@@ -163,27 +168,39 @@ public ActionResult GetMediaInfoImage(
163168
/// <returns>A <see cref="FileStreamResult"/> containing the image contents on success, or a <see cref="NotFoundResult"/> if the image could not be found.</returns>
164169
private ActionResult GetImageFile(string basePath, string theme, string? name)
165170
{
166-
var themeFolder = Path.Combine(basePath, theme);
171+
var themeFolder = Path.GetFullPath(Path.Combine(basePath, theme));
172+
167173
if (Directory.Exists(themeFolder))
168174
{
169175
var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(themeFolder, name + i))
170176
.FirstOrDefault(System.IO.File.Exists);
171177

172178
if (!string.IsNullOrEmpty(path) && System.IO.File.Exists(path))
173179
{
180+
if (!path.StartsWith(basePath))
181+
{
182+
return BadRequest("Invalid image path.");
183+
}
184+
174185
var contentType = MimeTypes.GetMimeType(path);
186+
175187
return PhysicalFile(path, contentType);
176188
}
177189
}
178190

179-
var allFolder = Path.Combine(basePath, "all");
191+
var allFolder = Path.GetFullPath(Path.Combine(basePath, "all"));
180192
if (Directory.Exists(allFolder))
181193
{
182194
var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(allFolder, name + i))
183195
.FirstOrDefault(System.IO.File.Exists);
184196

185197
if (!string.IsNullOrEmpty(path) && System.IO.File.Exists(path))
186198
{
199+
if (!path.StartsWith(basePath))
200+
{
201+
return BadRequest("Invalid image path.");
202+
}
203+
187204
var contentType = MimeTypes.GetMimeType(path);
188205
return PhysicalFile(path, contentType);
189206
}

MediaBrowser.Providers/Subtitles/SubtitleManager.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,12 +205,30 @@ private async Task TrySaveSubtitle(
205205

206206
if (saveInMediaFolder)
207207
{
208-
savePaths.Add(Path.Combine(video.ContainingFolderPath, saveFileName));
208+
var mediaFolderPath = Path.GetFullPath(Path.Combine(video.ContainingFolderPath, saveFileName));
209+
// TODO: Add some error handling to the API user: return BadRequest("Could not save subtitle, bad path.");
210+
if (mediaFolderPath.StartsWith(video.ContainingFolderPath))
211+
{
212+
savePaths.Add(mediaFolderPath);
213+
}
209214
}
210215

211-
savePaths.Add(Path.Combine(video.GetInternalMetadataPath(), saveFileName));
216+
var internalPath = Path.GetFullPath(Path.Combine(video.GetInternalMetadataPath(), saveFileName));
217+
218+
// TODO: Add some error to the user: return BadRequest("Could not save subtitle, bad path.");
219+
if (internalPath.StartsWith(video.GetInternalMetadataPath()))
220+
{
221+
savePaths.Add(internalPath);
222+
}
212223

213-
await TrySaveToFiles(memoryStream, savePaths).ConfigureAwait(false);
224+
if (savePaths.Count > 0)
225+
{
226+
await TrySaveToFiles(memoryStream, savePaths).ConfigureAwait(false);
227+
}
228+
else
229+
{
230+
_logger.LogError("An uploaded subtitle could not be saved because the resulting paths were invalid.");
231+
}
214232
}
215233
}
216234

0 commit comments

Comments
 (0)