secret list reports the time of the listing as every secret's creation and last-update time #142

Open
opened 2026-10-13 00:30:22 +02:00 by clawbot · 0 comments
Collaborator

Severity: major. The LAST UPDATED column and the created_at/updated_at fields of --json are wrong for every secret: they always hold the current time.

What happens. GetSecretObject calls Secret.LoadMetadata, which is marked deprecated and sets both times to time.Now(); printSecretsTable and printSecretsJSON print them.

echo v | secret add s1
secret list --json | grep updated_at    # "updated_at": "2026-10-12T22:20:24.98Z"
sleep 3
secret list --json | grep updated_at    # "updated_at": "2026-10-12T22:20:28.00Z"

Where.

metadata := secretObj.GetMetadata()
and
metadata := secretObj.GetMetadata()
,
err = secretObj.LoadMetadata()
,
func (s *Secret) LoadMetadata() error {
Debug("LoadMetadata called but is deprecated in versioned model",
"secret_name", s.Name)
// For backward compatibility, we'll populate with basic info
now := time.Now()
s.Metadata = Metadata{
CreatedAt: now,
UpdatedAt: now,
}
return nil
}
.

Correct behaviour. Real times, or none. The true creation time is in each version's encrypted metadata.age, which list cannot read without unlocking. Recommended: take the last update from the modification time of the secret's current file (replaced on every add and promote) and the creation time from its oldest version directory, so list still needs no passphrase; otherwise drop the column and the two fields.

Definition of done

  • Two listings of an unchanged vault show the same times, and they match when the secret was added or updated; or no times are shown.
  • A test adds a secret, lists twice with a clock step between, and fails before the fix because the times differ.

Model: fable-5-1

Severity: major. The `LAST UPDATED` column and the `created_at`/`updated_at` fields of `--json` are wrong for every secret: they always hold the current time. **What happens.** `GetSecretObject` calls `Secret.LoadMetadata`, which is marked deprecated and sets both times to `time.Now()`; `printSecretsTable` and `printSecretsJSON` print them. ``` echo v | secret add s1 secret list --json | grep updated_at # "updated_at": "2026-10-12T22:20:24.98Z" sleep 3 secret list --json | grep updated_at # "updated_at": "2026-10-12T22:20:28.00Z" ``` **Where.** https://git.eeqj.de/sneak/secret/src/commit/ef0ae90768c8b18a829033b3ebd4cf98fcaeb3d1/internal/cli/secrets.go#L547 and https://git.eeqj.de/sneak/secret/src/commit/ef0ae90768c8b18a829033b3ebd4cf98fcaeb3d1/internal/cli/secrets.go#L622, https://git.eeqj.de/sneak/secret/src/commit/ef0ae90768c8b18a829033b3ebd4cf98fcaeb3d1/internal/vault/secrets.go#L452, https://git.eeqj.de/sneak/secret/src/commit/ef0ae90768c8b18a829033b3ebd4cf98fcaeb3d1/internal/secret/secret.go#L77-L88. **Correct behaviour.** Real times, or none. The true creation time is in each version's encrypted `metadata.age`, which `list` cannot read without unlocking. Recommended: take the last update from the modification time of the secret's `current` file (replaced on every add and promote) and the creation time from its oldest version directory, so `list` still needs no passphrase; otherwise drop the column and the two fields. **Definition of done** - Two listings of an unchanged vault show the same times, and they match when the secret was added or updated; or no times are shown. - A test adds a secret, lists twice with a clock step between, and fails before the fix because the times differ. Model: fable-5-1
sneak was assigned by clawbot 2026-10-13 00:30:22 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/secret#142