Skip to content

security(storage): keep the repository signing key out of list() enumeration - #965

Merged
ertime037 merged 1 commit into
mainfrom
feat/891-signing-key-leak
Sep 6, 2026
Merged

security(storage): keep the repository signing key out of list() enumeration#965
ertime037 merged 1 commit into
mainfrom
feat/891-signing-key-leak

Conversation

@devitway

@devitway devitway commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

The repository signing private key lives at <storage.path>/.signing/nora.key and is persisted owner-only (0600). But StorageBackend::list() / list_with_meta() enumerated it as if it were an artifact — only the pin sidecar was excluded — so it was swept into every enumeration-based operation:

  • backup wrote it into the tar at mode 0644 (widened from the on-disk 0600), and restore then left it 0644 on disk;
  • migrate --to s3 copied it into the bucket as a plaintext object, with no owner-only protection;
  • GC/retention walked it as an unreferenced artifact (able to delete the signing identity), and the browse UI listed it.

This excludes the .signing/ prefix from both backends' enumeration (local + object store), mirroring the existing pin-sidecar exclusion, through a single shared is_reserved_signing_key helper. The key is loaded through direct filesystem I/O, never through list(), so the exclusion has zero runtime impact; operators provision it out-of-band.

Tests

Regression guards that fail without the fix:

  • list() no longer surfaces the key (storage::local::tests::list_excludes_signing_key);
  • a backup tar no longer contains it (backup::tests::test_backup_omits_signing_key).

@devitway
devitway requested a review from ertime037 as a code owner September 6, 2026 08:09
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

🐳 Test image pushed: ghcr.io/getnora-io/nora:pr-965

docker pull ghcr.io/getnora-io/nora:pr-965
docker run --rm -p 4000:4000 ghcr.io/getnora-io/nora:pr-965

@devitway devitway closed this Sep 6, 2026
@devitway
devitway force-pushed the feat/891-signing-key-leak branch from be4a77f to 7d95325 Compare September 6, 2026 08:35
…eration

StorageBackend::list()/list_with_meta() enumerated the .signing/ key as an artifact, so backup (0644 tar), migrate (plaintext object) and GC swept it up. Exclude the .signing/ prefix on both backends via a shared is_reserved_signing_key helper; the key loads via direct filesystem I/O, never list(), so zero runtime impact. Regression tests: list_excludes_signing_key, test_backup_omits_signing_key.
@devitway devitway reopened this Sep 6, 2026
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

🐳 Test image pushed: ghcr.io/getnora-io/nora:pr-965

docker pull ghcr.io/getnora-io/nora:pr-965
docker run --rm -p 4000:4000 ghcr.io/getnora-io/nora:pr-965

@ertime037
ertime037 added this pull request to the merge queue Sep 6, 2026
Merged via the queue into main with commit 08c782e Sep 6, 2026
20 checks passed
@ertime037
ertime037 deleted the feat/891-signing-key-leak branch September 6, 2026 09:04
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