3e93416b9a
* Admit only valid OCI layout files when loading image. - Adds `AdmissionMapper` protocol for validating archive member paths and normalizing them to relative paths under the extraction root directory. - Renames `Reader.swift` to `ArchiveReader.swift` to match type name. - Rework `TempDir` to address `NSString.utf8String` deprecation warning in Swift 6.2.3. - Rework `ArchiveReader.extractContent()` to use an `AdmissionMapper` to validate and remap archive members before extracting. - Adds `IdentityAdmissionWrapper` for naive extraction. - Adds `NoSymlinkAdmissionWrapper` that only extracts regular files and directories under the extraction root. - Adds `OCIImageAdmissionWrapper` that only extracts valid OCI image layout paths. - Use `OCIImageAdmissionWrapper` for `cctl image load` and print rejected paths. * PR feedback. * Adds public init() for TrustedAdmissionMapper. * Replace AdmissionMapper with more secure extraction. - Adds FileDescriptor.mkdirSecure() to prevent root escapes on member pathnames, and to prevent symlink traversal. - Adds FileDescriptor.unlinkRecursive() to facilitate overwrites when there are multiple archive entries with the same member path. - Adds FileDescriptor.validateSymlinkTargetInRoot() to validate that extracted symlink targets do not escape the root. - Rewrite ArchiveReader.extractContents() to use secure path functions. * Remove unneeded symlink check, rename files. * Simplify the lexical normalizer workaround. * Reject member paths containing parent traversal components. * Remove unused lexical normalization workaround. * Fix leaking fds, extract absolute members as relative.
35 lines
1.5 KiB
Swift
35 lines
1.5 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import ContainerizationExtras
|
|
import Foundation
|
|
|
|
internal func createTemporaryDirectory(baseName: String) -> URL? {
|
|
let url = FileManager.default.uniqueTemporaryDirectory().appendingPathComponent(
|
|
"\(baseName).XXXXXX")
|
|
|
|
var path = url.absoluteURL.path
|
|
return path.withUTF8 { utf8Bytes in
|
|
var mutablePath = Array(utf8Bytes) + [0]
|
|
return mutablePath.withUnsafeMutableBufferPointer { buffer -> URL? in
|
|
guard let baseAddress = buffer.baseAddress else { return nil }
|
|
mkdtemp(baseAddress)
|
|
let resultPath = String(decoding: buffer[..<(buffer.count - 1)], as: UTF8.self)
|
|
return URL(fileURLWithPath: resultPath, isDirectory: true)
|
|
}
|
|
}
|
|
}
|