{"record":{"id":"2bd4c1177a2f8a01","repo":"router-for-me/CLIProxyAPI","slug":"source-url-must-use-http-or-https","errorCode":null,"errorMessage":"source-url must use http or https","messagePattern":"source-url must use http or https","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginstore/manifest.go","lineNumber":187,"sourceCode":"\t\treturn fmt.Errorf(\"missing required field id\")\n\t}\n\tif !validPluginID(id) {\n\t\treturn fmt.Errorf(\"invalid plugin id %q\", id)\n\t}\n\treturn nil\n}\n\nfunc validateManifestSourceURL(sourceURL string) error {\n\tsourceURL = strings.TrimSpace(sourceURL)\n\tif sourceURL == \"\" {\n\t\treturn fmt.Errorf(\"missing required field source-url\")\n\t}\n\tparsed, errParse := url.Parse(sourceURL)\n\tif errParse != nil || parsed.Scheme == \"\" || parsed.Host == \"\" {\n\t\treturn fmt.Errorf(\"invalid source-url\")\n\t}\n\tif parsed.Scheme != \"https\" && parsed.Scheme != \"http\" {\n\t\treturn fmt.Errorf(\"source-url must use http or https\")\n\t}\n\tif hasSensitiveQueryParameter(parsed) {\n\t\treturn fmt.Errorf(\"source-url contains sensitive query parameter\")\n\t}\n\treturn nil\n}\n","sourceCodeStart":169,"sourceCodeEnd":194,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginstore/manifest.go#L169-L194","documentation":"validateManifestSourceURL() accepts only http and https schemes. A URL that parses fine and has a host but uses file://, git+ssh://, ftp://, etc. is rejected because the pluginstore fetches provenance over HTTP(S) only.","triggerScenarios":"source-url: \"file:///srv/plug\"; \"git@github.com:acme/plug.git\" (parsed scheme is ssh-ish/empty — typically caught by 691, but scp-like strings with a scheme like \"ssh://git@github.com/acme/plug\" land here); \"ftp://mirror/plug\".","commonSituations":"Local development manifests pointing at a file path; developers pasting the SSH clone URL instead of the HTTPS web URL; internal git-scheme URIs from documentation.","solutions":["Use the HTTPS web URL of the repository/page: https://github.com/acme/plug","For local development, serve the source over a local http server or accept using the real upstream URL","Check for typos like \"htps://\" which can masquerade as unsupported schemes"],"exampleFix":"# before\nsource-url: file:///srv/plug-src\n# source-url must use http or https\n\n# after\nsource-url: https://github.com/acme/plug","handlingStrategy":"validation","validationCode":"u, err := url.Parse(strings.TrimSpace(m.SourceURL))\nif err != nil || u.Scheme == \"\" || u.Host == \"\" || (u.Scheme != \"https\" && u.Scheme != \"http\") {\n    return errors.New(\"source-url must be http(s)\")\n}\n_ = m.Validate()","typeGuard":"func httpSourceURL(raw string) bool { u, err := url.Parse(strings.TrimSpace(raw)); return err == nil && (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\" }","tryCatchPattern":"if err := m.Validate(); err != nil && strings.Contains(err.Error(), \"must use http or https\") { /* replace file:// or ssh:// with the https web URL */ }","preventionTips":["Use the repository's web URL, never clone URLs or local paths","CI lint rejecting non-http(s) schemes in source-url"],"tags":["pluginstore","manifest","source-url","scheme"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}