Files
admin/webconfig-password-xml-escape.md
vitya 2d307f2dd0 docs(.wiki): iis-migration rollback + post-mortem + xml-escape concept
Phase 9 — rollback миграции на host-IIS из-за Docker port-loop
(host.docker.internal:80 от traefik container резолвится обратно
в сам traefik через NAT, https.yml http-catchall middleware
отдавал 301 -> TOO_MANY_REDIRECTS). Prod снова через VM.

- iis-migration-2026-05-19-postmortem: 10 ошибок миграции +
  recipe для следующей попытки (backend port НЕ :80, smoke с
  MaximumRedirection 0, тест из НЕ-LAN, parallel VM x N часов,
  atomic revert plan)
- webconfig-password-xml-escape: новая gotcha — & в conn-string
  пароле требует & в Web.config (XML reserved char)
- iis-host-migration-2026-05-19: Phase 9 rollback chronology +
  что осталось на хосте inert
- snolla-recovery-vm: статус -> active prod (обратно)
- windows-recovery-host: host IIS sites -> inert artifacts
- recovery-architecture-snapshot: chain снова через VM,
  traefik backends восстановлены из .bak-phase3

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:08:07 +03:00

4.1 KiB
Raw Blame History

title, type, tags, sources, updated
title type tags sources updated
Web.config — XML escape для спецсимволов в connection-string паролях concept
iis
webconfig
encoding
xml
gotcha
../sources/iis-host-migration-2026-05-19.md
2026-05-19

Web.config: XML-escape для & (и других reserved chars) в пароле

Симптом

После patch Web.config с новым connection-string'ом ASP.NET-сайт отдаёт HTTP 500 на любой запрос. В Event Viewer / IIS logs — System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize или Unrecognized escape sequence. На уровне XML парсера — error при чтении Web.config.

Корень

Web.config — это XML-документ. Атрибуты в нём (<add connectionString="..." />) проходят через XML-парсер до того, как .NET runtime увидит сам connection string. Если в пароле есть XML-зарезервированный символ, парсер ломается.

XML reserved chars (в значениях атрибутов):

Символ XML-entity escape Когда обязателен
& &amp; всегда (в attribute value и в text content)
< &lt; всегда
" &quot; если значение в "..." (наш кейс — атрибуты обычно в двойных кавычках)
' &apos; если значение в '...'
> &gt; формально не обязателен, но safer

В именно нашем кейсе из iis-host-migration-2026-05-19: пароль ^I9D)LB)DK)8J#xBDG$t}W&_ioaT!M!LF содержит & — XML-парсер начинал интерпретировать &_ioaT... как entity reference (&_ioaT; — невалидное имя entity) → exception → IIS 500.

Правильный способ

<!-- WRONG (literal &) -->
<add name="MoreThenCmsEntities"
     connectionString="...Password=^I9D)LB)DK)8J#xBDG$t}W&_ioaT!M!LF;..."
     providerName="System.Data.SqlClient" />

<!-- RIGHT (& -> &amp;) -->
<add name="MoreThenCmsEntities"
     connectionString="...Password=^I9D)LB)DK)8J#xBDG$t}W&amp;_ioaT!M!LF;..."
     providerName="System.Data.SqlClient" />

После XML-парсинга .NET runtime получит литеральный & в значении атрибута и передаст в SqlConnection — там пароль уже текст, всё ок.

Что НЕ требует escape

  • ^, $, (, ), {, }, [, ], *, +, ?, \, /, ., ,, ;, :, =, #, @, %, !, ~, | — все безопасны в XML attribute value.
  • Особое: ; в пароле в ADO.NET conn-string'е требует обёртки пароля в '...' или "..." внутри connection-string'а — но это отдельная история.

PowerShell-подсказка для patch

При программной замене conn-string'асразу escape & в значение, не оставляй на потом:

# 💻 Windows host
$plainPassword = '^I9D)LB)DK)8J#xBDG$t}W&_ioaT!M!LF'
$xmlSafePassword = $plainPassword -replace '&', '&amp;'
# и потом подставлять $xmlSafePassword в Web.config

# или комбинированный escape всех 5 reserved chars:
function Xml-EscapeAttr($s) {
    $s -replace '&','&amp;' -replace '<','&lt;' -replace '>','&gt;' -replace '"','&quot;' -replace "'",'&apos;'
}

Связанные паттерны

  • cms-config-rewrite-pattern — UTF-8 BOM ловушка при Set-Content без -Encoding utf8 (другая XML/IIS гнойная тема).
  • При генерации паролей для DB-логинов CMS — лучше запретить &, <, " в генераторе, чтобы не словить эту проблему в будущем (особенно при автоматизированных patches Web.config через CI).