Bug: NumSecrets() always returns 0 due to incorrect directory traversal #4

Open
opened 2026-02-08 21:01:50 +01:00 by clawbot · 0 comments

Bug

In internal/vault/vault.go, the NumSecrets() method counts secrets by looking for non-directory files (excluding current) directly under each secret's directory:

for _, vFile := range versionFiles {
    if !vFile.IsDir() && vFile.Name() != "current" {
        count++
        break
    }
}

However, the actual directory structure of a secret is:

secrets.d/<name>/
  current         (file - version pointer)
  versions/       (directory)
    20240101.001/ (directory with actual data)

The only direct children of a secret directory are current (excluded by the filter) and versions (excluded by !vFile.IsDir()). This means the condition is never true and NumSecrets() always returns 0.

Impact

  • UnlockersRemove uses NumSecrets() to check if removing the last unlocker is safe. Since it always returns 0, users can always remove the last unlocker without --force, even when secrets exist.
  • The info command may show incorrect secret counts.

Fix

Should check if the versions subdirectory contains entries, or simply check for the existence of the current file.

## Bug In `internal/vault/vault.go`, the `NumSecrets()` method counts secrets by looking for non-directory files (excluding `current`) directly under each secret's directory: ```go for _, vFile := range versionFiles { if !vFile.IsDir() && vFile.Name() != "current" { count++ break } } ``` However, the actual directory structure of a secret is: ``` secrets.d/<name>/ current (file - version pointer) versions/ (directory) 20240101.001/ (directory with actual data) ``` The only direct children of a secret directory are `current` (excluded by the filter) and `versions` (excluded by `!vFile.IsDir()`). This means the condition is **never true** and `NumSecrets()` always returns 0. ## Impact - `UnlockersRemove` uses `NumSecrets()` to check if removing the last unlocker is safe. Since it always returns 0, users can always remove the last unlocker without `--force`, even when secrets exist. - The `info` command may show incorrect secret counts. ## Fix Should check if the `versions` subdirectory contains entries, or simply check for the existence of the `current` file.
Sign in to join this conversation.
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: sneak/secret#4
No description provided.