Skip to content

fix: Prevent an App from setting a public address that conflicts with a Teleport Proxy public address 👮🏾#58475

Merged
cthach merged 20 commits intomasterfrom
cthach/restrict-public-addr
Sep 4, 2025
Merged

fix: Prevent an App from setting a public address that conflicts with a Teleport Proxy public address 👮🏾#58475
cthach merged 20 commits intomasterfrom
cthach/restrict-public-addr

Conversation

@cthach
Copy link
Copy Markdown
Contributor

@cthach cthach commented Aug 28, 2025

What?

Fixes https://github.com/gravitational/teleport-private/issues/2104.

Changelog: Prevents an application from being registered if its public address matches a Teleport cluster address.

Why?

If an application's public address conflicts with any public addresses of the Teleport cluster, it potentially enables a malicious attacker to perform session hijacking through the misconfigured application.

How?

Adds application public address validation for applications added through Teleport's config and through dynamic means.

It also updates the routing logic to prevent users of existing Teleport instances from routing to any misconfigured applications that existed before this change.

Demo

CLI

When attempting to set an application's public_addr to one that conflicts with the Teleport cluster's proxy address, an error is returned when starting Teleport.

Screenshot 2025-09-04 at 1 02 03 PM

Web UI

If a misconfigured application existed prior to these changes, the Web UI will prevent routing to that misconfigured app and will display an error message with next steps.

bad-app-ui-conflict

Comment thread lib/service/servicecfg/app.go Outdated
@cthach cthach self-assigned this Aug 28, 2025
@cthach cthach added security Security Issues backport-required cli Tickets related to CLI experience size/md sec-internal Security Vulnerability - Reported by employees or auditors, no known exploitation backport/branch/v16 backport/branch/v17 backport/branch/v18 application-access labels Aug 28, 2025
Comment thread lib/config/configuration.go Outdated
Signed-off-by: Chris Thach <chris.thach@goteleport.com>
@cthach cthach force-pushed the cthach/restrict-public-addr branch from 47a562e to 37902d9 Compare August 28, 2025 22:32
cthach added 4 commits August 29, 2025 18:20
Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Comment thread lib/service/servicecfg/app.go Outdated
…ethod.

Signed-off-by: Chris Thach <chris.thach@goteleport.com>
@cthach cthach force-pushed the cthach/restrict-public-addr branch from 2e2d454 to 23fcc9b Compare September 2, 2025 20:45
Signed-off-by: Chris Thach <chris.thach@goteleport.com>
…d add validation check in connections handler

Signed-off-by: Chris Thach <chris.thach@goteleport.com>
@cthach cthach force-pushed the cthach/restrict-public-addr branch from 3b08ac5 to e91ef38 Compare September 2, 2025 21:47
Signed-off-by: Chris Thach <chris.thach@goteleport.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Sep 3, 2025

Amplify deployment status

Branch Commit Job ID Status Preview Updated (UTC)
cthach/restrict-public-addr b5e75b5 12 ✅SUCCEED cthach-restrict-public-addr 2025-09-04 19:52:00

Comment thread lib/srv/app/connections_handler.go Outdated
Comment thread lib/services/app.go
Comment on lines +91 to +95
"Application %q public address %q conflicts with the Teleport Proxy public address. "+
"If both addresses are identical, requests intended for the proxy could be misrouted to the application, "+
"compromising security. "+
"Configure the application to use a unique public address that does not match the proxy's public addresses. "+
"Refer to https://goteleport.com/docs/enroll-resources/application-access/guides/connecting-apps/.",
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 would consider dropping the explanation to keep the message concise and not distract from what is wrong and how to remediate.

Suggested change
"Application %q public address %q conflicts with the Teleport Proxy public address. "+
"If both addresses are identical, requests intended for the proxy could be misrouted to the application, "+
"compromising security. "+
"Configure the application to use a unique public address that does not match the proxy's public addresses. "+
"Refer to https://goteleport.com/docs/enroll-resources/application-access/guides/connecting-apps/.",
"Application %q public address %q conflicts with the Teleport Proxy public address. "+
"Configure the application to use a unique public address that does not match the proxy's public addresses. "+
"Refer to https://goteleport.com/docs/enroll-resources/application-access/guides/connecting-apps/.",

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.

Yes, I like that! Pushed in 20b176c

Comment thread lib/web/app/middleware.go Outdated
Comment on lines +96 to +97
"If both addresses are identical, requests intended for the proxy could be misrouted to the application, " +
"compromising security. " +
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.

Same suggestion as above.

Suggested change
"If both addresses are identical, requests intended for the proxy could be misrouted to the application, " +
"compromising security. " +

…licts with proxy

Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Comment thread lib/services/app.go Outdated
// ValidateApp validates the Application resource.
func ValidateApp(app types.Application, proxyGetter ProxyGetter) error {
// Prevent routing conflicts and session hijacking by ensuring the application's public address
// does not match any of the proxy's public addresses. If both addresses are identical,
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.

nit: grammatically I think you mean "the public address of any proxy" (i.e. each proxy only has one)

Copy link
Copy Markdown
Contributor Author

@cthach cthach Sep 4, 2025

Choose a reason for hiding this comment

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

(i.e. each proxy only has one)

When I first started this, I assumed exactly that. After looking through the code, I found that Proxy can have more than one 🤯 and it will even start just fine if multiple addresses are set in the public_addr field (e.g. [ "p1.example.com", "p2.example.com"]

Is this a bug or a valid configuration?

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 we only return one with GetPublicAddr below. Maybe this could lead to a bypass if I can set multiple, but we're only validating the first, which seems to be how it works:

// GetPublicAddr returns a public address where this server can be reached.
func (s *ServerV2) GetPublicAddr() string {
	addrs := s.GetPublicAddrs()
	if len(addrs) != 0 {
		return addrs[0]
	}
	return ""
}

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.

Interesting. I'm not sure the reasoning behind that, but there is a GetPublicAddrs() that we can use. I'll update to use that instead so we're validating all public addrs.

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.

Done in b5e75b5.

Thoughts?

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 good to me!

Comment thread lib/services/app.go Outdated
Comment thread lib/web/app/middleware.go Outdated
h.logger.ErrorContext(r.Context(), errMsg, "launcher_params", p)

// Immediately return an error since this is a critical misconfiguration 🛑
if p.publicAddr == proxyAddr.Host() {
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.

Why is this if statement here, but we log the error to warn admins outside of it?

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.

Great catch! Fixed in 3ffc606

Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Signed-off-by: Chris Thach <chris.thach@goteleport.com>
@cthach cthach enabled auto-merge September 4, 2025 20:05
@cthach cthach added this pull request to the merge queue Sep 4, 2025
Merged via the queue into master with commit 0627efa Sep 4, 2025
43 checks passed
@cthach cthach deleted the cthach/restrict-public-addr branch September 4, 2025 20:28
@backport-bot-workflows
Copy link
Copy Markdown
Contributor

@cthach See the table below for backport results.

Branch Result
branch/v16 Failed
branch/v17 Failed
branch/v18 Failed

cthach added a commit that referenced this pull request Sep 4, 2025
… a Teleport Proxy public address 👮🏾 (#58475)

* fix: apps should not be able to set public_addr to the web proxy address

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* feat: add API validation

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* test: add coverage for UpsertApplicationServer

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: polish

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: make consistent

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: use ValidateApp func everywhere. Revert changes to Check* method.

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: dedupe

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: improve error messages for application address conflicts and add validation check in connections handler

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* ux: bubble up friendly error to UI

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: revert unnecessary change

* fix: app public address in redirect

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: streamline proxy address validation in ValidateApp function

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: remove contact cluster admin in favor of self-service. Add logging.

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* Apply suggestions from code review

Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>

* fix: skip proxy servers with unset public addresses in ValidateApp function

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: simplify error messages for application public address conflicts with proxy

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: logging in the wrong spot

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: handle when a server has multiple public addrs

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

---------

Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>
cthach added a commit that referenced this pull request Sep 4, 2025
… a Teleport Proxy public address 👮🏾 (#58475)

* fix: apps should not be able to set public_addr to the web proxy address

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* feat: add API validation

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* test: add coverage for UpsertApplicationServer

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: polish

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: make consistent

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: use ValidateApp func everywhere. Revert changes to Check* method.

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: dedupe

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: improve error messages for application address conflicts and add validation check in connections handler

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* ux: bubble up friendly error to UI

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: revert unnecessary change

* fix: app public address in redirect

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: streamline proxy address validation in ValidateApp function

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: remove contact cluster admin in favor of self-service. Add logging.

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* Apply suggestions from code review

Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>

* fix: skip proxy servers with unset public addresses in ValidateApp function

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: simplify error messages for application public address conflicts with proxy

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: logging in the wrong spot

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: handle when a server has multiple public addrs

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

---------

Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>
Signed-off-by: Chris Thach <chris.thach@goteleport.com>
cthach added a commit that referenced this pull request Sep 4, 2025
… a Teleport Proxy public address 👮🏾 (#58475)

* fix: apps should not be able to set public_addr to the web proxy address

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* feat: add API validation

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* test: add coverage for UpsertApplicationServer

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: polish

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: make consistent

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: use ValidateApp func everywhere. Revert changes to Check* method.

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: dedupe

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: improve error messages for application address conflicts and add validation check in connections handler

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* ux: bubble up friendly error to UI

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: revert unnecessary change

* fix: app public address in redirect

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: streamline proxy address validation in ValidateApp function

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: remove contact cluster admin in favor of self-service. Add logging.

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* Apply suggestions from code review

Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>

* fix: skip proxy servers with unset public addresses in ValidateApp function

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: simplify error messages for application public address conflicts with proxy

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: logging in the wrong spot

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: handle when a server has multiple public addrs

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

---------

Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>
Signed-off-by: Chris Thach <chris.thach@goteleport.com>
cthach added a commit that referenced this pull request Sep 4, 2025
… a Teleport Proxy public address 👮🏾 (#58475)

* fix: apps should not be able to set public_addr to the web proxy address

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* feat: add API validation

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* test: add coverage for UpsertApplicationServer

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: polish

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: make consistent

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: use ValidateApp func everywhere. Revert changes to Check* method.

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: dedupe

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: improve error messages for application address conflicts and add validation check in connections handler

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* ux: bubble up friendly error to UI

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: revert unnecessary change

* fix: app public address in redirect

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: streamline proxy address validation in ValidateApp function

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: remove contact cluster admin in favor of self-service. Add logging.

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* Apply suggestions from code review

Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>

* fix: skip proxy servers with unset public addresses in ValidateApp function

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: simplify error messages for application public address conflicts with proxy

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: logging in the wrong spot

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: handle when a server has multiple public addrs

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

---------

Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>
Signed-off-by: Chris Thach <chris.thach@goteleport.com>
github-merge-queue bot pushed a commit that referenced this pull request Sep 5, 2025
… a Teleport Proxy public address 👮🏾 (#58475) (#58768)

* fix: apps should not be able to set public_addr to the web proxy address



* feat: add API validation



* test: add coverage for UpsertApplicationServer



* refactor: polish



* refactor: make consistent



* refactor: use ValidateApp func everywhere. Revert changes to Check* method.



* refactor: dedupe



* refactor: improve error messages for application address conflicts and add validation check in connections handler



* ux: bubble up friendly error to UI



* refactor: revert unnecessary change

* fix: app public address in redirect



* fix: streamline proxy address validation in ValidateApp function



* refactor: remove contact cluster admin in favor of self-service. Add logging.



* Apply suggestions from code review



* fix: skip proxy servers with unset public addresses in ValidateApp function



* refactor: simplify error messages for application public address conflicts with proxy



* fix: logging in the wrong spot



* fix: handle when a server has multiple public addrs



---------

Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>
github-merge-queue bot pushed a commit that referenced this pull request Sep 5, 2025
… a Teleport Proxy public address 👮🏾 (#58475) (#58767)

* fix: apps should not be able to set public_addr to the web proxy address



* feat: add API validation



* test: add coverage for UpsertApplicationServer



* refactor: polish



* refactor: make consistent



* refactor: use ValidateApp func everywhere. Revert changes to Check* method.



* refactor: dedupe



* refactor: improve error messages for application address conflicts and add validation check in connections handler



* ux: bubble up friendly error to UI



* refactor: revert unnecessary change

* fix: app public address in redirect



* fix: streamline proxy address validation in ValidateApp function



* refactor: remove contact cluster admin in favor of self-service. Add logging.



* Apply suggestions from code review



* fix: skip proxy servers with unset public addresses in ValidateApp function



* refactor: simplify error messages for application public address conflicts with proxy



* fix: logging in the wrong spot



* fix: handle when a server has multiple public addrs



---------

Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>
github-merge-queue bot pushed a commit that referenced this pull request Sep 5, 2025
… a Teleport Proxy public address 👮🏾 (#58475) (#58766)

* fix: apps should not be able to set public_addr to the web proxy address



* feat: add API validation



* test: add coverage for UpsertApplicationServer



* refactor: polish



* refactor: make consistent



* refactor: use ValidateApp func everywhere. Revert changes to Check* method.



* refactor: dedupe



* refactor: improve error messages for application address conflicts and add validation check in connections handler



* ux: bubble up friendly error to UI



* refactor: revert unnecessary change

* fix: app public address in redirect



* fix: streamline proxy address validation in ValidateApp function



* refactor: remove contact cluster admin in favor of self-service. Add logging.



* Apply suggestions from code review



* fix: skip proxy servers with unset public addresses in ValidateApp function



* refactor: simplify error messages for application public address conflicts with proxy



* fix: logging in the wrong spot



* fix: handle when a server has multiple public addrs



---------

Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>
mmcallister pushed a commit that referenced this pull request Sep 22, 2025
… a Teleport Proxy public address 👮🏾 (#58475)

* fix: apps should not be able to set public_addr to the web proxy address

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* feat: add API validation

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* test: add coverage for UpsertApplicationServer

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: polish

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: make consistent

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: use ValidateApp func everywhere. Revert changes to Check* method.

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: dedupe

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: improve error messages for application address conflicts and add validation check in connections handler

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* ux: bubble up friendly error to UI

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: revert unnecessary change

* fix: app public address in redirect

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: streamline proxy address validation in ValidateApp function

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: remove contact cluster admin in favor of self-service. Add logging.

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* Apply suggestions from code review

Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>

* fix: skip proxy servers with unset public addresses in ValidateApp function

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* refactor: simplify error messages for application public address conflicts with proxy

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: logging in the wrong spot

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

* fix: handle when a server has multiple public addrs

Signed-off-by: Chris Thach <chris.thach@goteleport.com>

---------

Signed-off-by: Chris Thach <chris.thach@goteleport.com>
Co-authored-by: rosstimothy <39066650+rosstimothy@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

application-access backport/branch/v17 backport/branch/v18 backport-required cli Tickets related to CLI experience documentation sec-internal Security Vulnerability - Reported by employees or auditors, no known exploitation security Security Issues size/md

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants