Filter patterns (subscription subFilter, policy-group Filter, message
MsgFilter) accept arbitrary user input while the tested text (remarks
from subscriptions, log lines) is attacker-influenced. Regex.IsMatch
without timeout hangs on evil patterns like (a+)+$ - a malicious
subscription can freeze the UI/log pipeline on every update.
Add Utils.IsRegexMatch with a 2s timeout; fail open (match) with a log
so no node or message is silently dropped. Apply to all four call
sites.
Co-authored-by: sdhfsl <sdhfsl@users.noreply.github.com>
Refactor `ConfigHandler.MoveServer` to accept a `List<string>` of profile `IndexId`s instead of full `ProfileItem` objects. In `ProfilesViewModel`, remove the duplicated `_lstProfile` cache and build move lists directly from `ProfileItems`, so move and drag-reorder actions use the live UI order and avoid stale profile snapshots.
#9930 made the Xray TUN inbound always request ::/0 in autoSystemRoutingTable
so that IPv6 stops bypassing the tunnel. That only helps a host which actually
holds a globally routable IPv6 address. On any other host it does harm.
With IPv6 disabled the TUN device gets no IPv6 address at all, the kernel
rejects the route with EACCES and the whole inbound fails to start:
Failed to start: app/proxyman/inbound: failed to start proxy > proxy/tun:
failed to add system route ::/0 > permission denied
With IPv6 enabled but no global address the route is accepted and the host
gains an IPv6 default route it cannot use. The TUN completes the TCP handshake
locally before dialing the outbound, so IPv6 destinations start to look
reachable and get picked, and the connection then dies at the outbound instead
of failing fast (#10051).
Neither host has IPv6 traffic that could bypass the tunnel, so ::/0 buys them
nothing. Detect a global IPv6 address once while building the config context
and drop ::/0 when there is none. Link-local and unique local addresses do not
count: they never reach the IPv6 internet.
Co-authored-by: liuclare <177657698+liuclare@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
`Utils.ParseQueryString` already unescapes every value, and
`BaseFmt.GetQueryDecoded` unescaped it again. A value that still held a
valid percent sequence after the first pass decayed on the second: an
obfuscation password of `ob%41fs` is exported as `ob%2541fs` and imported
back as `obAfs`. Only well-formed sequences are affected, which is why the
damage is silent - `100%` and `66%ff` survive untouched.
The same function also split each pair on every `=`, and skipped the pair
unless exactly two halves came out. RFC 3986 lists `=` among the
sub-delimiters a query value may carry, so only the first one separates the
key from the value, and `HttpUtility.ParseQueryString` reads a query string
the same way. Splitting on all of them discarded a syntactically valid
pair: `?ech=AAj+DQAEAAAAAA==` was lost entirely, and so was a `plugin`
value in the non-canonical SIP002 spelling, since those are `;` separated
`key=value` lists.
v2rayN percent-encodes both on export, so its own links were never
affected; what changes is that the parser now follows the grammar instead
of discarding a pair it cannot split in two.
Splitting on the first `=` only, and reading the value the parser already
decoded, fixes both. `ParseQueryString` keeps decoding because
`ConfigHandler` reads its result directly.
`GetQueryDecoded` and `GetQueryValue` are now equivalent; they are left
separate to keep this change small, and can be collapsed if you prefer.
The Hysteria2 URI scheme makes the port optional: "The hostname and
optional port of the server. If the port is omitted, it defaults to 443."
`Hysteria2Fmt.Resolve` assigned `url.Port` straight through, and
`System.Uri` answers -1 for an unregistered scheme that carries no port,
so `hysteria2://password@hy2.example/` imported as a profile with
`Port = -1`. `ProfileItem.IsValid` rejects any port outside 1..65535, so
such a link produced a profile that could never be used, and nothing said
why.
-1 is the only value that means "the port was omitted"; a ':' with no
digits after it maps to -1 as well. An explicit ":0" parses as 0 and
keeps the fate it has today - rejected by `IsValid` - rather than being
redirected to a server the link never named.
`ResolveRealm` takes its port from `HyRealm.RendezvousPort` instead of
the URI, so it is unaffected.
The added tests cover both spellings of the scheme, with and without a
trailing slash, a bare ':', and the resulting profile's validity. Two of
them are controls: an explicit port is still preserved, and an explicit
":0" still does not turn into 443.
Follow-up to #9830: audit of all TunModeItem.EnableTun usages found
three more launch-path reads of the live mutable config where the
behavior must agree with the context snapshot that generated the
config:
- CoreConfigClashService (mihomo custom config): the tun section was
decided from the live config while the mihomo launch elevation uses
the snapshot; a mid-reload toggle could produce a config containing
tun launched without sudo, the same failure fixed in #9830. The tun
state is now passed in as a snapshot.
- CoreManager.LoadCore: the Windows RemoveTunDevice cleanup now checks
the main/pre context snapshots.
- CoreManager.WaitForProxyPort: preContext.AppConfig is a shared live
reference; use preContext.IsTunEnabled instead.
Reads that intentionally stay live: StatusBarViewModel (UI state
source), CoreConfigContextBuilder (the snapshot capture point),
GetPreSocksItem (called during snapshot construction, self-consistent),
and AppManager.StatePort2 (transient mid-reload skew only, self-heals
after reload).
* fix: sanitize system proxy exceptions to avoid macOS ExceptionsList being dropped
On macOS/Linux the exception list is comma-separated and passed to networksetup. It was only stripped of spaces, so a stray newline or a trailing comma left a malformed/empty entry. macOS configd then silently rejects the whole ExceptionsList (scutil --proxy shows no ExceptionsList), so the bypass never takes effect. Split on ',' with TrimEntries + RemoveEmptyEntries and rejoin; behavior-preserving for well-formed input. Windows path (';') is left unchanged.
Note: not built locally (no .NET SDK on hand); relying on CI.
* Update SysProxyHandler.cs
---------
Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
sing-box requires realm.server_url as a full URL (https://host:port).
Bare host:port caused "missing host in realm server_url" on import.
Also forward stun_servers and clear ResolveRealm success message.
Fixes#9635
* first changes
* fix: use ItemsSource for fragment packets ComboBox so value saves correctly
* feat: add customizable packet fragmentation for Xray-core
- Add fragment settings in Core tab: Packets (dropdown), Length (range), Interval (range), MaxSplit (0-10000)
- Support both 'from-to' (e.g., 50-100) and single value (e.g., 50) formats for Length, Interval, and MaxSplit
- Validation with shortened error message: 'Invalid range format. Use from-to (e.g., 50-100).'
- UI in PopupBox (materialDesign) visible only when EnableFragment is checked
- Only Xray-core supported (Mihomo/sing-box fragment code removed)
- Localization updated for 8 languages
* fix: address 2dust review feedback
- Move FragmentPacketsOptions to Global class
- Remove default values from Fragment4RayItem model (set in ConfigHandler)
- Fix Avalonia bindings: move ItemsSource and SelectedItem to code-behind
- Update ViewModel to use Global.FragmentPacketsOptions
- Remove defaults from model properties
* Adjust ui
---------
Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>