Skip to content

SSH private key used as raw PBKDF2 input without validation #397

@umag

Description

@umag

Summary

local_encryption_vault_provider.ts reads the entire SSH private key file (including PEM headers, newlines, and comments) and feeds it directly to PBKDF2 as raw key material. This has three issues:

  1. PEM envelope wastes entropy — the -----BEGIN OPENSSH PRIVATE KEY----- header/footer are fixed across all SSH keys (17.5% of a typical key file), adding zero entropy to PBKDF2 input.

  2. Encrypted SSH keys silently break — if the SSH key is protected with a passphrase, the file contains encrypted binary data. The code never checks for this and never prompts for a passphrase. Worse: changing the SSH passphrase (re-encrypting the same key) changes the file bytes, which changes the PBKDF2 derivation, silently making all previously encrypted vault secrets unrecoverable.

  3. No permission validationssh itself refuses to use a key file with permissions wider than 0600 ("Permissions 0644 for 'id_rsa' are too open"), but swamp reads it silently without warning.

Affected Code

local_encryption_vault_provider.ts lines 201-215:

const sshKeyContent = await Deno.readTextFile(expandedPath);
const keyBytes = new TextEncoder().encode(sshKeyContent);
return await crypto.subtle.importKey("raw", keyBytes, { name: "PBKDF2" }, false, ["deriveKey"]);

Steps to Reproduce

A Deno test repro demonstrates all three issues: PEM entropy dilution, encrypted vs unencrypted key divergence, and permission non-validation.

Expected Behavior

  • Parse the SSH key format and extract only the actual key material (after base64 decoding the PEM body)
  • Detect encrypted SSH keys and either prompt for passphrase or error with a clear message
  • Validate file permissions are 0600 and warn/error otherwise

Fix Approach

Either parse the OpenSSH key format properly (extract binary key material from the PEM body) or recommend users switch to auto_generate: true which avoids SSH keys entirely. At minimum, add a check for encrypted SSH keys (look for aes256-ctr or similar cipher in the key header) and validate file permissions.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingexternalAn issue raised by an external contributor

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions