Skip to content

fix(proxy): stop emitting allowInsecure for domains with a valid cert - #34

Open
yarrrly wants to merge 1 commit into
hiddify:devfrom
yarrrly:fix/allow-insecure-valid-cert
Open

fix(proxy): stop emitting allowInsecure for domains with a valid cert#34
yarrrly wants to merge 1 commit into
hiddify:devfrom
yarrrly:fix/allow-insecure-valid-cert

Conversation

@yarrrly

@yarrrly yarrrly commented Aug 14, 2026

Copy link
Copy Markdown

Fixes hiddify/Hiddify-Manager#5438.

Xray-core removed allowInsecure. In current main the check is unconditional
(infra/conf/transport_security.go:361):

if c.AllowInsecure {
    return nil, errors.PrintRemovedFeatureError(`"allowInsecure"`, `"pinnedPeerCertSha256"(pcs) and "verifyPeerCertByName"(vcn)`)
}

The config is rejected as a whole, so a client bundling a recent core refuses the
subscription outright. #5438 reports it for Happ Plus, and the same core change
produced 2dust/v2rayN#8736, MHSanaei/3x-ui#3727 and
Openwrt-Passwall/openwrt-passwall2#999, all with the identical
The feature "allowInsecure" has been removed error.

The panel puts the flag on every non-Reality TLS outbound, including domains it
classifies itself as needing a valid certificate. sni_host_server_extractor
computes the correct value and then discards it:

allow_insecure=not domain_db.need_valid_ssl
if all_snis := split_pattern.split((domain_db.servernames or "").strip()):
    sni = random_or_none(all_snis) or sni
    if 'reality' in domain_db.mode:
        allow_insecure=False
        ...
    else:
        allow_insecure=True

need_valid_ssl is True for direct, cdn, worker, relay, auto_cdn_ip,
old_xtls_direct and sub_link_only (models/domain.py:136), so line 324 already
yields False for the domains that are supposed to have a certificate. The
condition below it reads as "this domain has servernames", but it never gates:

>>> re.compile(r'[ \t\r\n;,]+').split("")
['']
>>> bool([''])
True

The block is entered for every domain, which makes line 324 dead code for
anything that is not Reality. The value then goes into xrayjson.py:243
(allowInsecure), xray.py:209 (allowInsecure=true and insecure=true in the
URI), clash.py:75,115 (skip-cert-verify) and singbox.py:216 (insecure).

This keeps line 324 as the source of truth, removes the else branch, and makes
the condition test what it was written to test. Reality is still forced to False.

allow_insecure per domain mode, before and after:

mode need_valid_ssl before after
direct True True False
cdn, no servernames True True False
cdn + domain fronting True True False
relay True True False
fake False True True
special_reality_tcp False False False

The workaround circulating in the #5438 thread only filters the empty split. That
leaves cdn with domain fronting on True, because that path takes the else
branch on purpose. The reporter wrote in the thread that they were not going to
open a PR and preferred to leave the design to you; the diagnosis above is theirs.

There is a cost. A domain in a need_valid_ssl mode whose certificate is not
CA-valid (ACME never issued, or a fronting SNI the CDN does not serve) now stops
connecting instead of silently skipping verification. On Xray those configs are
already rejected by the core, so nothing that works today gets worse. On sing-box
and mihomo, where insecure and skip-cert-verify still exist, such a setup does
break, and the operator has to fix the certificate or move the domain to a mode
that is not expected to have one.

fake keeps allow_insecure = True, so its xray configs stay rejected by new
cores. The replacement Xray points at is pinnedPeerCertSha256 /
verifyPeerCertByName, which the panel could compute for the modes that cannot be
CA-verified. That is a larger change and not part of this one.

Test

make test and make lint are @echo skip here and there is no tests/
directory, so there is nothing to extend. I checked the function by executing it
against each domain mode, which is where the table comes from.

On a running panel: with a direct domain and core_type = xray, open
/<proxy_path>/<uuid>/xray/ and look for allowInsecure. Before the change every
TLS outbound carries "allowInsecure": true; after a panel restart they are
false. Same for the vless:// links in /<proxy_path>/<uuid>/sub/, where
allowInsecure=true&insecure=true disappears from the query.

need_valid_ssl already yields False for the modes that are supposed to have a
certificate, but the servernames branch overwrote it with True for every
non-Reality domain. The guard never gates: re.split on an empty string returns
[''], which is truthy, so the block runs for every domain.

Xray-core has removed allowInsecure, so configs carrying it are now rejected.

Refs hiddify/Hiddify-Manager#5438
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.

Configs with allowInsecure: true are rejected by Xray-core since 2026-06-01 — clients (Happ Plus, etc.) can no longer connect

1 participant