Skip to content

Conversation

@dcoric
Copy link
Contributor

@dcoric dcoric commented Apr 28, 2025

This PR implements SSH support for Git operations, resolving #27. The implementation allows users to perform Git operations over SSH protocol, providing an alternative to HTTPS for repository access.

Changes

  1. Added SSH server implementation using ssh2 library
  2. Implemented two authentication methods:
    • Public key authentication
    • Password authentication
  3. Added SSH configuration options in config.schema.json
  4. Created comprehensive SSH documentation in docs/SSH.md
  5. Added SSH server tests in test/ssh/sshServer.test.js

Configuration

SSH support can be configured in the main configuration file:

{
  "ssh": {
    "enabled": true,
    "port": 2222,
    "hostKey": {
      "privateKeyPath": "./.ssh/host_key",
      "publicKeyPath": "./.ssh/host_key.pub"
    }
  }
}

Usage

Users can connect using standard Git SSH commands. The command format depends on the configured port:

  • If port is set to 22 (default SSH port):

    git clone git@your-proxy:username/repo.git
  • If using a custom port (e.g., 2222):

    git clone ssh://git@your-proxy:2222/username/repo.git

Testing

Added comprehensive tests for SSH functionality:

  • Server initialization
  • Authentication methods
  • Connection handling
  • Git protocol support

Documentation

Added detailed documentation in docs/SSH.md covering:

  • Configuration options
  • Authentication methods
  • Security features
  • Usage instructions
  • Troubleshooting guide

Future Improvements

  1. Move SSH configuration options (keep alive, timeouts, and other params) to config file
  2. Enhance actions for SSH functionality
  3. Increase test coverage
  4. Improved error reporting
  5. Additional security features

This implementation provides a secure and reliable way to perform Git operations over SSH, giving users more flexibility in how they interact with their repositories.

Below is a summary of the most important changes:

SSH Feature Implementation:

  • Added a new ssh configuration section in config.schema.json and proxy.config.json to enable SSH support, configure the port, and specify host key paths. ([[1]](https://github.com/finos/git-proxy/pull/987/files#diff-be1695b1e63a508d59982601f9e1fb7f58247deecb1e427adb77bcad758ae5e5R82-R111), [[2]](https://github.com/finos/git-proxy/pull/987/files#diff-c465aafa0fe603e2d28b017938f55e5ce3253aac7aa303efeabfc06a4ad52d5fR105-R112))
  • Created docs/SSH.md to provide comprehensive documentation for configuring, using, and troubleshooting the SSH feature. ([docs/SSH.mdR1-R165](https://github.com/finos/git-proxy/pull/987/files#diff-1d0301881738da7c699d7634669c5156c345a5094d6c012cfa7254cbdf15cbd2R1-R165))
  • Integrated SSH key management into the CLI, including commands to add and remove SSH keys (addSSHKey function and ssh-key command). ([[1]](https://github.com/finos/git-proxy/pull/987/files#diff-ee51eb1c2264303569f2a8fa9f5bb2de1b6b51eed24eed943d079f341f4139b0R310-R363), [[2]](https://github.com/finos/git-proxy/pull/987/files#diff-ee51eb1c2264303569f2a8fa9f5bb2de1b6b51eed24eed943d079f341f4139b0R494-R524), [[3]](https://github.com/finos/git-proxy/pull/987/files#diff-c3c551630c7afb35431840ab36bd8cc771deb1fa385b73804eaf8da4b8db7e0cR1-R122))

Database Enhancements:

  • Updated the user schema to include SSH public keys and added functions for managing SSH keys (addPublicKey, removePublicKey, findUserBySSHKey). ([[1]](https://github.com/finos/git-proxy/pull/987/files#diff-d90c8ba033b20fb64a27fb6f16a94afa5ebc2f25bb7af6ec42cd260dcbf46710R43-R46), [[2]](https://github.com/finos/git-proxy/pull/987/files#diff-d90c8ba033b20fb64a27fb6f16a94afa5ebc2f25bb7af6ec42cd260dcbf46710R98-R155), [[3]](https://github.com/finos/git-proxy/pull/987/files#diff-c7d2c320d1f7fc0aad36b8bf616a7289ca4dcf00e6e057ba8a1d354fb25b74c0R84-R86))

Configuration and Code Updates:

  • Introduced new methods in src/config/index.ts to retrieve SSH-related settings (getSSHConfig, getSSHProxyUrl). ([[1]](https://github.com/finos/git-proxy/pull/987/files#diff-198a1431d7c5e26ea78bc6e54b34b54e6f8ab342dd48ea11013877e8466a87c5R33), [[2]](https://github.com/finos/git-proxy/pull/987/files#diff-198a1431d7c5e26ea78bc6e54b34b54e6f8ab342dd48ea11013877e8466a87c5R48-R58))
  • Updated package.json to include the ssh2 library and its TypeScript types for SSH server implementation. ([[1]](https://github.com/finos/git-proxy/pull/987/files#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519R75), [[2]](https://github.com/finos/git-proxy/pull/987/files#diff-7ae45ad102eab3b6d7e7896acd08c427a9b25b346470d7bc6507b6481575d519R90))

Documentation Enhancements:

  • Updated README.md to include a link to the new SSH documentation. ([README.mdR88-R95](https://github.com/finos/git-proxy/pull/987/files#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R88-R95))

These changes collectively enable the SSH feature, providing an alternative to HTTPS for secure Git operations while enhancing user control and security.

@netlify
Copy link

netlify bot commented Apr 28, 2025

Deploy Preview for endearing-brigadeiros-63f9d0 canceled.

Name Link
🔨 Latest commit 39c0ee7
🔍 Latest deploy log https://app.netlify.com/projects/endearing-brigadeiros-63f9d0/deploys/691b288d16fe310008934a1f

@dcoric
Copy link
Contributor Author

dcoric commented May 9, 2025

@JamieSlome @coopernetes, please take a look when you get a chance

@dcoric dcoric force-pushed the denis-coric/ssh-flow branch from 399bf6c to f514691 Compare May 16, 2025 11:04
@fabiovincenzi fabiovincenzi mentioned this pull request May 28, 2025
Copy link
Contributor

@jescalada jescalada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a preliminary review of the code changes. I'll run it and test more thoroughly afterwards!


class SSHServer {
constructor() {
// TODO: Server config could go to config file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just bringing attention to this TODO

Copy link
Contributor

@jescalada jescalada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review (Part 2): I managed to confirm that the general flow works as expected, but I'm wondering how to trigger the proxy action chain through SSH.

Other than that, improving user-facing errors and some documentation improvements would be great for UX. 🙂

// TODO: Server config could go to config file
this.server = new ssh2.Server(
{
hostKeys: [require('fs').readFileSync(config.getSSHConfig().hostKey.privateKeyPath)],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another issue I found, is that the path doesn't seem to resolve when using ~. It might be nice to be able to set the config to ~/.ssh/host_key so that it resolves to the home directory. Not a huge deal though! 👍🏼

findUser(username)
.then((user) => {
if (!user) {
reject(new Error('User not found'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line gets successfully triggered when the user isn't found. However, the CLI just prints this out instead of bubbling up the User not found error message (which is much more descriptive):

Error: SSH key: 'Request failed with status code 500'

});

proxyGitSsh.on('error', (err) => {
console.error('[SSH] Remote SSH error with proxy key:', err);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upon entering an invalid key, I trigger the following error on line 638:

git-proxy backend

[0] [GitHub SSH Debug] Handshake completed
[0] [GitHub SSH Debug] Outbound: Sending SERVICE_REQUEST (ssh-userauth)
[0] [GitHub SSH Debug] Inbound: Received EXT_INFO
[0] [GitHub SSH Debug] Inbound: Received SERVICE_ACCEPT (ssh-userauth)
[0] [GitHub SSH Debug] Outbound: Sending USERAUTH_REQUEST (none)
[0] [GitHub SSH Debug] Inbound: Received USERAUTH_FAILURE (publickey)
[0] [GitHub SSH Debug] Client: none auth failed
[0] [GitHub SSH Debug] Outbound: Sending USERAUTH_REQUEST (publickey -- check)
[0] [GitHub SSH Debug] Inbound: Received USERAUTH_FAILURE (publickey)
[0] [GitHub SSH Debug] Client: publickey (rsa-sha2-256) auth failed
[0] [GitHub SSH Debug] Client: publickey auth failed
[0] [SSH] Remote SSH error with proxy key: Error: All configured authentication methods failed
[0]     at doNextAuth (/home/juan/Desktop/Juan/Projects/git-proxy/node_modules/ssh2/lib/client.js:863:21)
[0]     at tryNextAuth (/home/juan/Desktop/Juan/Projects/git-proxy/node_modules/ssh2/lib/client.js:1080:7)
[0]     at USERAUTH_FAILURE (/home/juan/Desktop/Juan/Projects/git-proxy/node_modules/ssh2/lib/client.js:428:11)
[0]     at 51 (/home/juan/Desktop/Juan/Projects/git-proxy/node_modules/ssh2/lib/protocol/handlers.misc.js:408:16)
[0]     at Protocol.onPayload (/home/juan/Desktop/Juan/Projects/git-proxy/node_modules/ssh2/lib/protocol/Protocol.js:2059:10)
[0]     at AESGCMDecipherBinding.decrypt (/home/juan/Desktop/Juan/Projects/git-proxy/node_modules/ssh2/lib/protocol/crypto.js:1086:26)
[0]     at Protocol.parsePacket [as _parse] (/home/juan/Desktop/Juan/Projects/git-proxy/node_modules/ssh2/lib/protocol/Protocol.js:2028:25)
[0]     at Protocol.parse (/home/juan/Desktop/Juan/Projects/git-proxy/node_modules/ssh2/lib/protocol/Protocol.js:313:16)
[0]     at Socket.<anonymous> (/home/juan/Desktop/Juan/Projects/git-proxy/node_modules/ssh2/lib/client.js:773:21)
[0]     at Socket.emit (node:events:524:28) {
[0]   level: 'client-authentication'
[0] }
[0] [SSH Debug] [518855.983928741] Outbound: Sending CHANNEL_DATA (r:0, 51)
[0] [SSH Debug] [518855.983928741] Outbound: Sending CHANNEL_EOF (r:0)
[0] [SSH Debug] [518855.983928741] Outbound: Sending CHANNEL_CLOSE (r:0)
[0] [GitHub SSH Debug] Outbound: Sending DISCONNECT (11)
[0] [SSH Debug] [518855.983928741] Inbound: CHANNEL_CLOSE (r:0)
[0] [SSH Debug] [518855.983928741] Inbound: Received DISCONNECT (11, "disconnected by user")
[0] [SSH Debug] [518855.983928741] Socket ended
[0] [SSH] Client disconnected
[0] [SSH] Client disconnected
[0] [SSH Debug] [518855.983928741] Socket closed
[0] [SSH] Client connection closed
[0] [GitHub SSH Debug] Socket ended
[0] [GitHub SSH Debug] Socket closed

However, the user facing CLI gives an unrelated error:

User-facing CLI

$ git clone ssh://git@localhost:2222/jescalada/git-proxy-experiments.git
Cloning into 'git-proxy-experiments'...
fatal: protocol error: bad line length character: Erro

Would be great if we could get a more descriptive error for this common scenario (bad key).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my case, this was because of my GitHub authentication not set up correctly.


// Execute the Git command on remote
remoteGitSsh.exec(
command,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be missing something in my configuration, but when I execute git push, the git-proxy action chain isn't triggered:

$ git push ssh://git@localhost:2222/jescalada/git-proxy-experiments.git
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 331 bytes | 331.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To ssh://localhost:2222/jescalada/git-proxy-experiments.git
   fa06cb5..ea81914  main -> main

It directly updated my upstream repo instead of going through the proxy's approval process.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That said, after setting up the public key in the GitHub SSH page, the SSH works great! The SSH key setup is worth explaining in detail in the ssh.md guide.

Copy link
Contributor

@jescalada jescalada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review (Part 3): Just took a look at the unit tests. It would be great to cover some more edge cases and get more granular testing by passing error messages through the ctx.reject (if possible).

If you'd like, I can help out with the documentation refactor and unit test coverage 🙂

accept();
} else {
console.log('[SSH] Rejecting unknown global request:', info.type);
reject();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better if we sent the error string as a reject argument? Might be better for more granular testing.

expect(mockClient.on.calledWith('authentication')).to.be.true;
});

describe('authentication', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be great to add extra tests for authentication failure cases. These are a few passing sample tests I wrote:

Suggested change
describe('authentication', () => {
describe('authentication', () => {
it('should reject invalid public keys', async () => {
const mockCtx = {
method: 'publickey',
key: {
algo: 'ssh-rsa',
data: Buffer.from('invalid-key-data'),
comment: 'invalid-key',
},
accept: sinon.stub(),
reject: sinon.stub(),
};
mockDb.findUserBySSHKey.resolves(null);
server.handleClient(mockClient);
const authHandler = mockClient.on.withArgs('authentication').firstCall.args[1];
await authHandler(mockCtx);
expect(mockCtx.reject.calledOnce).to.be.true;
expect(mockClient.username).to.be.null;
expect(mockClient.userPrivateKey).to.be.null;
});
it('should reject invalid passwords', async () => {
const mockCtx = {
method: 'password',
username: 'test-user',
password: 'invalid-password',
accept: sinon.stub(),
reject: sinon.stub(),
};
mockDb.findUser.resolves({
username: 'test-user',
password: '$2a$10$mockHash',
});
const bcrypt = require('bcryptjs');
sinon.stub(bcrypt, 'compare').resolves(false);
server.handleClient(mockClient);
const authHandler = mockClient.on.withArgs('authentication').firstCall.args[1];
await authHandler(mockCtx);
expect(mockDb.findUser.calledWith('test-user')).to.be.true;
expect(bcrypt.compare.calledWith('invalid-password', '$2a$10$mockHash')).to.be.true;
expect(mockCtx.reject.calledOnce).to.be.true;
});
it('should handle a missing private key', async () => {
const mockCtx = {
method: 'publickey',
key: null,
accept: sinon.stub(),
reject: sinon.stub(),
};
mockDb.findUserBySSHKey.resolves({ username: 'test-user' });
server.handleClient(mockClient);
const authHandler = mockClient.on.withArgs('authentication').firstCall.args[1];
await authHandler(mockCtx);
expect(mockCtx.reject.calledOnce).to.be.true;
expect(mockClient.username).to.be.null;
expect(mockClient.userPrivateKey).to.be.null;
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra authentication test case ideas:

  • Malformed SSH keys
    • Currently, malformed keys go through the findUserBySSHKey function which logs [SSH] No user found with this SSH key instead of throwing error
  • Invalid auth method (neither publickey nor password)
  • Nonexistent user

command: "git-upload-pack 'test/repo'",
};

mockChain.executeChain.resolves({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be great to include some cases with error: true/blocked: true:

Sample

I wrote a sample test for this, but it seems to be failing:

    it('should handle git-upload-pack command with error in chain', async () => {
      const mockInfo = {
        command: "git-upload-pack 'test/repo'",
      };
      
      mockChain.executeChain.resolves({
        error: true,
        blocked: true,
      });

      server.handleSession(mockAccept, mockReject);
      const execHandler = mockSession.on.withArgs('exec').firstCall.args[1];
      await execHandler(mockAccept, mockReject, mockInfo);

      expect(mockChain.executeChain.calledWith({
        method: 'GET',
        originalUrl: " 'test/repo",
        isSSH: true,
      })).to.be.true;

      expect(mockStream.end.calledOnce).to.be.true;
      expect(mockStream.exit.calledOnce).to.be.true;
      expect(mockStream.exit.calledWith(1)).to.be.true;
    });

Error:

  2) SSHServer
       handleSession
         should handle git-upload-pack command with invalid repo:
     TypeError: stream.write is not a function
      at SSHServer.<anonymous> (src/proxy/ssh/server.js:664:18)
      at Generator.next (<anonymous>)
      at fulfilled (src/proxy/ssh/server.js:5:58)
      at processTicksAndRejections (node:internal/process/task_queues:105:5)


it('should handle git-receive-pack command', async () => {
const mockInfo = {
command: "git-receive-pack 'test/repo'",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other possible test cases for handleSession:

  • Invalid repo handling
    • Currently gets stuck on [GitHub SSH Debug] Client: Trying github.com on port 22 ... without throwing error. executeChain doesn't seem to get called
  • Edge case tests:
    • Empty repository name, whitespace inputs
    • SSH injection (example: command: "git-upload-pack 'repo'; rm -rf /; #",)

- Implement complete SSH server with public key and password authentication
- Add SSH key management to user database (both File and MongoDB)
- Create SSH CLI tools for key management
- Add SSH configuration schema and TypeScript types
- Integrate SSH server with main proxy lifecycle
- Add REST endpoints for SSH key CRUD operations
- Include comprehensive test suite and documentation
- Support Git operations over SSH with full proxy chain integration
- Convert SSH server (src/proxy/ssh/server.js -> server.ts)
- Convert SSH CLI tool (src/cli/ssh-key.js -> ssh-key.ts)
- Add proper TypeScript types and interfaces
- Install @types/ssh2 for SSH2 library types
- Fix TypeScript compilation errors with type assertions
- Update imports to use TypeScript files
- Remove @ts-expect-error comment as no longer needed
- Add email and gitAccount fields to SSHUser and AuthenticatedUser interfaces
- Improve client connection handling by logging client IP and user details
- Refactor handleClient method to accept client connection info
- Enhance error handling and logging for better debugging
- Update tests to reflect changes in client handling and authentication
- Update keepalive settings to recommended intervals for better connection stability
- Implement cleanup of keepalive timers on client disconnects
- Modify error handling to allow client recovery instead of closing connections
- Improve logging for debugging client key usage and connection errors
- Update tests to reflect changes in keepalive behavior and error handling
@dcoric dcoric force-pushed the denis-coric/ssh-flow branch from 6667d15 to 2fd1703 Compare September 17, 2025 11:06
- Introduce SSH key management to securely store and reuse user SSH keys during the approval process
- Add SSHKeyManager and SSHAgent classes for key encryption, storage, and expiration management
- Implement captureSSHKey processor to capture and store SSH key information during push actions
- Enhance Action and request handling to support SSH-specific user data
- Update push action chain to include SSH key capture
- Extend PushData model to include encrypted SSH key and expiration details
- Provide configuration options for SSH key encryption and management
 - Introduce .nvmrc file to specify Node.js version (v20)
- Add SSH interface definitions for configuration of SSH proxy server and host keys
- Update config generation to include SSH settings
- Modify SSH server command handling to improve error reporting and session
  management
- Enhance tests for SSH key capture and server functionality, ensuring robust
  error handling and edge case coverage
@dcoric dcoric force-pushed the denis-coric/ssh-flow branch from 5d680a6 to 91b58eb Compare September 19, 2025 14:22
- Add .claude/ to .gitignore to prevent tracking of Claude-related files
…handling in SSH server

- Update SSH configuration merging to guarantee 'enabled' is always a boolean value.
- Enhance error handling in SSH server to provide clearer error messages when chain execution fails.
@codecov
Copy link

codecov bot commented Nov 9, 2025

Codecov Report

❌ Patch coverage is 62.93260% with 407 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.90%. Comparing base (df6406b) to head (631e635).

Files with missing lines Patch % Lines
src/proxy/ssh/server.ts 82.80% 57 Missing and 36 partials ⚠️
src/service/SSHKeyForwardingService.ts 11.49% 77 Missing ⚠️
src/security/SSHAgent.ts 21.12% 56 Missing ⚠️
src/proxy/processors/push-action/pullRemote.ts 46.75% 32 Missing and 9 partials ⚠️
src/security/SSHKeyManager.ts 41.50% 30 Missing and 1 partial ⚠️
src/service/routes/users.ts 46.42% 28 Missing and 2 partials ⚠️
src/service/urls.ts 47.50% 17 Missing and 4 partials ⚠️
src/config/index.ts 42.85% 11 Missing and 5 partials ⚠️
src/db/mongo/users.ts 22.22% 14 Missing ⚠️
src/db/file/users.ts 77.50% 9 Missing ⚠️
... and 4 more

❌ Your patch check has failed because the patch coverage (62.93%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.
❌ Your project check has failed because the head coverage (77.90%) is below the target coverage (80.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #987      +/-   ##
==========================================
- Coverage   83.36%   77.90%   -5.46%     
==========================================
  Files          70       77       +7     
  Lines        3005     4082    +1077     
  Branches      499      704     +205     
==========================================
+ Hits         2505     3180     +675     
- Misses        397      738     +341     
- Partials      103      164      +61     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

// In a real-world scenario, you would need to:
// 1. Use SSH agent forwarding to access the user's private key
// 2. Store the key securely with proper encryption
// 3. Set up automatic cleanup
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dcoric Double-check if modifying/improving implementation is required

Copy link
Contributor

@jescalada jescalada Nov 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double-check if this needs to be removed (autogenerated) or if required for test fixture. Also other SSH key sample files

console.log(`User '${username}' created successfully`);
console.log(`SSH key added successfully for user ${username}`);
} catch (error: any) {
let errorMessage = `Error: Create User: '${error.message}'`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: Might be worth refactoring the error handling here to use promises and possibly reusing the endpoint error message instead of repeating it here.

const axiosError = error as ErrorWithResponse;
console.error('Full error:', error);

if (axiosError.response) {
Copy link
Contributor

@jescalada jescalada Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for self: Error handling here should be improved by leveraging the status codes (same as before) and also using promises/.then in case we need to do multiple requests.

message: string;
}

async function addSSHKey(username: string, keyPath: string): Promise<void> {
Copy link
Contributor

@jescalada jescalada Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noticed that there's duplicate logic for addSSHKey and removeSSHKey - the same API calls are happening in git-proxy-cli/index.ts. We should figure out if we want to keep the standalone SSH key manager script or have it all included in the CLI.

fabiovincenzi added a commit to fabiovincenzi/git-proxy that referenced this pull request Nov 12, 2025
@jescalada jescalada force-pushed the denis-coric/ssh-flow branch from ee4de06 to 7a6b7a7 Compare November 13, 2025 09:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Migration] Convert ssh/server to TS Security: Api endpoints should not expose user credentials

4 participants