Skip to content

Commit a52796f

Browse files
kibanamachineshaharglcursoragent
authored
[9.4] [Actions] Fix HTTP connector TLS options through proxies (#269898) (#270104)
# Backport This will backport the following commits from `main` to `9.4`: - [[Actions] Fix HTTP connector TLS options through proxies (#269898)](#269898) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Shahar Glazner","email":"shaharglazner@gmail.com"},"sourceCommit":{"committedDate":"2026-05-20T08:50:22Z","message":"[Actions] Fix HTTP connector TLS options through proxies (#269898)\n\n## Summary\n- For HTTPS requests through an HTTP proxy, forward target TLS options\nto the CONNECT-upgraded request created by `HttpsProxyAgent`.\n- Ensures connector `verificationMode: none` and per-request SSL\noverrides like `fetcher.skip_ssl_verification` are honored when the\nproxy performs TLS inspection.\n- Adds a regression test covering target SSL overrides through the proxy\nagent callback.\n\n## Test plan\n- `node scripts/jest\nsrc/platform/packages/shared/kbn-actions-utils/utils/get_custom_agents.test.ts`\n- `node scripts/check_changes.ts`\n- Manually reproduced with local mitmproxy before the fix and verified\n`_execute` succeeds after the fix.\n\n## References\nCloses elastic/security-team#17454\nCloses https://github.com/elastic/kibana/issues/196602\n\nMade with [Cursor](https://cursor.com)\n\nCo-authored-by: Cursor <cursoragent@cursor.com>","sha":"4783bfafd2d0e25d59d5f2a835ef5f84defd1333","branchLabelMapping":{"^v9.5.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:fix","backport:all-open","Team:One Workflow","v9.5.0"],"title":"[Actions] Fix HTTP connector TLS options through proxies","number":269898,"url":"https://github.com/elastic/kibana/pull/269898","mergeCommit":{"message":"[Actions] Fix HTTP connector TLS options through proxies (#269898)\n\n## Summary\n- For HTTPS requests through an HTTP proxy, forward target TLS options\nto the CONNECT-upgraded request created by `HttpsProxyAgent`.\n- Ensures connector `verificationMode: none` and per-request SSL\noverrides like `fetcher.skip_ssl_verification` are honored when the\nproxy performs TLS inspection.\n- Adds a regression test covering target SSL overrides through the proxy\nagent callback.\n\n## Test plan\n- `node scripts/jest\nsrc/platform/packages/shared/kbn-actions-utils/utils/get_custom_agents.test.ts`\n- `node scripts/check_changes.ts`\n- Manually reproduced with local mitmproxy before the fix and verified\n`_execute` succeeds after the fix.\n\n## References\nCloses elastic/security-team#17454\nCloses https://github.com/elastic/kibana/issues/196602\n\nMade with [Cursor](https://cursor.com)\n\nCo-authored-by: Cursor <cursoragent@cursor.com>","sha":"4783bfafd2d0e25d59d5f2a835ef5f84defd1333"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.5.0","branchLabelMappingKey":"^v9.5.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/269898","number":269898,"mergeCommit":{"message":"[Actions] Fix HTTP connector TLS options through proxies (#269898)\n\n## Summary\n- For HTTPS requests through an HTTP proxy, forward target TLS options\nto the CONNECT-upgraded request created by `HttpsProxyAgent`.\n- Ensures connector `verificationMode: none` and per-request SSL\noverrides like `fetcher.skip_ssl_verification` are honored when the\nproxy performs TLS inspection.\n- Adds a regression test covering target SSL overrides through the proxy\nagent callback.\n\n## Test plan\n- `node scripts/jest\nsrc/platform/packages/shared/kbn-actions-utils/utils/get_custom_agents.test.ts`\n- `node scripts/check_changes.ts`\n- Manually reproduced with local mitmproxy before the fix and verified\n`_execute` succeeds after the fix.\n\n## References\nCloses elastic/security-team#17454\nCloses https://github.com/elastic/kibana/issues/196602\n\nMade with [Cursor](https://cursor.com)\n\nCo-authored-by: Cursor <cursoragent@cursor.com>","sha":"4783bfafd2d0e25d59d5f2a835ef5f84defd1333"}}]}] BACKPORT--> Co-authored-by: Shahar Glazner <shaharglazner@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 412dca0 commit a52796f

2 files changed

Lines changed: 78 additions & 12 deletions

File tree

src/platform/packages/shared/kbn-actions-utils/utils/get_custom_agents.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,50 @@ describe('getCustomAgents', () => {
5252
expect(httpsAgent instanceof HttpsProxyAgent).toBeTruthy();
5353
});
5454

55+
test('passes target SSL overrides to the CONNECT-upgraded TLS request', async () => {
56+
const callbackSpy = jest
57+
.spyOn(HttpsProxyAgent.prototype, 'callback')
58+
.mockResolvedValue({} as Awaited<ReturnType<HttpsProxyAgent['callback']>>);
59+
const proxySettings = {
60+
proxyUrl: 'http://someproxyhost',
61+
proxySSLSettings: {
62+
verificationMode: 'full',
63+
},
64+
proxyBypassHosts: undefined,
65+
proxyOnlyHosts: undefined,
66+
} as ProxySettings;
67+
68+
const { httpsAgent } = getCustomAgents({
69+
logger,
70+
proxySettings,
71+
sslOverrides: {
72+
verificationMode: 'none',
73+
},
74+
sslSettings: defaultSSLSettings,
75+
url: targetUrl,
76+
});
77+
78+
try {
79+
await (httpsAgent as unknown as HttpsProxyAgent).callback(
80+
{} as Parameters<HttpsProxyAgent['callback']>[0],
81+
{
82+
host: targetHost,
83+
port: 443,
84+
secureEndpoint: true,
85+
} as Parameters<HttpsProxyAgent['callback']>[1]
86+
);
87+
88+
expect(callbackSpy).toHaveBeenCalledWith(
89+
expect.anything(),
90+
expect.objectContaining({
91+
rejectUnauthorized: false,
92+
})
93+
);
94+
} finally {
95+
callbackSpy.mockRestore();
96+
}
97+
});
98+
5599
test('return default agents for invalid proxy URL', () => {
56100
const proxySettings = {
57101
proxyUrl: ':nope: not a valid URL',

src/platform/packages/shared/kbn-actions-utils/utils/get_custom_agents.ts

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@ interface GetCustomAgentsOpts {
3333
url: string;
3434
}
3535

36+
class TargetSslHttpsProxyAgent extends HttpsProxyAgent {
37+
constructor(
38+
proxyOptions: ConstructorParameters<typeof HttpsProxyAgent>[0],
39+
private readonly targetSSLOptions: AgentOptions
40+
) {
41+
super(proxyOptions);
42+
}
43+
44+
callback(
45+
req: Parameters<HttpsProxyAgent['callback']>[0],
46+
opts: Parameters<HttpsProxyAgent['callback']>[1]
47+
) {
48+
// HttpsProxyAgent constructor options configure the proxy connection. Target TLS
49+
// options must be merged into the CONNECT-upgraded request options instead.
50+
return super.callback(req, { ...opts, ...this.targetSSLOptions });
51+
}
52+
}
53+
3654
export function getCustomAgents(opts: GetCustomAgentsOpts): GetCustomAgentsResponse {
3755
const {
3856
customHostSettings,
@@ -137,22 +155,26 @@ export function getCustomAgents(opts: GetCustomAgentsOpts): GetCustomAgentsRespo
137155
// We will though, copy over the calculated ssl options from above, into
138156
// the https agent.
139157
const httpAgent = new HttpProxyAgent(proxySettings.proxyUrl) as unknown as HttpAgent;
140-
const httpsAgent = new HttpsProxyAgent({
141-
host: proxyUrl.hostname,
142-
port: Number(proxyUrl.port),
143-
protocol: proxyUrl.protocol,
144-
headers: proxySettings.proxyHeaders,
145-
...(proxyUrl.username &&
146-
proxyUrl.password && { auth: `${proxyUrl.username}:${proxyUrl.password}` }),
147-
// do not fail on invalid certs if value is false
148-
...proxyNodeSSLOptions,
149-
}) as unknown as HttpsAgent;
158+
const targetSSLOptions = agentOptions ?? agentSSLOptions;
159+
const httpsAgent = new TargetSslHttpsProxyAgent(
160+
{
161+
host: proxyUrl.hostname,
162+
port: Number(proxyUrl.port),
163+
protocol: proxyUrl.protocol,
164+
headers: proxySettings.proxyHeaders,
165+
...(proxyUrl.username &&
166+
proxyUrl.password && { auth: `${proxyUrl.username}:${proxyUrl.password}` }),
167+
// do not fail on invalid certs if value is false
168+
...proxyNodeSSLOptions,
169+
},
170+
targetSSLOptions
171+
) as unknown as HttpsAgent;
150172
// vsCode wasn't convinced HttpsProxyAgent is an https.Agent, so we convinced it
151173

152-
if (agentOptions) {
174+
if (targetSSLOptions) {
153175
httpsAgent.options = {
154176
...httpsAgent.options,
155-
...agentOptions,
177+
...targetSSLOptions,
156178
};
157179
}
158180

0 commit comments

Comments
 (0)