Repository navigation
Releases: GooDAnDReaDY/dsh-lanmode
Release list
v0.8.53 [DSH v0.2.1-rc.2]
Release 0.8.53
- Security (#479): Protect plugin mutating endpoints and sensitive reads under LAN PIN and prevent core auth cookie leakage to unauthenticated LAN clients.
- Resolves #479
v0.8.52 [DSH v0.2.1-rc.2]
Зачем выпускаем
- #353: Автоматический перевыпуск серверного TLS-сертификата при появлении новых адресов или хостов в сети, предотвращающий ошибки SSL
NET::ERR_CERT_COMMON_NAME_INVALID. - #480: Гигиена кодовой базы — стабилизация тестов VAPID, очистка серверных
console.*, удаление мертвых экспортов, разбор и аннотирование пустых блоковcatch.
Что сделано
- TLS (#353): В
lib/tls.js:ensureCertificateвосстановлен вызовstillGood(info, hosts, now). Если хост меняет сетевой адрес или подключается к новой сети/Tailscale, сертификат перевыпускается с включением нового SAN, при этом корневой Root CA (100 лет) сохраняется неизменным. - VAPID (#480): В
lib/push.js:generateVapidKeysдобавлено строгое выравнивание скаляра приватного ключа P-256 нулями до 32 байт, устранившее флап теста при параллельных прогонах. - Серверный вывод (#480): Вызовы
console.errorвlib/devices.jsиlib/bans.jsпереведены на fallbackprocess.stderr.write. - Мертвый код (#480): Удалены неиспользуемые экспорты
canonicalDeviceId,mintCoreAuthCookie,isPidAlive. - Preflight (#480): Аннотированы все 29 пустых блоков
catch,preflight.shпроходит сFAIL=0. - Бюджет пакета: 523,448 байт (при лимите 512 КиБ).
Совместимость и миграции
Полная обратная совместимость. Миграция не требуется.
Проверена совместимость с DeepSeek Harness v0.2.1-rc.2.
Ссылки
- Issues: #353, #480
- PR: #481
- Gitea commit:
ed7c71a - GitHub mirror commit:
4f97b73
v0.8.51 [DSH v0.2.1-rc.2]
Зачем выпускаем
Устранение уязвимости раскрытия sensitive токена именованного туннеля Cloudflare в таблице процессов (ps aux, /proc/<pid>/cmdline) и сообщениях об ошибках (#477).
Что сделано
- Безопасная передача токена: В
lib/tunnel.jsаргумент--tokenисключён из командной строки запускаcloudflared tunnel run. Токен передаётся через переменную окруженияTUNNEL_TOKEN, нативно поддерживаемуюcloudflared. - Санитизация логов и ошибок: Добавлена функция
sanitizeToken(), гарантирующая маскирование ([REDACTED]) токена вthis.lastError, событиях ошибок процесса и статусе туннеля. - Тесты и качество: Добавлен модульный сьют
test/issue-477-tunnel-token-security.test.mjs, скорректированы тесты аудита туннеля. Все 526 тестов проходят. - Бюджет пакета: 523,651 байт (в пределах лимита 512 KiB).
Совместимость и миграции
Полная обратная совместимость со всеми версиями cloudflared. Миграция конфигов не требуется.
Проверена совместимость с DeepSeek Harness v0.2.1-rc.2.
Ссылки
- Issue: #477
- PR: #478
- Gitea commit:
bcb9a9e - GitHub mirror commit:
edff2bd
v0.8.27
English
Release 0.8.27 fixes critical configuration lifecycle, dynamic bridge state synchronization, and client card error reporting issues (#363, #364, #365, #394, #401):
- Nested Schemastery Validation (#363): Strict type checking for
tlsSitesitems (host,cert,key) and per-keyConfig.dict[key]validation. - Persistence Atomicity (#364):
effectiveconfiguration and callbacks update only after durable persistence succeeds. - Getter Safety & Dynamic Bridge Policy (#365): Safe descriptor updates avoiding
TypeErroron getter-only properties; live evaluation ofpasswordAuthon incoming requests. - Dynamic Partial Configuration Merging (#394): Merges incoming patches over
effectivebefore applying Schemastery schema defaults. - Card Save Error Reporting (#401): Inspects HTTP status codes and API errors on settings save.
中文
0.8.27 版本修复了关键的配置生命周期、动态网桥状态同步以及客户端卡片错误报告问题 (#363, #364, #365, #394, #401):
- 嵌套 Schemastery 校验 (#363):对
tlsSites项(host、cert、key)进行严格类型检查,并通过Config.dict[key]验证所有已知字段。 - 持久化原子性 (#364):仅在底层配置持久化成功后才变更
effective配置和触发更新回调。 - Getter 安全性与动态策略即时生效 (#365):通过属性描述符安全更新状态,避免 getter 属性上的
TypeError;每次请求动态读取passwordAuth状态。 - 动态局部配置合并 (#394):在执行 Schemastery 模式前将补丁合并到
effective上,防止未修改字段回退到默认值。 - 卡片保存错误提示 (#401):保存配置时严格检查 HTTP 状态码与 API 错误信息。
Русский
В релизе 0.8.27 устранены проблемы жизненного цикла конфигурации, синхронизации живого состояния моста и отображения ошибок сохранения в карточке настроек (#363, #364, #365, #394, #401):
- Вложенная валидация Schemastery (#363): строгая проверка типов строковых полей
host,certиkeyдляtlsSitesи валидация всех распознанных полей черезConfig.dict[key]. - Атомарность персистентности (#364): эффективная конфигурация и колбэки обновляются строго после успешного сохранения в долговременное хранилище.
- Безопасность геттеров и живое обновление политики (#365): безопасное обновление состояния через дескрипторы свойств для исключения ошибок геттеров; динамическая проверка
passwordAuthна каждый запрос моста без перезапуска. - Слияние частичных патчей (#394): входящий патч объединяется с текущей эффективной конфигурацией до применения схемы, защищая настройки от сброса к значениям по умолчанию.
- Индикация ошибок сохранения в карточке (#401): разбор HTTP статусов и сообщений об ошибках при сохранении настроек для исключения ложного статуса «Сохранено».
v0.8.23
What's Changed / 更新内容 / Что изменилось
English
- Full Client Localization Dictionary Registration (#1): Registered complete 153-key dictionaries (
en,zh) viactx.locale.register(NS, { en: I18N.en, zh: I18N.zh })insidectx.effect(...)with proper disposer return. CorrectedgetLocale()to prioritize user-selected DSH interface locale (window.__DSH_LOCALE__,ctx.locale.getSnapshot(),document.documentElement.lang) over browsernavigator.language. Wired external translation fallback (env.boundT = ctx.locale.bind(NS)) enabling@goodandready/dsh-russian-langto provide Russian UI without modifying plugin source code. Injectedtinto all registered slots (LanModeCard,QuickQrPopover). - Quick QR LAN / WAN Mode Selector Switch (#49): Added interactive segmented toggle between
LANandWANmodes in the Quick QR popover (lib/client-parts/08-qr.js). Exposedtunnelstatus and public URL inhostReport(state)(/dsh-lanmode/health?format=json). Disables the WAN option with a descriptive hint when the tunnel is inactive. When active, switching to WAN updates the target URL, QR code, and copy/share actions to the Cloudflare public URL.
中文
- 完整客户端本地化词典注册 (#1):在
ctx.effect(...)中通过ctx.locale.register(NS, { en: I18N.en, zh: I18N.zh })注册完整的 153 个键值词典,并支持清理回收。修复getLocale()优先级,确保优先读取 DSH 界面语言(window.__DSH_LOCALE__、ctx.locale.getSnapshot()、document.documentElement.lang),而非浏览器默认的navigator.language。集成外部翻译器回退(env.boundT = ctx.locale.bind(NS)),使得第三方本地化插件无需修改源码即可翻译本插件。为所有插槽注入t翻译函数。 - 快速二维码 LAN / WAN 切换器 (#49):在快速二维码弹窗中新增
LAN/WAN切换药丸按钮(lib/client-parts/08-qr.js)。在健康诊断接口中输出隧道状态与公网地址(hostReport(state))。当 Cloudflare 隧道未就绪时禁用 WAN 选项并提示;隧道激活后点击 WAN 即可直接显示公网二维码、链接复制及系统分享。
Русский
- Полная регистрация словарей и приоритет локали DSH (#1): В
ctx.effect(...)зарегистрированы полные словариI18N.enиI18N.zh(все 153 ключа) черезctx.locale.register. ФункцияgetLocale()теперь строго приоритезирует язык интерфейса DSH (window.__DSH_LOCALE__,ctx.locale.getSnapshot(),document.documentElement.lang) над языком ОС/браузераnavigator.language. Подключён внешний трансляторenv.boundT = ctx.locale.bind(NS), позволяющий плагину@goodandready/dsh-russian-langпереводить UI без правок кода. - Переключатель LAN / WAN в Quick QR (#49): В поповер Quick QR добавлен сегментированный переключатель режимов LAN / WAN. Статус и адрес туннеля включены в
hostReport(state)(/dsh-lanmode/health?format=json). Если туннель не активен, кнопка WAN отключена с поясняющей подсказкой. При активном туннеле выбор WAN динамически генерирует QR-код и ссылки для Cloudflare URL.
Verification
npm test: 398 passed (0 failed).preflight.sh: FAIL=0, WARN=6.- All runtime files strictly <= 600 lines.
- Zero Cyrillic characters in runtime library.
Gitea commit: 4553f0cc443b8732409fd2471d15bd462876db2d
Mirror commit: 02ba944e7e147eb9ebfa7e0d1f5138344d443c3b
v0.8.22
What's Changed
Client PIN Challenge, Headers, QR & Live Re-auth
- Request & Header Preservation on PIN Retry (#374): Preserved all request headers (
Headersinstance, plain object, tuples, orRequest.headers) upon PIN challenge retry inlib/shim.js. ClonedRequestbefore initial dispatch preventing body consumption errors on retries. - Canonical Listener QR Descriptor & Interface Categorization (#375): Integrated canonical listener scheme and port from health and interfaces endpoints into Quick QR in
lib/client-parts/08-qr.js, formatting IPv6 addresses in brackets. Supported custommdnsNameand returned dual keys (category/typeandname/label) inlib/network-interfaces.jsandlib/bridge-local.js. - Queued Unlock Manager & Safe Cancel (#201): Centralized pending 403 authorization challenges in
_pendingOpsqueue inlib/shim.js. Submitting PIN replays all queued requests; cancelling resolves all pending promises with the original 403 response without leaving requests hanging indefinitely. - Lossless Session Expiry Handling (#240): Eliminated premature hard redirect
window.location.href = '/'on HTTP 401 inlib/shim.js. Dispatcheddsh:auth-requiredto trigger the Live Re-auth overlay, preserving user draft prompts and session context.
Verification
npm test: 391 passed (0 failed).preflight.sh: FAIL=0, WARN=6.- All runtime files strictly <= 600 lines.
- Zero Cyrillic characters in runtime library.
Gitea commit: dac97550fc04edd67bcd8eb5ec108729a4521b8c
Mirror commit: f78eea44abbe535950e5a25c894e84520ec67e34
v0.8.21 [DSH v0.2.0-rc.2]
What's Changed in v0.8.21
Updater, Lifecycle & Persistence (Audit Block 4)
- Plugin Updater Action Split (#371): Differentiated
action: 'check'andaction: 'update'inlib/plugin-updater.js. Body is securely read withreadLimitedBody. Actioncheckperforms a read-only version check without triggering package installations. Actionupdateverifies active profile lock (package.json.lock) before executinginstallExact. Returned status payload includesname: options.packageNameandcheckedAttimestamp. Successful updates returnsuccess: true. - Hardened Device Registry Persistence (#370): Preserved in-memory dirty state upon file write errors in
lib/devices.js. Rolled back in-memory nickname changes if disk flush fails. Ensuredrevoke,revokeAll, andrevokeAllExceptaccurately return boolean write status. Endpoints inlib/routes/devices.jsandlib/bridge-local.jsreturn HTTP 500 when disk persistence fails instead of false 200 OK. - Fixed
isPasswordAuth()Evaluation in Ban Route (#256): Evaluated boolean function calltypeof isPasswordAuth === 'function' ? isPasswordAuth() : Boolean(isPasswordAuth)inlib/bridge-local.jshandleBanRoute, preventing spurious 401 Unauthorized for passwordless local admins. - Named Tunnels Readiness Detection & Hostname Support (#47): Added
NAMED_READY_REGEXto detect Cloudflare named tunnel connection readiness from logs (Registered tunnel connection,Connection ... registered,Updated to new configuration) without waiting for 30s quick URL timeout. Added customhostnamesupport across constructor, routes, and state reporting. - WAN Tunnel Auto-start & Clean Disposal (#48): Added config-driven WAN tunnel startup effect in
lib/index.jswhenconfig.tunnel !== 'off', with credentials resolution and clean disposal on context unload and dynamic config updates.
Quality Gates
- Tests: 385/385 passed (0 failed).
- Preflight: FAIL=0, WARN=6.
- Zero Cyrillic: Verified across runtime code under
lib/. - File limits: Max line count is
lib/index.jsat 591 lines (strict <= 600). - Bundle size: 134.7 kB (strict <= 256 kB).
Full Changelog: v0.8.20...v0.8.21
v0.8.20 [DSH v0.2.0-rc.2]
v0.8.20 [DSH v0.2.0-rc.2]
EN
- Tunnel & Process Lifecycle:
- Fail-safe CloudflareTunnel Process Error Handling (#372): Registered default error listener on child process
EventEmitterpreventing host crashes whencloudflaredis missing (ENOENT) or fails. Addedtry/catchguard to/dsh-lanmode/tunnel/toggleroute handler returning HTTP 500 JSON without server failure. Attached tunnel logger in main plugin index. - Full HTTPS Origin Contract for Cloudflare Tunnel (#373): Enhanced
buildArgs()to supportscheme: 'https',--origin-server-name(defaults todsh.local), and--origin-ca-poolpointing to the locally generated Root CA certificate (state.caCertPath), eliminating--no-tls-verifywhile ensuring trusted loopback origin validation. - Process Lifecycle Isolation & Timeout Management (#343): Isolated event handlers (
onOutput,exit,error) to current child process instance (if (this.proc !== currentProc) return), preventing stale dying processes from corrupting subsequent tunnel instances. Guaranteedstop()cancels_startTimeout, sendsSIGTERM, and escalates toSIGKILLafter 3 seconds.
- Fail-safe CloudflareTunnel Process Error Handling (#372): Registered default error listener on child process
ZH
- 隧道与进程生命周期:
- CloudflareTunnel 进程错误安全捕获 (#372):在子进程
EventEmitter上注册默认错误监听器,防止cloudflared二进制缺失(ENOENT)或启动失败时引发宿主 Node.js 进程崩溃。在/dsh-lanmode/tunnel/toggle路由中增加try/catch保护,遇到启动异常时返回 HTTP 500 JSON,保障服务器稳定运行。在插件主入口挂载隧道错误日志。 - Cloudflare 隧道完整 HTTPS 源站契约 (#373):扩展
buildArgs()支持scheme: 'https',动态传递--origin-server-name(默认dsh.local)与指向本地 Root CA 证书(state.caCertPath)的--origin-ca-pool参数,彻底杜绝--no-tls-verify,保证本地回环来源证书的严格校验。 - 子进程生命周期隔离与超时清理 (#343):对
onOutput、exit、error等事件处理器进行当前进程实例隔离(if (this.proc !== currentProc) return),彻底解决旧进程残留事件篡改新隧道实例状态的问题。stop()调用时保证清除_startTimeout,发送SIGTERM并在 3 秒后升级至SIGKILL强行终止。
- CloudflareTunnel 进程错误安全捕获 (#372):在子进程
RU
- Туннели и жизненный цикл процессов:
- Безопасная обработка ошибок процесса CloudflareTunnel (#372): Зарегистрирован постоянный обработчик события
'error'наEventEmitter, предотвращающий аварийное завершение Node.js при отсутствии бинарникаcloudflared(ENOENT) или сбое запуска. В обработчик маршрута/dsh-lanmode/tunnel/toggleдобавленtry/catch, возвращающий HTTP 500 JSON при сбоях старта без падения сервера. Логгер туннеля подключен в главном индексе плагина. - Строгий HTTPS контракт для Cloudflare Tunnel (#373): Метод
buildArgs()расширен поддержкойscheme: 'https', передавая--origin-server-name(по умолчаниюdsh.local) и--origin-ca-poolс путем к локальному корневому CA (state.caCertPath). Флаг--no-tls-verifyполностью исключен, гарантируя строгую валидацию TLS для loopback origin. - Изоляция жизненного цикла процессов и очистка таймаутов (#343): Обработчики
onOutput,exit,errorизолированы для текущего экземпляра процесса (if (this.proc !== currentProc) return), исключая искажение состояния туннеля событиями от старых умирающих дочерних процессов. Методstop()гарантированно очищает_startTimeout, отправляетSIGTERMи эскалирует доSIGKILLчерез 3 секунды.
- Безопасная обработка ошибок процесса CloudflareTunnel (#372): Зарегистрирован постоянный обработчик события
Verification
v0.8.19 [DSH v0.2.0-rc.2]
v0.8.19 [DSH v0.2.0-rc.2]
EN
- Configuration & Live Lifecycle:
- Schema & Semantic Validation on PATCH Config (#363): Validates enums (
mode,tls,tunnel), port ranges (directPort: 1..65535), session days (authSessionDays >= 1), stream timeouts (streamTimeoutMs >= 0), strict booleans, and CIDR strings viaparseRule(). Rejects invalid payloads atomically with HTTP 400 Bad Request without mutating in-memory state. - Durable Profile Persistence via Cordis Loader (#364): Integrates
persistConfigDurable()with Cordis Loader entry tree (fiber.entry.parent.tree.write()) and fiber updates. Configuration changes are committed durably to the profile patch; failures return HTTP 500 without reporting false success. - Live Role Propagation without Listener Restart (#365): Replaced static rule closures with dynamic state getters (
getRules,getAdminRules,getGuestRules,getTrustedProxyCidrs). Runtime updates toadminAllowandguestAllowtake effect immediately on active HTTP and WebSocket surfaces without dropping connections or restarting the TCP listener. Returnsrestart: falsewhen only permissions change, andrestart: trueonly when socket binding parameters (port, host, TLS) change. - Async Credentials Resolution & Boundary Enforcement (#329): Removed direct regex reading of
~/.dsh/.credentials.yaml. MaderesolveBrowserAuthSecret(ctx)async, safely awaitingcreds.readRecord('client-connection', 'browser-session'). Declaredcredentialsas optional dependency in plugininject, loggingfailed.stackand using backoff retry upon startup errors.
- Schema & Semantic Validation on PATCH Config (#363): Validates enums (
ZH
- 配置与实时生命周期:
- PATCH 配置模式与语义校验 (#363):全面验证枚举项(
mode、tls、tunnel)、端口有效范围(directPort: 1..65535)、会话天数(authSessionDays >= 1)、流超时时间(streamTimeoutMs >= 0)、布尔型字段以及通过parseRule()校验 CIDR 规则。遇到无效配置原子化返回 HTTP 400 Bad Request,不污染或修改内存状态。 - Cordis Loader 持久化配置文件 (#364):实现
persistConfigDurable(),深入集成 Cordis Loader 条目树(fiber.entry.parent.tree.write())与 fiber 更新逻辑。配置修改安全持久化保存至 profile patch 文件;持久化失败时明确返回 HTTP 500,杜绝虚假成功提示。 - 零重启角色权限实时生效 (#365):使用动态状态获取函数(
getRules、getAdminRules、getGuestRules、getTrustedProxyCidrs)替代静态规则闭包。运行时更新adminAllow与guestAllow立即作用于所有活跃 HTTP 及 WebSocket 连接,无需中断网络连接或重启监听套接字。仅修改权限时返回restart: false,仅在端口/TLS/绑定地址等网络核心参数变动时返回restart: true。 - 异步凭证解析与架构边界隔离 (#329):彻底移除直接读取
~/.dsh/.credentials.yaml文件的正则表达式解析逻辑。将resolveBrowserAuthSecret(ctx)改造为异步调用,安全等待creds.readRecord('client-connection', 'browser-session')。在插件inject中将credentials服务声明为可选依赖,捕获并记录failed.stack堆栈,启动失败时执行指数退避重试。
- PATCH 配置模式与语义校验 (#363):全面验证枚举项(
RU
- Конфигурация и живой жизненный цикл:
- Схемная и семантическая валидация PATCH Config (#363): Проверка enum-значений (
mode,tls,tunnel), диапазонов портов (directPort: 1..65535), срока сессий (authSessionDays >= 1), таймаута потоков (streamTimeoutMs >= 0), строгих boolean-флагов и корректности CIDR-подсетей черезparseRule(). Любые некорректные данные атомарно отклоняются с HTTP 400 Bad Request без мутации состояния в памяти. - Долговременное сохранение профиля через Cordis Loader (#364): Реализована функция
persistConfigDurable()с интеграцией в дерево Cordis Loader (fiber.entry.parent.tree.write()) и fiber updates. Изменения гарантированно сохраняются на диск в patch профиля; ошибки записи возвращают HTTP 500 без ложного отчёта об успехе. - Динамическое применение ролей без перезапуска слушателя (#365): Статические замыкания правил заменены на динамические геттеры состояния (
getRules,getAdminRules,getGuestRules,getTrustedProxyCidrs). ИзмененияadminAllowиguestAllowнемедленно вступают в силу для HTTP-запросов и WebSocket-соединений без разрыва сессий и без перезапуска TCP-сокета. Ответ API возвращаетrestart: falseпри смене прав иrestart: trueтолько при смене сетевых параметров привязки (порт, хост, TLS). - Асинхронное получение секрета сессии и опциональный inject credentials (#329): Полностью удалено чтение файла
~/.dsh/.credentials.yamlнапрямую регулярным выражением.resolveBrowserAuthSecret(ctx)переведена в асинхронный режим с корректным вызовомawait creds.readRecord('client-connection', 'browser-session'). Зависимостьcredentialsобъявлена опциональной вinject, логируется стек ошибок и применяется backoff при сбоях старта.
- Схемная и семантическая валидация PATCH Config (#363): Проверка enum-значений (
Verification
v0.8.18 [DSH v0.2.0-rc.1]
v0.8.18 [DSH v0.2.0-rc.1]
EN
- Security & Hardening:
- Resolved ReferenceError in raiseListener when accessing TLS certificate and key paths in files mode.
- Enforced fail-closed guard preventing listener raise when binding 0.0.0.0 without an allow list or password authentication.
- Safe credential reference resolution with fallback to empty value on unresolved refs and TTL caching.
- Prevented masked '***' passwords in the settings card from overwriting stored secrets during configuration PATCH.
- Enforced LAN PIN verification and attempt rate-limiting on state-mutating configuration requests.
- Enforced ban list, guest role restrictions, LAN PIN, and origin validation during WebSocket upgrades.
- Restricted inclusion of core harness authentication tokens in /dsh-lanmode/qr to authenticated admin sessions and loopback clients.
- Blocked non-loopback callers from accessing /auth/bootstrap through the bridge with 403 Forbidden.
- Stored SHA-256 digests of device authentication tokens with 0o600 file permissions instead of plaintext tokens.
- Immediately terminated active WebSocket duplex streams upon session or device revocation.
- Protected device revocation records from LRU eviction under device registry limit pressure.
ZH
- 安全与加固:
- 修复 files 模式下在 raiseListener 中读取 TLS 证书和密钥路径时的 ReferenceError。
- 强化 fail-closed 防护机制:未配置允许列表或密码认证时禁止监听 0.0.0.0。
- 安全凭证引用解析:未解析凭证安全回退至空值,增加 TTL 缓存。
- 设置面板防覆盖:在配置 PATCH 时忽略 '***' 密码掩码,防止覆盖已存储密钥。
- 保护配置接口:对修改状态的配置请求强制执行 LAN PIN 验证及重试限制。
- WebSocket 升级安全网关:在 HTTP Upgrade 阶段强制校验黑名单、访客权限、LAN PIN 及 Origin。
- 二维码核心令牌防护:仅允许已认证管理员会话或环回接口获取 /dsh-lanmode/qr 中的核心访问令牌。
- 阻止外部访问引导端点:外部调用者通过网桥访问 /auth/bootstrap 时返回 403 Forbidden。
- 设备令牌安全存储:以 SHA-256 哈希及 0o600 文件权限持久化设备令牌。
- 会话注销即时断开:撤销会话或设备时立即强制断开所有相关的活跃 WebSocket 连接。
- 防淘汰撤销记录:将设备撤销记录隔离于永久集合中,不受 200 台设备 LRU 淘汰机制影响。
RU
- Безопасность и ужесточение доступа:
- Устранён сбой ReferenceError в raiseListener при загрузке путей к TLS сертификату и ключу в режиме files.
- Задействован fail-closed guard: запрещён запуск слушателя на 0.0.0.0 без заданного списка allow или парольной аутентификации.
- Безопасное разрешение ссылок на секреты: неразрешённые ref возвращают fallback/пустоту вместо сырых ключей, добавлен TTL кэша.
- Защита паролей в настройках: маски '***' игнорируются при PATCH /dsh-lanmode/api/config, предотвращая затирание паролей.
- Защита конфигурации LAN PIN: мутирующие вызовы защищены обязательной валидацией PIN с защитой от перебора.
- Контроль WebSocket upgrade: на этапе Upgrade проверяются черный список, роль гостя, LAN PIN, unlockPrivileged и Origin.
- Защита токена в QR: включение токена ядра в /dsh-lanmode/qr разрешено только авторизованным сессиям админа и loopback.
- Блокировка внешнего bootstrap: обращения к /auth/bootstrap через внешний сетевой мост отклоняются с кодом 403 Forbidden.
- SHA-256 хэширование в DeviceRegistry: токены устройств сохраняются на диске в виде хэшей с правами доступа 0o600.
- Принудительный сброс сокетов: отзыв сессии или устройства немедленно разрывает связанные активные WebSocket-сессии.
- Постоянное хранение отзывов: записи об отозванных токенах не вытесняются при достижении лимита в 200 устройств.