Skip to content

fix(provider): validate coder_app URL scheme for external apps - #540

Open
mmustafasenoglu wants to merge 1 commit into
coder:mainfrom
mmustafasenoglu:fix/validate-coder-app-external-url
Open

fix(provider): validate coder_app URL scheme for external apps#540
mmustafasenoglu wants to merge 1 commit into
coder:mainfrom
mmustafasenoglu:fix/validate-coder-app-external-url

Conversation

@mmustafasenoglu

Copy link
Copy Markdown

Closes #483

Summary

Adds URL scheme validation for the coder_app resource's url field when external = true.

Motivation

Go's url.Parse() is permissive and accepts bare strings like "my-repo" as relative URLs. However, JavaScript's new URL() in the Coder frontend requires a scheme and throws TypeError: Invalid URL when encountering these values, crashing the UI.

Changes

  • provider/app.go: Added CustomizeDiff that checks url has a scheme when external = true. Internal URLs (external=false) still accept relative paths since they are resolved server-side.
  • provider/helpers/validation.go: Added ValidateExternalURL helper for standalone URL scheme validation.
  • provider/helpers/validation_test.go: Added unit tests for ValidateExternalURL.
  • provider/app_test.go: Added ExternalURLValidation test cases covering external/internal URLs with various schemes.

Testing

All existing tests pass. New test cases cover:

  • External with scheme (https://, vscode://, jetbrains-gateway://) → pass
  • External bare string ("my-repo") → error
  • External relative path ("/some/path") → error
  • Internal bare string / relative path → pass (resolved server-side)

When external=true, the URL field now requires a scheme (e.g. https://,
vscode://, jetbrains-gateway://). Bare strings like "my-repo" or
relative paths like "/some/path" are rejected because they cause
JavaScript TypeError in the Coder frontend.

Uses CustomizeDiff to cross-reference external and url fields.
Internal URLs (external=false) still accept relative paths since
they are resolved server-side.

Fixes coder#483
Copilot AI lite review requested due to automatic review settings September 1, 2026 10:28
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@mmustafasenoglu

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@mmustafasenoglu

Copy link
Copy Markdown
Author

recheck

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds validation to prevent invalid coder_app.url values for externally-opened apps (external = true), aligning provider behavior with JavaScript’s stricter URL parsing to avoid frontend crashes.

Changes:

  • Added CustomizeDiff validation in coder_app to require a URL scheme when external = true.
  • Introduced helpers.ValidateExternalURL for scheme validation and added unit tests for it.
  • Added coder_app acceptance/unit test cases covering external vs internal URL behaviors.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
provider/app.go Adds CustomizeDiff validation for external app URLs.
provider/helpers/validation.go Introduces ValidateExternalURL helper.
provider/helpers/validation_test.go Adds unit tests for ValidateExternalURL.
provider/app_test.go Adds test coverage for external/internal URL validation behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread provider/app.go
Comment on lines +46 to +61
urlVal, ok := diff.GetOkExists("url")
if !ok {
return nil
}

u, err := url.Parse(urlVal.(string))
if err != nil {
return fmt.Errorf("invalid URL %q: %w", urlVal.(string), err)
}

if u.Scheme == "" {
return fmt.Errorf(
"\"url\" must have a URL scheme (e.g. https://, vscode://, jetbrains-gateway://) when \"external\" is true, got %q",
urlVal.(string),
)
}
Comment on lines +207 to +212
{
name: "localhost without scheme",
value: "localhost:8080",
label: "url",
expectError: false, // Go's url.Parse treats "localhost" as the scheme
},
Comment thread provider/app_test.go
Comment on lines +616 to +619
name: "ExternalLocalhostNoScheme",
url: "localhost:8080",
external: true, // Go's url.Parse treats "localhost" as the scheme, so this passes
},
// Go's url.Parse is permissive and accepts bare strings like "my-repo" as
// relative URLs, but JavaScript's new URL() requires a scheme and will crash
// if one is not present.
func ValidateExternalURL(value any, label string) ([]string, []error) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

label is only used as a detail added to the error message, all the tests only pass "url" as a label . its unneeded as input to this function .

all first param returns are nil, I think these were meant to represent warnings but there are none. neither return parameter needs to be an array . mostly good tests tho.

could also check that parsed.Host is not empty .

@untra untra left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thank you for the contribution. I am also actively working on this issue right now. there are improvements to validation and implementation, but good checking extra beyond url.Parse(value) ; external urls should carry a scheme and host.

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.

Validate coder_app URL field to require a parseable scheme

3 participants