Skip to content

fix(web): validate service and namespace in profile download handler - #15726

Open
musthaf-bughunter wants to merge 1 commit into
linkerd:mainfrom
musthaf-bughunter:web-profile-download-validate
Open

musthaf-bughunter wants to merge 1 commit into
linkerd:mainfrom
musthaf-bughunter:web-profile-download-validate

Conversation

@musthaf-bughunter

Copy link
Copy Markdown

The dashboard's GET /profiles/new handler passes the service and
namespace query parameters straight into the ServiceProfile
text/template and into an unquoted Content-Disposition filename. A
link such as

/profiles/new?namespace=default&service=x%3B%20filename*%3DUTF-8''run.sh%0A---%0AapiVersion:...%0Akind:%20ClusterRoleBinding...

returns a download whose body contains attacker-supplied YAML documents
(for example a ClusterRoleBinding to cluster-admin) next to the
ServiceProfile, and whose filename* parameter overrides the intended
<service>-profile.yml name. The dashboard only checks the Host header,
so a top-level navigation to the port-forwarded dashboard is enough to
trigger the download.

linkerd profile --template already rejects these values by requiring
the service to be a DNS-1035 label and the namespace a DNS-1123 label
before calling the same renderer. Apply the same checks in
handleProfileDownload and return 400 when they fail.

Validation: added TestHandleConfigDownloadInvalidParams, which fails on
main (200 with the injected header and body) and passes with this
change. go test ./web/... and go vet ./web/... pass.

Signed-off-by: mushtaf saheb musthaf@medios.digiscrypt.com

The dashboard's `GET /profiles/new` handler passes the `service` and
`namespace` query parameters straight into the ServiceProfile
text/template and into an unquoted `Content-Disposition` filename. A
link such as

    /profiles/new?namespace=default&service=x%3B%20filename*%3DUTF-8''run.sh%0A---%0AapiVersion:...%0Akind:%20ClusterRoleBinding...

returns a download whose body contains attacker-supplied YAML documents
(for example a ClusterRoleBinding to cluster-admin) next to the
ServiceProfile, and whose `filename*` parameter overrides the intended
`<service>-profile.yml` name. The dashboard only checks the Host header,
so a top-level navigation to the port-forwarded dashboard is enough to
trigger the download.

`linkerd profile --template` already rejects these values by requiring
the service to be a DNS-1035 label and the namespace a DNS-1123 label
before calling the same renderer. Apply the same checks in
handleProfileDownload and return 400 when they fail.

Validation: added TestHandleConfigDownloadInvalidParams, which fails on
main (200 with the injected header and body) and passes with this
change. `go test ./web/...` and `go vet ./web/...` pass.

Signed-off-by: mushtaf saheb <musthaf@medios.digiscrypt.com>
@musthaf-bughunter
musthaf-bughunter requested a review from a team as a code owner October 16, 2026 18:38
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.

1 participant