mirror of https://github.com/sbt/sbt.git
[2.x] fix: Guard diskcache against path traversal (#9605)
**Problem** There are several places in diskcache where resolve is called without guards. **Solution** This adds guards to prevent path traversal.
This commit is contained in:
parent
e8f40d68c3
commit
0ae3c152bd
|
|
@ -278,6 +278,15 @@ case class DiskActionCacheStore(base: Path, converter: FileConverter)
|
||||||
try Files.exists(casFile) && Digest.sameDigest(casFile, digest)
|
try Files.exists(casFile) && Digest.sameDigest(casFile, digest)
|
||||||
catch case _: NoSuchFileException => false
|
catch case _: NoSuchFileException => false
|
||||||
|
|
||||||
|
private def requireWithinBase(base: Path, target: Path, ref: HashedVirtualFileRef): Path =
|
||||||
|
val normalizedBase = base.toAbsolutePath.normalize()
|
||||||
|
val normalizedTarget = target.toAbsolutePath.normalize()
|
||||||
|
if normalizedTarget.startsWith(normalizedBase) then target
|
||||||
|
else
|
||||||
|
throw new IOException(
|
||||||
|
s"Refusing to sync ${ref.id}: resolved path $normalizedTarget is outside $normalizedBase"
|
||||||
|
)
|
||||||
|
|
||||||
private def getBlobs(refs: Seq[HashedVirtualFileRef]): Seq[VirtualFile] =
|
private def getBlobs(refs: Seq[HashedVirtualFileRef]): Seq[VirtualFile] =
|
||||||
refs.flatMap: r =>
|
refs.flatMap: r =>
|
||||||
try
|
try
|
||||||
|
|
@ -343,9 +352,13 @@ case class DiskActionCacheStore(base: Path, converter: FileConverter)
|
||||||
val result = linkOrCopy(outPath)
|
val result = linkOrCopy(outPath)
|
||||||
afterFileWrite(ref, result, outputDirectory)
|
afterFileWrite(ref, result, outputDirectory)
|
||||||
result
|
result
|
||||||
val resolvedPath = converter.toPath(ref) match
|
val resolvedPath = requireWithinBase(
|
||||||
case p if p.isAbsolute => p
|
outputDirectory,
|
||||||
case p => outputDirectory.resolve(p)
|
converter.toPath(ref) match
|
||||||
|
case p if p.isAbsolute => p
|
||||||
|
case p => outputDirectory.resolve(p),
|
||||||
|
ref
|
||||||
|
)
|
||||||
resolvedPath match
|
resolvedPath match
|
||||||
case p if !Files.exists(p) =>
|
case p if !Files.exists(p) =>
|
||||||
// println(s"- syncFile: $p does not exist")
|
// println(s"- syncFile: $p does not exist")
|
||||||
|
|
@ -407,7 +420,7 @@ case class DiskActionCacheStore(base: Path, converter: FileConverter)
|
||||||
// manifest contains the list of files in the dirzip, and their hashes
|
// manifest contains the list of files in the dirzip, and their hashes
|
||||||
val m = ActionCache.manifestFromFile(mPath)
|
val m = ActionCache.manifestFromFile(mPath)
|
||||||
m.outputFiles.foreach: ref =>
|
m.outputFiles.foreach: ref =>
|
||||||
val currentItem = converter.toPath(ref)
|
val currentItem = requireWithinBase(outputDirectory, converter.toPath(ref), ref)
|
||||||
val shortPath = outputDirectory.relativize(currentItem).toString
|
val shortPath = outputDirectory.relativize(currentItem).toString
|
||||||
allPaths.remove(currentItem)
|
allPaths.remove(currentItem)
|
||||||
val d = Digest(ref)
|
val d = Digest(ref)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue