Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Process ACCESS_CONTROL_ALLOW_ORIGIN parameter #24225

Closed
wants to merge 0 commits into from
Closed

Process ACCESS_CONTROL_ALLOW_ORIGIN parameter #24225

wants to merge 0 commits into from

Conversation

aralex
Copy link

@aralex aralex commented Apr 20, 2023

  • read ACCESS_CONTROL_ALLOW_ORIGIN parameter from app.ini;
  • send Access-Control-Allow-Origin header for request with the same domain in ORIGIN header.

@silverwind
Copy link
Member

silverwind commented Apr 20, 2023

This looks insecure as it will echo the Origin header back, basically allowing all origins. We have a setting repo.ACCESS_CONTROL_ALLOW_ORIGIN which allows specifying a single origin header, which seems a slightly more secure approach.

Edit: I think I've misread. Retracting.

Generally I would recommend avoiding CORS where possible via reverse proxies.

@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Apr 20, 2023
@aralex aralex closed this Apr 20, 2023
@silverwind
Copy link
Member

Maybe describe a bit what problem you are trying to solve to help us understand why this is needed.

I'm no expert on CORS but in the few situations I've dealt with it, I found it easier to just set up reverse proxies to reduce to a single origin and not have CORS in first place, which has many negative effects, like pre-flight requests and such.

@aralex
Copy link
Author

aralex commented Apr 20, 2023

Generally I would recommend avoiding CORS where possible via reverse proxies.

I'm agree that CORS is more flexible and safe. But I didn's succeeded in activating CORS. I explored the sources. It seemed to Me that both CORS and repo.ACCESS_CONTROL_ALLOW_ORIGIN are not realized completly.

  1. There's no reading of ACCESS_CONTROL_ALLOW_ORIGIN from app.ini. There's no place of setting.Repository.AccessControlAllowOrigin assignment. It can not work at all.
  2. The only place of header Access-Control-Allow-Origin creation is here. But that function doesn't work while sending file via HTTP. Besides setting.Repository.AccessControlAllowOrigin didn't assigned a real domain. It will not work too. I see that CORS can not create header Access-Control-Allow-Origin too.

I decided to go the simple way: to add setting.Repository.AccessControlAllowOrigin reading from app.ini. And I added creation of the header to the code which creates other similar headers. This feature is not deprecated and it's useful. Admins may choose whether to use it or not.

I need this feature to read data files from Gitea in some web page. I'd like to load files from Gitea in JavaScript by HTTP request. It's the single domain (My web server). I can use repo.ACCESS_CONTROL_ALLOW_ORIGIN to specify it. In My case is simple and safe.

As you obviously understood, I realized sending of Access-Control-Allow-Origin header to the specified domain only. In case of simple CORS it has no negative effects. In more heavy cases admins should use CORS section of app.ini.

I think My PR is useful.

@wxiaoguang
Copy link
Contributor

I read the code briefly. At the moment, my thoughts are:

  1. The sec.MapTo(&Repository) below should read the setting.Repository.AccessControlAllowOrigin, if it doesn't, then there seems to be a bug for INI handling.
  2. There is similar logic in repo/http.go: httpBase(), so I would assume this PR is right.

Correct me if I am wrong.

@aralex
Copy link
Author

aralex commented Apr 21, 2023

Thank You, wxiaoguang!

I'd like to add some details...

  1. There is similar logic in repo/http.go: httpBase()...
  1. Yes. But repo/http.go: httpBase() doesn't take part in responsing to My requests. I'm trying to load files from Gitea in raw mode by URLs like this: https://raw.githubusercontent.com/go-gitea/gitea/main/LICENSE. So I had to dub the code.
  2. repo/http.go: httpBase() sends a header Access-Control-Allow-Origin: <my_domain> on requests from any domains (as I see). It isn't critical, but it's no good. It should be corrected, I think.

So what will be further? I'm novice in Gitea development and in development on Github too... :)

@wxiaoguang
Copy link
Contributor

Maybe let's keep this PR open? If you don't mind, I could try this PR on my side and maybe make some changes on it.

@aralex
Copy link
Author

aralex commented Apr 21, 2023

I'm agree! I really need this feature! Thank You!

I tested it by requests like this:

curl -s -I -H "Origin: https://mydomain.org" -u <user>:<password>  http://<repo_url>/raw/branch/master/<data_file>

I think specifying a value of ACCESS_CONTROL_ALLOW_ORIGIN without a protocol is better. Like this:

ACCESS_CONTROL_ALLOW_ORIGIN: mydomain.org

It allows both HTTP and HTTPS. But I prepose to add an example in app.example.ini because this detail is not obvious.

@aralex
Copy link
Author

aralex commented Apr 21, 2023

Maybe let's keep this PR open?..

Should I reopen this PR?

@aralex aralex reopened this Apr 21, 2023
@pull-request-size pull-request-size bot added the size/S Denotes a PR that changes 10-29 lines, ignoring generated files. label Apr 21, 2023
Comment on lines 392 to 399
if len(setting.Repository.AccessControlAllowOrigin) > 0 {
origin := strings.ToLower(ctx.Req.Header.Get("Origin"))
matcher := regexp.MustCompile(`http(s?)://`)
origin = matcher.ReplaceAllString(origin, "")
if origin == setting.Repository.AccessControlAllowOrigin {
header.Set("Access-Control-Allow-Origin", setting.Repository.AccessControlAllowOrigin)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

TBH, it doesn't look good to me.

Although I think we can respect the Repository.AccessControlAllowOrigin config, but this logic seems strange, it's different from how the AccessControlAllowOrigin is used in httpBase.

Copy link
Author

Choose a reason for hiding this comment

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

Although I think we can respect the Repository.AccessControlAllowOrigin config, but this logic seems strange, it's different from how the AccessControlAllowOrigin is used in httpBase.

You mean removing of a protocol prefix, don't You? I'm agree that logics should be the same. Do You think that this removing is excess?

Copy link
Contributor

@wxiaoguang wxiaoguang Apr 24, 2023

Choose a reason for hiding this comment

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

You mean removing of a protocol prefix

No, I mean this logic is different from how the AccessControlAllowOrigin is used in httpBase.

func httpBase(ctx *context.Context) (h *serviceHandler) {

I believe every single line should have its clear purpose and meaning. If httpBase is correct, then new code should follow it (extract the common part to a new function, to avoid duplicate code). If your new code is correct, then is old httpBase incorrect and should be fixed? If httpBase and your code are both correct, then what's the difference, why they should be written differently (which causes inconsistent behavior for the single config option) ?

Quote:

repo/http.go: httpBase() sends a header Access-Control-Allow-Origin: <my_domain> on requests from any domains (as I see).

I haven't looked into details, but there is a standard: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin

Copy link
Author

@aralex aralex Apr 24, 2023

Choose a reason for hiding this comment

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

I believe every single line should have its clear purpose and meaning. If httpBase is correct, then new code should follow it (extract the common part to a new function, to avoid duplicate code). If your new code is correct, then is old httpBase incorrect and should be fixed? If httpBase and your code are both correct, then what's the difference, why they should be written differently (which causes inconsistent behavior for the single config option)?

You're quite right! But I see the following facts:

  1. http.go implements Git Smart HTTP protocol. This module doesn't take part in responsing to usual requests from web browser or other simple clients.
  2. httpBase sends Access-Control-Allow-Origin to all clients. It's wrong. Someone should correct it by another PR. I'm better just to add TODO remark in http.go, I think.
  3. http.go and context.go really have some similar code. This fragment could be located in a separate function. But I think it is not useful right now. It should be a part of further refactoring. The changes could be much more wide. I'd like to minimize My changes now. But I can add one more TODO remark about this idea.

What do You think?

Copy link
Contributor

@wxiaoguang wxiaoguang Apr 24, 2023

Choose a reason for hiding this comment

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

At least, according to MDN: Access-Control-Allow-Origin: <origin> , https://developer.mozilla.org/en-US/docs/Glossary/Origin , the code origin = matcher.ReplaceAllString(origin, "") doesn't look right.


I would suggest to use a strict (and correct) CORS implementation.

Copy link
Contributor

@wxiaoguang wxiaoguang Apr 24, 2023

Choose a reason for hiding this comment

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

To fix the httpBase problem, I proposed #24303 , using a standard CORS package could be better.


after it gets merged, I think you can just add repo.CorsHandler() to m.Group("/raw", func() {, then the CORS should work.

Copy link
Author

Choose a reason for hiding this comment

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

OK, I'll wait for #24303

Copy link
Contributor

Choose a reason for hiding this comment

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

ps: usually the PR doesn't need to sync with main frequently (unless it is out-dated for long time, or there are conflicts). Just leave it there, as long as the PR is ready and approved, maintainers could help to sync & update & merge.

Copy link
Contributor

Choose a reason for hiding this comment

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

#24303 has been merged

@aralex aralex closed this May 12, 2023
@pull-request-size pull-request-size bot added size/XS Denotes a PR that changes 0-9 lines, ignoring generated files. and removed size/S Denotes a PR that changes 10-29 lines, ignoring generated files. labels May 12, 2023
@go-gitea go-gitea locked as resolved and limited conversation to collaborators Aug 10, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. size/XS Denotes a PR that changes 0-9 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants