Skip to content

Conversation

@herpf
Copy link
Contributor

@herpf herpf commented Dec 16, 2025

Hi there, please find a bug I faced while unzipping a file (with certificate encryption):
Title
Fix index out of range panic in ZIP accessor during directory traversal for deeply nested paths

Content:
This PR addresses a runtime panic in the ZIP file accessor (accessors/zip/zip.go) caused by an off-by-one error leading to a slice index out of range. The issue occurs in the ZipFileCache.GetChildren method during prefix-matching for directory listings or globbing operations.
Specifically, when listing children of a directory (full_path) with a certain depth (e.g., 10+ path components), the code iterates over each potential ZIP entry (cd_cache) to check if it matches the prefix. However, it does not first ensure that the entry's path (cd_cache.full_path.Components) is long enough to match the directory's depth before accessing indices in the inner loop:

for j, component := range full_path.Components {
    if component != cd_cache.full_path.Components[j] {
        if !nocase || !strings.EqualFold(component, cd_cache.full_path.Components[j]) {
            continue loop
        }
    }
}

If a ZIP entry has fewer components than len(full_path.Components), accessing cd_cache.full_path.Components[j] panics when j exceeds the entry's length. This is common in forensic ZIP collections with irregular or varying path depths, triggering during globbing (glob.(*Globber).ExpandWithContext via ReadDirWithOSPath).
The panic manifests as "runtime error: index out of range [N] with length N" (e.g., [9] with length 9), indicating an attempt to access the Nth index on a slice of exactly N elements.
This affects Velociraptor versions at least up to 0.75.1 (tested on darwin-arm64 builds). It prevents unzipping collections with deep nesting, crashing mid-extraction.

Steps to Reproduce:

Create or use a ZIP file with entries of varying path depths (e.g., some with 8 components, others with 10+).
Run velociraptor unzip on the ZIP with a config that triggers deep traversal (e.g., forensic collections).
Observe the panic when processing entries under a directory with depth > entry length.

Redacted Error Sample:
The following is a redacted log excerpt from a failed unzip operation (paths and usernames obfuscated). The crash happens after uploading files with ~8 components, while attempting to list a deeper directory:

[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/DiagnosticMessages/2025.12.12.asl (113151 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/DiagnosticMessages/2025.12.13.asl (70547 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/DiagnosticMessages/StoreData (8 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/com.apple.wifi.analytics/ch.out (371944 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/com.apple.wifi.analytics/unavail.out (2521 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/com.apple.wifi.analytics/usage.out (6400 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/db/com.apple.xpc.launchd/disabled.502.plist (688 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/Users/[REDACTED]/.zsh_history (303 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/Users/[REDACTED]/Library/Containers/com.apple.Safari/.com.apple.containermanagerd.metadata.plist (62235 bytes) 
panic: runtime error: index out of range [9] with length 9


goroutine 160 [running]:
www.velocidex.com/golang/velociraptor/accessors/zip.(*ZipFileCache).GetChildren(0x1400093cc60, 0x1400138e280, 0x1)
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/accessors/zip/zip.go:435 +0x6d8
www.velocidex.com/golang/velociraptor/accessors/zip.(*ZipFileSystemAccessor).ReadDirWithOSPath(0x140007f8bc0, 0x1400138e280)
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/accessors/zip/accessor.go:325 +0x70
www.velocidex.com/golang/velociraptor/accessors/collector.(*CollectorAccessor).ReadDirWithOSPath(0x140007f8be0, 0x104ae46d8?)
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/accessors/collector/collector.go:408 +0x38
www.velocidex.com/golang/velociraptor/glob.(*Globber).ExpandWithContext.func1()
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/glob/glob.go:322 +0x184
created by www.velocidex.com/golang/velociraptor/glob.(*Globber).ExpandWithContext in goroutine 186
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/glob/glob.go:304 +0x140

Proposed Fix:
Add a length check before the prefix-matching loop to skip entries shorter than or equal to the directory depth. This ensures only potential child entries are processed, preventing invalid index access.
The fix has been tested locally on affected ZIP files (e.g., forensic collections) and resolves the panic, allowing full extraction.

@scudette scudette merged commit c65a0f8 into Velocidex:master Dec 16, 2025
5 checks passed
scudette pushed a commit that referenced this pull request Dec 23, 2025
Hi there, please find a bug I faced while unzipping a file (with
certificate encryption):
**Title**
Fix index out of range panic in ZIP accessor during directory traversal
for deeply nested paths

**Content:**
This PR addresses a runtime panic in the ZIP file accessor
(accessors/zip/zip.go) caused by an off-by-one error leading to a slice
index out of range. The issue occurs in the ZipFileCache.GetChildren
method during prefix-matching for directory listings or globbing
operations.
Specifically, when listing children of a directory (full_path) with a
certain depth (e.g., 10+ path components), the code iterates over each
potential ZIP entry (cd_cache) to check if it matches the prefix.
However, it does not first ensure that the entry's path
(cd_cache.full_path.Components) is long enough to match the directory's
depth before accessing indices in the inner loop:

```
for j, component := range full_path.Components {
    if component != cd_cache.full_path.Components[j] {
        if !nocase || !strings.EqualFold(component, cd_cache.full_path.Components[j]) {
            continue loop
        }
    }
}
```
If a ZIP entry has fewer components than len(full_path.Components),
accessing cd_cache.full_path.Components[j] panics when j exceeds the
entry's length. This is common in forensic ZIP collections with
irregular or varying path depths, triggering during globbing
(glob.(*Globber).ExpandWithContext via ReadDirWithOSPath).
The panic manifests as "runtime error: index out of range [N] with
length N" (e.g., [9] with length 9), indicating an attempt to access the
Nth index on a slice of exactly N elements.
This affects Velociraptor versions at least up to 0.75.1 (tested on
darwin-arm64 builds). It prevents unzipping collections with deep
nesting, crashing mid-extraction.

**Steps to Reproduce:**

Create or use a ZIP file with entries of varying path depths (e.g., some
with 8 components, others with 10+).
Run velociraptor unzip on the ZIP with a config that triggers deep
traversal (e.g., forensic collections).
Observe the panic when processing entries under a directory with depth >
entry length.

Redacted Error Sample:
The following is a redacted log excerpt from a failed unzip operation
(paths and usernames obfuscated). The crash happens after uploading
files with ~8 components, while attempting to list a deeper directory:
```
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/DiagnosticMessages/2025.12.12.asl (113151 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/DiagnosticMessages/2025.12.13.asl (70547 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/DiagnosticMessages/StoreData (8 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/com.apple.wifi.analytics/ch.out (371944 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/com.apple.wifi.analytics/unavail.out (2521 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/com.apple.wifi.analytics/usage.out (6400 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/db/com.apple.xpc.launchd/disabled.502.plist (688 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/Users/[REDACTED]/.zsh_history (303 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/Users/[REDACTED]/Library/Containers/com.apple.Safari/.com.apple.containermanagerd.metadata.plist (62235 bytes) 
panic: runtime error: index out of range [9] with length 9


goroutine 160 [running]:
www.velocidex.com/golang/velociraptor/accessors/zip.(*ZipFileCache).GetChildren(0x1400093cc60, 0x1400138e280, 0x1)
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/accessors/zip/zip.go:435 +0x6d8
www.velocidex.com/golang/velociraptor/accessors/zip.(*ZipFileSystemAccessor).ReadDirWithOSPath(0x140007f8bc0, 0x1400138e280)
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/accessors/zip/accessor.go:325 +0x70
www.velocidex.com/golang/velociraptor/accessors/collector.(*CollectorAccessor).ReadDirWithOSPath(0x140007f8be0, 0x104ae46d8?)
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/accessors/collector/collector.go:408 +0x38
www.velocidex.com/golang/velociraptor/glob.(*Globber).ExpandWithContext.func1()
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/glob/glob.go:322 +0x184
created by www.velocidex.com/golang/velociraptor/glob.(*Globber).ExpandWithContext in goroutine 186
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/glob/glob.go:304 +0x140
```


**Proposed Fix:**
Add a length check before the prefix-matching loop to skip entries
shorter than or equal to the directory depth. This ensures only
potential child entries are processed, preventing invalid index access.
The fix has been tested locally on affected ZIP files (e.g., forensic
collections) and resolves the panic, allowing full extraction.
scudette pushed a commit that referenced this pull request Dec 23, 2025
Hi there, please find a bug I faced while unzipping a file (with
certificate encryption):
**Title**
Fix index out of range panic in ZIP accessor during directory traversal
for deeply nested paths

**Content:**
This PR addresses a runtime panic in the ZIP file accessor
(accessors/zip/zip.go) caused by an off-by-one error leading to a slice
index out of range. The issue occurs in the ZipFileCache.GetChildren
method during prefix-matching for directory listings or globbing
operations.
Specifically, when listing children of a directory (full_path) with a
certain depth (e.g., 10+ path components), the code iterates over each
potential ZIP entry (cd_cache) to check if it matches the prefix.
However, it does not first ensure that the entry's path
(cd_cache.full_path.Components) is long enough to match the directory's
depth before accessing indices in the inner loop:

```
for j, component := range full_path.Components {
    if component != cd_cache.full_path.Components[j] {
        if !nocase || !strings.EqualFold(component, cd_cache.full_path.Components[j]) {
            continue loop
        }
    }
}
```
If a ZIP entry has fewer components than len(full_path.Components),
accessing cd_cache.full_path.Components[j] panics when j exceeds the
entry's length. This is common in forensic ZIP collections with
irregular or varying path depths, triggering during globbing
(glob.(*Globber).ExpandWithContext via ReadDirWithOSPath).
The panic manifests as "runtime error: index out of range [N] with
length N" (e.g., [9] with length 9), indicating an attempt to access the
Nth index on a slice of exactly N elements.
This affects Velociraptor versions at least up to 0.75.1 (tested on
darwin-arm64 builds). It prevents unzipping collections with deep
nesting, crashing mid-extraction.

**Steps to Reproduce:**

Create or use a ZIP file with entries of varying path depths (e.g., some
with 8 components, others with 10+).
Run velociraptor unzip on the ZIP with a config that triggers deep
traversal (e.g., forensic collections).
Observe the panic when processing entries under a directory with depth >
entry length.

Redacted Error Sample:
The following is a redacted log excerpt from a failed unzip operation
(paths and usernames obfuscated). The crash happens after uploading
files with ~8 components, while attempting to list a deeper directory:
```
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/DiagnosticMessages/2025.12.12.asl (113151 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/DiagnosticMessages/2025.12.13.asl (70547 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/DiagnosticMessages/StoreData (8 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/com.apple.wifi.analytics/ch.out (371944 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/com.apple.wifi.analytics/unavail.out (2521 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/log/com.apple.wifi.analytics/usage.out (6400 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/var/db/com.apple.xpc.launchd/disabled.502.plist (688 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/Users/[REDACTED]/.zsh_history (303 bytes) 
[INFO] 2025-12-16T18:20:21Z Uploaded /Users/[REDACTED]/Downloads/uploads/auto/Users/[REDACTED]/Library/Containers/com.apple.Safari/.com.apple.containermanagerd.metadata.plist (62235 bytes) 
panic: runtime error: index out of range [9] with length 9


goroutine 160 [running]:
www.velocidex.com/golang/velociraptor/accessors/zip.(*ZipFileCache).GetChildren(0x1400093cc60, 0x1400138e280, 0x1)
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/accessors/zip/zip.go:435 +0x6d8
www.velocidex.com/golang/velociraptor/accessors/zip.(*ZipFileSystemAccessor).ReadDirWithOSPath(0x140007f8bc0, 0x1400138e280)
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/accessors/zip/accessor.go:325 +0x70
www.velocidex.com/golang/velociraptor/accessors/collector.(*CollectorAccessor).ReadDirWithOSPath(0x140007f8be0, 0x104ae46d8?)
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/accessors/collector/collector.go:408 +0x38
www.velocidex.com/golang/velociraptor/glob.(*Globber).ExpandWithContext.func1()
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/glob/glob.go:322 +0x184
created by www.velocidex.com/golang/velociraptor/glob.(*Globber).ExpandWithContext in goroutine 186
/Users/jenkins/workspace/velociraptor-build_PR-28/velociraptor/glob/glob.go:304 +0x140
```


**Proposed Fix:**
Add a length check before the prefix-matching loop to skip entries
shorter than or equal to the directory depth. This ensures only
potential child entries are processed, preventing invalid index access.
The fix has been tested locally on affected ZIP files (e.g., forensic
collections) and resolves the panic, allowing full extraction.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants