W
File size: 3,302 Bytes
2b64d42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import http2 from 'http2';
import { redactProxyUrl, buildLanguageServerEnv, probeLanguageServerPort } from '../src/langserver.js';

async function withHttp2Server(handler, fn) {
  const server = http2.createServer();
  server.on('stream', handler);
  await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
  const port = server.address().port;
  try {
    return await fn(port);
  } finally {
    await new Promise(resolve => server.close(resolve));
  }
}

describe('redactProxyUrl', () => {
  it('redacts credentials from proxy URLs', () => {
    assert.equal(redactProxyUrl('http://user:secret@example.com:8080'), 'example.com:8080 (auth=true)');
  });

  it('shows host and port for unauthenticated proxies', () => {
    assert.equal(redactProxyUrl({ host: 'proxy.example.com', port: 1080 }), 'proxy.example.com:1080');
  });
});

describe('buildLanguageServerEnv', () => {
  it('keeps allowlisted vars and drops unrelated process env', () => {
    const env = buildLanguageServerEnv({
      HOME: '/home/dev',
      PATH: '/usr/bin',
      LANG: 'en_US.UTF-8',
      AWS_SECRET_ACCESS_KEY: 'leak-me',
      GITHUB_TOKEN: 'leak-me-too',
    });
    assert.equal(env.HOME, '/home/dev');
    assert.equal(env.PATH, '/usr/bin');
    assert.equal(env.LANG, 'en_US.UTF-8');
    assert.ok(!('AWS_SECRET_ACCESS_KEY' in env));
    assert.ok(!('GITHUB_TOKEN' in env));
  });

  it('applies proxy override across both HTTP and HTTPS forms', () => {
    const env = buildLanguageServerEnv(
      { HOME: '/home/dev', HTTP_PROXY: 'http://stale:8080' },
      { proxyUrl: 'http://fresh.example.com:9999' }
    );
    assert.equal(env.HTTP_PROXY, 'http://fresh.example.com:9999');
    assert.equal(env.HTTPS_PROXY, 'http://fresh.example.com:9999');
    assert.equal(env.http_proxy, 'http://fresh.example.com:9999');
    assert.equal(env.https_proxy, 'http://fresh.example.com:9999');
  });

  it('falls back to /root for HOME only when source has none', () => {
    const env = buildLanguageServerEnv({ PATH: '/usr/bin' });
    assert.equal(env.HOME, '/root');
  });

  it('preserves SSL trust env vars so hardened hosts still verify upstream', () => {
    const env = buildLanguageServerEnv({
      HOME: '/home/dev',
      SSL_CERT_FILE: '/etc/ssl/certs/ca-bundle.crt',
      NODE_EXTRA_CA_CERTS: '/etc/ssl/extra.pem',
    });
    assert.equal(env.SSL_CERT_FILE, '/etc/ssl/certs/ca-bundle.crt');
    assert.equal(env.NODE_EXTRA_CA_CERTS, '/etc/ssl/extra.pem');
  });
});

describe('probeLanguageServerPort', () => {
  it('accepts a port only when the response has a gRPC-like LS signature', async () => {
    await withHttp2Server((stream) => {
      stream.respond({ ':status': 405, 'content-type': 'application/grpc', 'grpc-status': '12' });
      stream.end();
    }, async (port) => {
      assert.equal(await probeLanguageServerPort(port), true);
    });
  });

  it('rejects unrelated HTTP/2 services on the default LS port shape', async () => {
    await withHttp2Server((stream) => {
      stream.respond({ ':status': 200, 'content-type': 'text/plain', server: 'not-ls' });
      stream.end('ok');
    }, async (port) => {
      assert.equal(await probeLanguageServerPort(port), false);
    });
  });
});