Do not serve derivations with /nix-support/private

This commit is contained in:
Aleix Boné 2025-10-03 17:28:01 +02:00
parent a098861c8d
commit 70cd4f1ec5
No known key found for this signature in database
2 changed files with 38 additions and 0 deletions

View File

@ -48,6 +48,7 @@ executable nix-serve
, base32 , base32
, bytestring , bytestring
, charset , charset
, directory
, http-types , http-types
, managed , managed
, megaparsec , megaparsec

View File

@ -10,6 +10,7 @@ import Control.Monad.IO.Class (liftIO)
import Data.ByteString (ByteString) import Data.ByteString (ByteString)
import Data.CharSet.ByteSet (ByteSet(..)) import Data.CharSet.ByteSet (ByteSet(..))
import Data.Function ((&)) import Data.Function ((&))
import Data.Word (Word8)
import Network.Socket (SockAddr(..)) import Network.Socket (SockAddr(..))
import Network.Wai (Application) import Network.Wai (Application)
import Nix (NoSuchPath(..), PathInfo(..)) import Nix (NoSuchPath(..), PathInfo(..))
@ -35,6 +36,7 @@ import qualified Network.Wai.Middleware.RequestLogger as RequestLogger
import qualified Nix import qualified Nix
import qualified Options import qualified Options
import qualified Options.Applicative as Options import qualified Options.Applicative as Options
import qualified System.Directory as Directory
import qualified System.Environment as Environment import qualified System.Environment as Environment
data ApplicationOptions = ApplicationOptions data ApplicationOptions = ApplicationOptions
@ -54,6 +56,20 @@ validHashPartBytes =
<> [ 0x76 .. 0x7A ] -- vwxyz <> [ 0x76 .. 0x7A ] -- vwxyz
) )
type HostAddressTuple = (Word8, Word8, Word8, Word8)
isInWhitelist :: Socket.HostAddress -> Bool
isInWhitelist host = any (uncurry (inRange $ Socket.hostAddressToTuple host)) allowedIPs
where
allowedIPs :: [(HostAddressTuple, HostAddressTuple)]
allowedIPs = [
((127,0,0,1), (127,0,0,1)),
((10,0,0,1), (10,255,255,254)),
((192,168,72,1), (192,168,79,254))
]
inRange ip a b = ip >= a && ip <= b
validHashPart :: ByteString -> Bool validHashPart :: ByteString -> Bool
validHashPart hash = ByteString.all (`ByteSet.member` validHashPartBytes) hash validHashPart hash = ByteString.all (`ByteSet.member` validHashPartBytes) hash
@ -250,6 +266,27 @@ makeApplication ApplicationOptions{..} request respond = do
done response done response
let privateFilePath = ByteString.Char8.unpack storePath ++ "/nix-support/private"
isPrivate <- liftIO $ Directory.doesPathExist privateFilePath
let isLocal = case Wai.remoteHost request of
SockAddrInet _ host -> isInWhitelist host
_ -> False
Monad.when (isPrivate && not isLocal) do
let headers = [ ("Content-Type", "text/plain") ]
let builder = "Forbidden.\n"
let response =
Wai.responseBuilder
Types.status403
headers
builder
done response
let streamingBody write flush = do let streamingBody write flush = do
result <- Nix.dumpPath hashPart callback result <- Nix.dumpPath hashPart callback