# Risk map — fatedier/frp

> Canonical page: https://codevetter.com/unpack/frp/risk-map

# Risk map — fatedier/frp

Scanned commit d20a232996007dfe6ab425abc0a39a3ae9a0889b (2026-09-10). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

The highest-risk areas are command-execution token sources (gated behind the TokenSourceExec unsafe feature), filesystem-serving and socket-exposing client plugins (static_file, unix_domain_socket which can expose docker.sock), the VirtualNet TUN setup that shells out to ifconfig/route on macOS, and admin web servers that depend on auth middleware correctness. Concurrency risk concentrates in server/control.go's ControlManager, which enforces a documented lock order (runMu -> cm.mu -> lifecycleMu -> registry) and generation handoff barriers; regressions there cause deadlocks or leaked controls. The deprecated INI path (pkg/config/legacy) and the testing-only --config_dir mode are legacy surface. Plugin content mutation uses a deliberate panic on wrong types.
- ExecSource.Resolve executes arbitrary commands (exec.CommandContext with env passthrough) to produce auth tokens; it is gated by the TokenSourceExec entry in both ClientUnsafeFeatures and ServerUnsafeFeatures requiring --allow-unsafe. — [pkg/config/v1/value_source.go#L136-160](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/config/v1/value_source.go#L136-L160) [pkg/policy/security/unsafe.go#L1-30](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/policy/security/unsafe.go#L1-L30)
- VirtualNet setup on Darwin shells out to ifconfig and route to configure the TUN device; tun_linux.go uses netlink. Errors here are runtime-privilege dependent. — [pkg/vnet/tun_darwin.go#L51-80](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/vnet/tun_darwin.go#L51-L80) [pkg/vnet/tun_linux.go](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/vnet/tun_linux.go)
- unix_domain_socket and static_file client plugins expose local filesystem paths/sockets remotely; README documents exposing /var/run/docker.sock as a TCP proxy, an intentionally dangerous capability. — [pkg/plugin/client/unix_domain_socket.go](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/plugin/client/unix_domain_socket.go) [pkg/plugin/client/static_file.go](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/plugin/client/static_file.go) [README.md#L334-385](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/README.md#L334-L385)
- Admin APIs (client /api/config PUT, /api/stop, /api/store/*; server DELETE /api/proxies, /api/v2/system/prune) are powerful mutation endpoints guarded only by helper.AuthMiddleware on the dashboard port — misconfiguration of webServer auth exposes full control. (inferred) — [client/api_router.go#L33-55](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/client/api_router.go#L33-L55) [server/api_router.go#L29-60](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/api_router.go#L29-L60)
- ControlManager implements a strict multi-lock protocol (never wait on runMu holding cm.mu; order runMu -> cm.mu -> ctl.lifecycleMu -> registry locks) with generation IDs and handoff barriers; the complexity concentrates deadlock/race risk in control.go. — [server/control.go#L51-105](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/control.go#L51-L105) [server/control.go#L222-248](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/control.go#L222-L248)
- GetWorkConn recovers from panics and the worker teardown closes pooled conns, but a full workConnCh silently discards registered work conns ('work connection pool is full, discarding'). — [server/control.go#L595-637](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/control.go#L595-L637) [server/control.go#L329-337](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/control.go#L329-L337)
- Plugin content mutation in handleMutableContent does retContent.(*T) with a comment 'Buggy Plugin implementations still panic here, by design' — a malicious/broken server plugin path can panic the handler goroutine. — [pkg/plugin/server/manager.go#L99-103](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/plugin/server/manager.go#L99-L103)
- Server plugins make outbound HTTP calls to user-configured addresses during login/proxy/workconn events; a plugin failure rejects the operation (errors fail closed for mutable ops like Login/NewProxy). — [pkg/plugin/server/manager.go#L90-98](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/plugin/server/manager.go#L90-L98) [pkg/plugin/server/http.go](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/plugin/server/http.go) [server/service.go#L461-476](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/service.go#L461-L476)
- Legacy INI support is deprecated and routed through pkg/config/legacy converters; conf/legacy holds reference INI files. New features are TOML/YAML/JSON-only, so the legacy path is dead-end code that still runs when a 'common' section is detected. — [pkg/config/load.go#L65-82](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/config/load.go#L65-L82) [pkg/config/legacy](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/config/legacy) [conf/legacy](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/conf/legacy) [cmd/frps/root.go#L73-76](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/cmd/frps/root.go#L73-L76)
- xtcp relies on public STUN (default stun.easyvoip.com:3478) and NAT-behavior heuristics in nathole; P2P may silently fail on incompatible NATs — README itself recommends stcp fallback. — [pkg/config/v1/client.go#L89](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/config/v1/client.go#L89) [pkg/nathole/analysis.go](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/nathole/analysis.go) [README.md#L455-459](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/README.md#L455-L459)
- SSH tunnel gateway accepts native SSH connections on a dedicated port and pipes them into the control plane (InternalListener); it expands the server's attack surface to the SSH protocol. (inferred) — [server/service.go#L280-287](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/service.go#L280-L287) [pkg/ssh/gateway.go](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/ssh/gateway.go)
- Duplicate proxy/visitor names across merged config sources are rejected at load by validateNoDuplicateNames; before this check a duplicate would have been silently dropped — indicates historically fragile merge semantics. (inferred) — [pkg/config/load.go#L424-447](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/pkg/config/load.go#L424-L447)
- frpc tlsListener sniffs first bytes to distinguish frp TLS from HTTPS; misclassification risk exists when vhostHTTPS shares the bind port (comment notes 0x16 ambiguity). (inferred) — [server/service.go#L352-355](https://github.com/fatedier/frp/blob/d20a232996007dfe6ab425abc0a39a3ae9a0889b/server/service.go#L352-L355)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
