---
title: Use Internal Data For File Paths
impact: CRITICAL
impactDescription: prevents Path Traversal (LFI) attacks that allow reading sensitive system files
tags: file-path, path-traversal, lfi, input-validation, security, kotlin
---

## Use Internal Data For File Paths

User-provided input should never be used to construct file paths directly. An attacker can use sequences like `../` to escape the intended directory and access sensitive files on the server (e.g., `/etc/passwd`, database credentials, or source code).

**Incorrect (user-controlled path construction):**

```kotlin
// VULNERABLE: Direct use of filename from query
@GetMapping("/download")
fun download(@RequestParam filename: String, response: HttpServletResponse) {
    val file = File("/opt/app/uploads/$filename")
    // Attacker: ?filename=../../../../etc/passwd
    file.inputStream().use { it.copyTo(response.outputStream) }
}
```

**Correct (validation and sanitization):**

```kotlin
import java.nio.file.Paths
import kotlin.io.path.name

@GetMapping("/download")
fun safeDownload(@RequestParam filename: String): ResponseEntity<Resource> {
    // 1. Sanitize: Extract ONLY the filename, ignore any path components
    val safeName = Paths.get(filename).fileName.toString()
    
    // 2. Ideally: Map the filename to an internal ID or record in the DB
    val fileRecord = fileRepository.findByOriginalNameAndUserId(safeName, currentUserId)
        ?: throw NotFoundException("File not found")

    // 3. Use a static base directory and the SANITIZED name
    val baseDir = Paths.get("/opt/app/uploads").toAbsolutePath()
    val filePath = baseDir.resolve(safeName).normalize()

    // 4. Verify the resulting path is still inside the base directory
    if (!filePath.startsWith(baseDir)) {
        throw SecurityException("Invalid file path attempt")
    }

    val resource = FileUrlResource(filePath.toUri().toURL())
    return ResponseEntity.ok()
        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"$safeName\"")
        .body(resource)
}
```

**Security Principles:**
- **Whitelisting:** Store files with generated IDs (UUIDs) and look them up in a database.
- **Sanitization:** Use `Paths.get(name).fileName` to strip directory components.
- **Normalization:** Always call `.normalize()` and `.toAbsolutePath()` before checking if a path starts with your root directory.
- **Isolation:** Run the application with a dedicated user that has minimal filesystem permissions.

**Tools:** SonarQube (S2083), Semgrep, OWASP Path Traversal Cheat Sheet, Manual Review
