mihomo-party-org/clash-party · error
Plugin URL must use https
Error message
Plugin URL must use https
What it means
After parsing succeeds, parseDownloadUrl requires the protocol to be exactly https:. Any other scheme (http:, ftp:, file:) is rejected with 'Plugin URL must use https' to guarantee plugin downloads are fetched over TLS.
Source
Thrown at src/main/resolve/plugin/remote.ts:13
import { getAppConfig } from '../../config/app'
import { MAX_PLUGIN_FILE_BYTES } from './constants'
import { requestOnce } from './http-client'
import { createGuardedLookup, isForbiddenHost } from './net-guard'
function parseDownloadUrl(url: string): URL {
let parsed: URL
try {
parsed = new URL(url)
} catch {
throw new Error('Invalid plugin URL')
}
if (parsed.protocol !== 'https:') throw new Error('Plugin URL must use https')
if (parsed.username || parsed.password) throw new Error('Plugin URL must not contain userinfo')
if (parsed.hash) throw new Error('Plugin URL must not contain a fragment')
if (isForbiddenHost(parsed.hostname)) throw new Error('Plugin URL must use a public host')
return parsed
}
export async function fetchRemotePlugin(url: string): Promise<string> {
const parsed = parseDownloadUrl(url)
const { subscriptionTimeout = 30000, pluginUseProxy } = await getAppConfig()
let proxy: { host: string; port: number } | undefined
if (pluginUseProxy) {
const { getControledMihomoConfig } = await import('../../config/controledMihomo')
const { 'mixed-port': port = 7890 } = await getControledMihomoConfig()
proxy = { host: '127.0.0.1', port }
}
const response = await requestOnce(parsed.toString(), {
method: 'GET',View on GitHub (pinned to 911e090537)
Solutions
- Switch the source to an https:// URL (use https mirror or CDN link).
- Upgrade an internal http server to TLS, or use an https reverse proxy.
- If the content is local, install it through the local-file plugin path instead of fetchRemotePlugin.
Example fix
// before
await fetchRemotePlugin('http://mirror.example.com/plugin.yaml')
// after
await fetchRemotePlugin('https://mirror.example.com/plugin.yaml') Defensive patterns
Strategy: validation
Validate before calling
const u = new URL(input)
if (u.protocol !== 'https:') throw new Error('download URL must start with https://') Type guard
const isHttpsUrl = (s: string): boolean => {
try { return new URL(s).protocol === 'https:' } catch { return false }
} Try / catch
try {
await fetchRemotePlugin(input)
} catch (e) {
if (e.message === 'Plugin URL must use https') {
showUrlInputError('Only https:// download links are supported')
} else throw e
} Prevention
- Only distribute https mirror links
- Migrate internal http servers to TLS
- Route local content through the local-file install path, not fetchRemotePlugin
When it happens
Trigger: Passing a download URL whose protocol is not https — most commonly an http:// mirror link, or a file:// URL for a local file.
Common situations: Old or internal mirror links still using http; user pastes a local file:// path; copying an insecure download link from docs.
Related errors
- Plugin URL must not contain userinfo
- Plugin URL must use a public host
- Invalid core path: directory traversal detected
- transient
- Forbidden header: ${k}
AI-assisted analysis of mihomo-party-org/clash-party@911e090537 (2026-08-30).
Data as JSON: /api/errors/df5523b39142d24f.
Report an issue: GitHub.