Skip to content

Standardize behaviour of no_proxy environmental variable - #1223

Merged
fhammerl merged 8 commits into
actions:mainfrom
felixlut:partial-no-proxy
Feb 13, 2023
Merged

fhammerl merged 8 commits into
actions:mainfrom
felixlut:partial-no-proxy

Conversation

@felixlut

Copy link
Copy Markdown
Contributor

The behaviour of the no_proxy environmental variable is famously inconsistent, but this change should follow how it usually works (i.e., that no_proxy=domain.com matches its subdomains, such as some.domain.com).

Resolves #1172

@felixlut
felixlut requested a review from a team as a code owner October 25, 2022 20:07
Comment thread packages/http-client/src/proxy.ts Outdated
.map(x => x.trim().toUpperCase())
.filter(x => x)) {
if (upperReqHosts.some(x => x === upperNoProxyItem)) {
if (upperReqHosts.some(x => x.includes(upperNoProxyItem))) {

@aibaars aibaars Oct 27, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it would be safer to use endsWith instead of includes to avoid bad actors from bypassing the proxy. For example if we set no_proxy=mycompany.com then a domain like mycompany.com.evil.org should not bypass the proxy.

Suggested change
if (upperReqHosts.some(x => x.includes(upperNoProxyItem))) {
if (upperReqHosts.some(x => x.endsWith(upperNoProxyItem))) {

The above would still let domains like evilmycompany.com bypass the proxy. Perhaps a better formulation would be

Suggested change
if (upperReqHosts.some(x => x.includes(upperNoProxyItem))) {
if (upperReqHosts.some(x => x === upperNoProxyItem || x.endsWith('.' + upperNoProxyItem))) {

In addition we might want to strip off a leading . to ensure that no_proxy=example.com and no_proxy=.example.com are treated the same.

I think the following should work:

  // Compare request host against noproxy
  for (const upperNoProxyItem of noProxy
    .split(',')
    .map(x => x.trim().toUpperCase())
    .map(x => x.charAt(0) === '.' ? x.substr(1) : x)
    .filter(x => x)) {
    if (upperReqHosts.some(x => x === upperNoProxyItem || x.endsWith('.' + upperNoProxyItem))) {
      return true
    }
  }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

+1 for @aibaars suggestions too, ensWith + '.' sounds good
NIT: I'd consider a small refactoring of the block from line 54, it's becoming a bit dense with filters

@felixlut Could you add a test-case that covers the change in https://github.com/actions/toolkit/blob/main/packages/http-client/__tests__/proxy.test.ts ?

PS the PR validation currently fails due to some older packages, I'll take a look in a different PR

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I like your suggestions, and sure I can add a test-case. I'll try to find time over the weekend!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've implemented the suggested changes (in addition to some other suggestions from the article I posted above), as well as test-cases for each of them. Namely the following was added:

  • * matching all hosts
  • Strip leading dots (.domain.com --> domain.com)

@felixlut
felixlut requested review from aibaars and fhammerl and removed request for aibaars and fhammerl October 30, 2022 16:03
@felixlut felixlut changed the title Match no_proxy environmental variable to partial domains Standardize behaviour of no_proxy environmental variable Oct 30, 2022

@aibaars aibaars left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks good to me. @fhammerl , could you have a look at this?

@TingluoHuang

Copy link
Copy Markdown
Member

@fhammerl We also need to make the actions/runner follow the same rule if we take this change.

@fhammerl

fhammerl commented Nov 1, 2022

Copy link
Copy Markdown
Contributor

@TingluoHuang actions/runner for sure, can you think of any other services where we use noproxy?

@TingluoHuang

Copy link
Copy Markdown
Member

@fhammerl

@TingluoHuang actions/runner for sure, can you think of any other services where we use noproxy?

No

@aibaars

aibaars commented Nov 1, 2022

Copy link
Copy Markdown
Contributor

@fhammerl Could you update and merge #1226 ? I think that PR is meant to unblock the audit failure.

@felixlut

felixlut commented Nov 6, 2022

Copy link
Copy Markdown
Contributor Author

Haven't seen any activity in here for a couple of days. Just checking, there is nothing I should do now? This PR is just blocked until #1230 is merged?

1 similar comment
@felixlut

felixlut commented Nov 6, 2022

Copy link
Copy Markdown
Contributor Author

Haven't seen any activity in here for a couple of days. Just checking, there is nothing I should do now? This PR is just blocked until #1230 is merged?

@fhammerl fhammerl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great tests, thanks for the refactoring too.

LGTM

We're holding off with merging it for now as the 'audit' check is failing.
We'll fix that first on main, then merge this branch.

@felixlut

Copy link
Copy Markdown
Contributor Author

@fhammerl any update?

@fhammerl

Copy link
Copy Markdown
Contributor

We're migrating the project over to Node16, will merge this PR right after.

@SebastianLeitz

Copy link
Copy Markdown

We're migrating the project over to Node16, will merge this PR right after.

Could you please reference the PR for that migration so that people waiting for this can track the progress?

@vmjoseph

Copy link
Copy Markdown
Contributor

@felixlut Would you mind committing one more time so that our checks can re-run? Once those clear we can get this ready to merge.

@felixlut

felixlut commented Feb 4, 2023

Copy link
Copy Markdown
Contributor Author

@vmjoseph Any update on this?

@felixlut

felixlut commented Feb 7, 2023

Copy link
Copy Markdown
Contributor Author

Any update on this? @fhammerl @aibaars

@vmjoseph vmjoseph left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks like there's a linting error.

Comment thread packages/http-client/__tests__/proxy.test.ts Outdated
@fhammerl

fhammerl commented Feb 9, 2023

Copy link
Copy Markdown
Contributor

Hey @felixlut
This is a long lived PR now, thanks for sticking by!

We'd like to follow the no_proxy system we've established in actions/runner

The runner rules today:

  1. ✅ Support matching for subdomains (the meat of this PR)
  2. ❌ Do NOT strip leading period in no_proxy entry (aka no_proxy=.github.com should bypass proxy for sub.github.com, but not for vanilla github.com urls)
  3. ❌ Do NOT support * wildcard

This would bring the behaviour to that of wget's if I understand the table correctly.

With those changes, I can get this PR merged ASAP.

Let me know if that works for you

@felixlut

felixlut commented Feb 9, 2023

Copy link
Copy Markdown
Contributor Author

Sounds good to me, as you say, the subdomains was the reason i opened this! I can make the required rollbacks later tonight, or more likely tomorrow!

@felixlut
felixlut requested a review from fhammerl February 10, 2023 10:18
const bypass = pm.checkBypass(new URL('https://anything.whatsoever.com'))
expect(bypass).toBeFalsy()
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can We add one more test to chech a subdomain is supported when no_proxy has a leading dot?

  it('checkBypass returns true if host with subdomain in no_proxy defined with leading "."', () => {
    process.env['no_proxy'] = '.myserver.com'
    const bypass = pm.checkBypass(new URL('https://sub.myserver.com'))
    expect(bypass).toBeTruthy()
  })

@felixlut felixlut Feb 10, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ye sure!

Another question also, since you want the no_proxy to be the same as in the actions/runner, do you also want me to re-structure the code to be more similar to how they handle it (see ref)?
Obviously it's not the same language, but might be easier to keep consistency between them if they are implemented using the same logic, just with different languages.

Might be overkill, but I'm willing to do it if that makes it easier maintainable for you guys!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'd prefer to keep PRs for the functional changes and refactoring changes separate, but really appreciate you asking 👍

Also, here's a good set of unit tests from the runner code if needed

@felixlut felixlut Feb 12, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I''ve added the test you wrote, as well a new one for checking partial domains (such that no_proxy=myserver.com won't let evilmyserver.com through).

This required some extra logic

@felixlut
felixlut requested a review from vmjoseph February 13, 2023 10:13
@fhammerl
fhammerl merged commit d2b7d85 into actions:main Feb 13, 2023
@fhammerl

Copy link
Copy Markdown
Contributor

@felixlut Thanks again for this, I'll ping you as we publish it 👍

@felixlut
felixlut deleted the partial-no-proxy branch February 14, 2023 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

no_proxy matching agains parts of the host name is not supported

6 participants