Skip to content

Commit f88212b

Browse files
jamietannaClaude Sonnet 5
andauthored
fix(proxy): sanitise password components in HTTP_PROXY variable(s) in logs (#45117)
If a proxy URL appears to have a password component in it, we should make sure that this is sanitised. Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
1 parent 54384ff commit f88212b

2 files changed

Lines changed: 45 additions & 0 deletions

File tree

lib/proxy.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { bootstrap, hasProxy } from './proxy.ts';
2+
import * as sanitize from './util/sanitize.ts';
3+
4+
const addSecretForSanitizing = vi.spyOn(sanitize, 'addSecretForSanitizing');
25

36
describe('proxy', () => {
47
const httpProxy = 'http://example.org/http-proxy';
@@ -57,4 +60,34 @@ describe('proxy', () => {
5760
bootstrap();
5861
expect(hasProxy()).toBeFalse();
5962
});
63+
64+
it('sanitizes password from HTTP_PROXY credentials', () => {
65+
process.env.HTTP_PROXY = 'http://user:s3cr3t@example.org';
66+
bootstrap();
67+
expect(addSecretForSanitizing).toHaveBeenCalledWith('s3cr3t', 'global');
68+
});
69+
70+
it('sanitizes password from HTTPS_PROXY credentials', () => {
71+
process.env.HTTPS_PROXY = 'http://user:s3cr3t@example.org';
72+
bootstrap();
73+
expect(addSecretForSanitizing).toHaveBeenCalledWith('s3cr3t', 'global');
74+
});
75+
76+
it('does not sanitize username-only proxy credentials', () => {
77+
process.env.HTTP_PROXY = 'http://user@example.org';
78+
bootstrap();
79+
expect(addSecretForSanitizing).not.toHaveBeenCalled();
80+
});
81+
82+
it('sanitizes password-only proxy credentials', () => {
83+
process.env.HTTP_PROXY = 'http://:s3cr3t@example.org';
84+
bootstrap();
85+
expect(addSecretForSanitizing).toHaveBeenCalledWith('s3cr3t', 'global');
86+
});
87+
88+
it('does not sanitize when proxy has no credentials', () => {
89+
process.env.HTTP_PROXY = httpProxy;
90+
bootstrap();
91+
expect(addSecretForSanitizing).not.toHaveBeenCalled();
92+
});
6093
});

lib/proxy.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
import { isNonEmptyString } from '@sindresorhus/is';
22
import { createGlobalProxyAgent } from 'global-agent';
33
import { logger } from './logger/index.ts';
4+
import { addSecretForSanitizing } from './util/sanitize.ts';
5+
import { parseUrl } from './util/url.ts';
46

57
const envVars = ['HTTP_PROXY', 'HTTPS_PROXY', 'NO_PROXY'];
8+
const proxyEnvVarsWithCredentials = ['HTTP_PROXY', 'HTTPS_PROXY'];
69

710
let agent = false;
811

12+
function sanitizeProxyCredentials(envVar: string): void {
13+
const uri = parseUrl(process.env[envVar]);
14+
if (uri?.password) {
15+
addSecretForSanitizing(uri.password, 'global');
16+
}
17+
}
18+
919
export function bootstrap(): void {
1020
envVars.forEach((envVar) => {
1121
/* v8 ignore next -- env is case-insensitive on windows */
@@ -22,6 +32,8 @@ export function bootstrap(): void {
2232
}
2333
});
2434

35+
proxyEnvVarsWithCredentials.forEach(sanitizeProxyCredentials);
36+
2537
if (
2638
isNonEmptyString(process.env.HTTP_PROXY) ||
2739
isNonEmptyString(process.env.HTTPS_PROXY)

0 commit comments

Comments
 (0)