diff --git a/README.md b/README.md index d576a31..91bf121 100644 --- a/README.md +++ b/README.md @@ -46,11 +46,12 @@ A decentralized, Nostr-based git server that enables git repository hosting and - **Input Validation**: Validates commit messages, author names, emails, and file paths - **File Size Limits**: 500 MB maximum per file (allows for images and demo videos) - **Ownership Verification**: Verifies repository ownership via self-transfer events or verification files -- **Commit Signing**: Sign commits using Nostr private keys (nsec or hex format) - - Supports both bech32 (nsec) and hex format keys +- **Commit Signing**: Sign commits using Nostr private keys - Signatures embedded in commit messages as trailers - - Server-side signing via `NOSTRGIT_SECRET_KEY` environment variable - - Client-side signing via optional `nsecKey` parameter in API requests + - **Web UI**: Uses NIP-07 browser extension (secure, keys never leave browser) + - **Git Operations**: Uses NIP-98 HTTP authentication (ephemeral signed events) + - **Server-side**: Optional `NOSTRGIT_SECRET_KEY` environment variable for automated signing + - ⚠️ **Security Note**: Never send private keys (nsec) in API requests. Use NIP-07 for web UI or NIP-98 for git operations. ## Nostr Event Kinds Used diff --git a/src/lib/services/git/commit-signer.ts b/src/lib/services/git/commit-signer.ts index 06b7a0b..c298973 100644 --- a/src/lib/services/git/commit-signer.ts +++ b/src/lib/services/git/commit-signer.ts @@ -135,17 +135,20 @@ export function createCommitSignatureEvent( * by embedding them in the commit message or as a trailer * * Supports multiple signing methods: - * - NIP-07: Browser extension signing (client-side) + * - NIP-07: Browser extension signing (client-side, secure - keys never leave browser) * - NIP-98: Use HTTP auth event as signature (server-side, for git operations) - * - nsec/hex: Direct key signing (server-side, when key is available) + * - nsec/hex: Direct key signing (server-side ONLY, via environment variables) + * + * ⚠️ SECURITY WARNING: nsecKey should NEVER be sent from client requests. + * It should only be used server-side via environment variables (e.g., NOSTRGIT_SECRET_KEY). * * @param commitMessage - The commit message to sign * @param authorName - Author name * @param authorEmail - Author email * @param options - Signing options - * @param options.useNIP07 - Use NIP-07 browser extension (client-side only) + * @param options.useNIP07 - Use NIP-07 browser extension (client-side only, secure) * @param options.nip98Event - Use NIP-98 auth event as signature (server-side) - * @param options.nsecKey - Use direct nsec/hex key (server-side) + * @param options.nsecKey - Use direct nsec/hex key (server-side ONLY, via env vars - NOT for client requests) * @param options.timestamp - Optional timestamp (defaults to now) * @returns Signed commit message and signature event */ diff --git a/src/lib/services/git/file-manager.ts b/src/lib/services/git/file-manager.ts index 8a4c516..3e7a708 100644 --- a/src/lib/services/git/file-manager.ts +++ b/src/lib/services/git/file-manager.ts @@ -276,9 +276,9 @@ export class FileManager { /** * Write file and commit changes * @param signingOptions - Optional commit signing options: - * - useNIP07: Use NIP-07 browser extension (client-side only) + * - useNIP07: Use NIP-07 browser extension (client-side, secure - keys never leave browser) * - nip98Event: Use NIP-98 auth event as signature (server-side, for git operations) - * - nsecKey: Use direct nsec/hex key (server-side) + * - nsecKey: Use direct nsec/hex key (server-side ONLY, via environment variables - NOT for client requests) */ async writeFile( npub: string, diff --git a/src/routes/api/repos/[npub]/[repo]/file/+server.ts b/src/routes/api/repos/[npub]/[repo]/file/+server.ts index 292900f..5d01f61 100644 --- a/src/routes/api/repos/[npub]/[repo]/file/+server.ts +++ b/src/routes/api/repos/[npub]/[repo]/file/+server.ts @@ -121,6 +121,9 @@ export const POST: RequestHandler = async ({ params, url, request }: { params: { } // Prepare signing options + // NOTE: nsecKey is intentionally NOT supported from client requests for security reasons. + // Clients should use NIP-07 (browser extension) or NIP-98 (HTTP auth) instead. + // nsecKey is only for server-side use via environment variables. const signingOptions: { useNIP07?: boolean; nip98Event?: any; @@ -131,9 +134,9 @@ export const POST: RequestHandler = async ({ params, url, request }: { params: { signingOptions.useNIP07 = true; } else if (nip98Event) { signingOptions.nip98Event = nip98Event; - } else if (nsecKey) { - signingOptions.nsecKey = nsecKey; } + // Explicitly ignore nsecKey from client requests - it's a security risk + // Server-side signing should use NOSTRGIT_SECRET_KEY environment variable instead if (action === 'delete') { await fileManager.deleteFile(