Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions examples/llama.swiftui/llama.swiftui/UI/DownloadButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ struct DownloadButton: View {

do {
if let temporaryURL = temporaryURL {
let tempDir = FileManager.default.temporaryDirectory
guard temporaryURL.path.hasPrefix(tempDir.path) else {
print("Security Error: Temporary file path is outside expected directory")
return
Comment on lines +52 to +54
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UX Issue: Silent Failure

When path validation fails, the code only prints to console with no user feedback. Users will see their download appear to complete but the file won't be saved, leading to confusion.

Current behavior:

guard temporaryURL.path.hasPrefix(tempDir.path) else {
    print("Security Error: Temporary file path is outside expected directory")
    return  // Silent failure - user sees no error
}

Suggested improvement:

guard temporaryURL.path.hasPrefix(tempDir.path) else {
    DispatchQueue.main.async {
        self.status = "download"  // Reset to allow retry
        // Consider adding an @State error message to display in UI
    }
    print("Security Error: Temporary file path is outside expected directory")
    return
}

Consider adding an error state variable to show security errors to users in the UI.

}
Comment on lines +51 to +55
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Issue: Insecure Path Validation

Using hasPrefix for path validation is vulnerable to path traversal attacks. This approach doesn't handle:

  1. Path normalization: Paths with .. components can bypass the check
  2. Symlinks: Symbolic links can point outside the allowed directory
  3. Path canonicalization: Different representations of the same path

Example Attack:

// If tempDir.path = "/tmp"
// An attacker could use: "/tmp/../var/tmp/malicious"
// This passes hasPrefix("/tmp") but resolves outside /tmp

Recommended Fix:

let tempDir = FileManager.default.temporaryDirectory
let resolvedTempURL = temporaryURL.standardizedFileURL.resolvingSymlinksInPath()
let resolvedTempDir = tempDir.standardizedFileURL.resolvingSymlinksInPath()

guard resolvedTempURL.path.hasPrefix(resolvedTempDir.path + "/") || resolvedTempURL.path == resolvedTempDir.path else {
    print("Security Error: Temporary file path is outside expected directory")
    return
}

The same fix should be applied to the destination path validation on lines 57-61.


let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
guard fileURL.path.hasPrefix(docsDir.path) else {
print("Security Error: Destination path is outside documents directory")
return
}
Comment on lines 51 to 61
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical Security Issue: Insufficient Path Validation

The current path validation using hasPrefix is vulnerable to path traversal attacks. This approach doesn't protect against:

  1. Symbolic links that could point outside the allowed directories
  2. Path components like .. that could escape the directory
  3. Non-canonical paths (e.g., /tmp/./../../etc/passwd)

Vulnerable Example:

let tempDir = "/tmp"  // path is "/tmp"
let maliciousPath = "/tmp/../../../etc/passwd"  // hasPrefix("/tmp") = true ✓ (bypassed!)

Recommended Fix:
Use standardizedFileURL or resolvingSymlinksInPath() to normalize paths before validation:

let tempDir = FileManager.default.temporaryDirectory
let normalizedTempURL = temporaryURL.standardizedFileURL
let normalizedTempDir = tempDir.standardizedFileURL

guard normalizedTempURL.path.hasPrefix(normalizedTempDir.path) else {
    print("Security Error: Temporary file path is outside expected directory")
    return
}

let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let normalizedFileURL = fileURL.standardizedFileURL
let normalizedDocsDir = docsDir.standardizedFileURL

guard normalizedFileURL.path.hasPrefix(normalizedDocsDir.path) else {
    print("Security Error: Destination path is outside documents directory")
    return
}

This ensures all symbolic links are resolved and relative path components are normalized before comparison.


try FileManager.default.copyItem(at: temporaryURL, to: fileURL)
print("Writing to \(filename) completed")

Expand Down
12 changes: 12 additions & 0 deletions examples/llama.swiftui/llama.swiftui/UI/InputButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ struct InputButton: View {

do {
if let temporaryURL = temporaryURL {
let tempDir = FileManager.default.temporaryDirectory
guard temporaryURL.path.hasPrefix(tempDir.path) else {
print("Security Error: Temporary file path is outside expected directory")
return
}

let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
guard fileURL.path.hasPrefix(docsDir.path) else {
print("Security Error: Destination path is outside documents directory")
return
}
Comment on lines 55 to 65
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same Security Issue: Insufficient Path Validation

This file has the identical path validation vulnerability as DownloadButton.swift. The hasPrefix check is insufficient and vulnerable to path traversal attacks.

Apply the same fix here:

let tempDir = FileManager.default.temporaryDirectory
let normalizedTempURL = temporaryURL.standardizedFileURL
let normalizedTempDir = tempDir.standardizedFileURL

guard normalizedTempURL.path.hasPrefix(normalizedTempDir.path) else {
    print("Security Error: Temporary file path is outside expected directory")
    return
}

let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let normalizedFileURL = fileURL.standardizedFileURL
let normalizedDocsDir = docsDir.standardizedFileURL

guard normalizedFileURL.path.hasPrefix(normalizedDocsDir.path) else {
    print("Security Error: Destination path is outside documents directory")
    return
}

See the comment on DownloadButton.swift for a detailed explanation of the vulnerability.


try FileManager.default.copyItem(at: temporaryURL, to: fileURL)
print("Writing to \(filename) completed")

Expand Down
2 changes: 1 addition & 1 deletion tools/server/webui/src/lib/constants/settings-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const SETTING_CONFIG_DEFAULT: Record<string, string | number | boolean> =
};

export const SETTING_CONFIG_INFO: Record<string, string> = {
apiKey: 'Set the API Key if you are using --api-key option for the server.',
apiKey: 'Configure the API Key for authentication. Never hardcode API keys in source code - use environment variables or secure configuration management instead.',
systemMessage: 'The starting message that defines how model should behave.',
theme:
'Choose the color theme for the interface. You can choose between System (follows your device settings), Light, or Dark.',
Expand Down
Loading