fix: harden browser file picker and remove legacy
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
# Вопросы и ответы по ревью Gemini 3.8 Flash — 2026-09-05
|
||||
|
||||
## Контекст
|
||||
|
||||
После критического разбора ревью Gemini 3.8 Flash были заданы уточняющие
|
||||
вопросы по версии исходников, дублированию API, семантике `File.name`, legacy
|
||||
XSS, `build.mjs`, ZIP-фильтрации и приоритетам исправлений.
|
||||
|
||||
## Зафиксированные ответы
|
||||
|
||||
### Версия кода и номера строк
|
||||
|
||||
Ревью выполнялось по исходникам `upload-platform`; `dist/` отдельно не
|
||||
исследовался. Номера строк в первой сводке были смещены из-за объединения
|
||||
отчётов субагента. Фактические участки находятся в текущих исходниках
|
||||
`on_files_change.js` и `list_zip_files.js`.
|
||||
|
||||
### `init_upload_table.js`
|
||||
|
||||
Буквального совпадения интерфейса с `initFilePicker` нет: один entry point
|
||||
принимает готовые DOM-узлы, другой создаёт DOM внутри `mount`. Однако внутренняя
|
||||
логика жизненного цикла таблицы параллельна: состояние `nodes/fileKeys/busy`,
|
||||
удаление узлов, делегирование кликов и похожий API. Файл не входит в граф сборки
|
||||
`build.mjs`, поэтому это legacy-альтернатива, создающая риск рассинхронизации.
|
||||
|
||||
### `File.name` и логический путь
|
||||
|
||||
`flattenFiles()` возвращает `name`, `path` и `file` раздельно, но при `rebaseTree`
|
||||
вложенный browser `File` получает полный путь в `file.name`. При прямом
|
||||
`FormData.append('files', file)` сервер получает filename с разделителями пути.
|
||||
Это может конфликтовать с серверными `basename`/`secure_filename` и нарушает
|
||||
обычный контракт browser `File`, где `name` является базовым именем. При явной
|
||||
передаче третьего аргумента `FormData.append('files', file, path)` проблема не
|
||||
возникает.
|
||||
|
||||
### XSS в `set_status.js`
|
||||
|
||||
Замечание относится только к legacy-файлу. `set_status.js` не входит в активный
|
||||
граф сборки и не используется боевым рендерером. В активном `render.js` значения
|
||||
статуса экранируются через `esc()`. Реальная уязвимость в текущем активном
|
||||
рендеринге не подтверждена; пункт относится к гигиене мёртвого кода.
|
||||
|
||||
### `build.mjs`
|
||||
|
||||
Для top-level `await` необработанная ошибка сборки сама приводит Node.js к
|
||||
завершению с ненулевым кодом. Явные `try/catch` и `process.exit(1)` технически
|
||||
избыточны. Реальное возможное улучшение этого пункта — определить поведение
|
||||
каталога `dist/` перед сборкой, например его предварительную очистку.
|
||||
|
||||
### Проверка фильтра `fflate`
|
||||
|
||||
Проверка исходника `fflate` подтвердила, что `filter` вызывается после чтения
|
||||
метаданных ZIP entry, но до копирования или декомпрессии данных. Если фильтр
|
||||
возвращает `false`, `inflateSync` для этой записи не вызывается и буфер для
|
||||
распакованных данных не создаётся. Поэтому добавление проверки расширения в
|
||||
`filter` является корректным способом не распаковывать тяжёлые неразрешённые
|
||||
entries.
|
||||
|
||||
### Приоритет до прода
|
||||
|
||||
Согласован обязательный приоритет:
|
||||
|
||||
1. **№2:** отбрасывать неразрешённые расширения внутри ZIP `filter` до
|
||||
декомпрессии, чтобы снизить риск OOM и лишнего расхода бюджета.
|
||||
2. **№1:** сбрасывать `elements.fileInputEl.value`, чтобы повторный выбор того
|
||||
же файла после удаления снова генерировал `change`.
|
||||
3. **№5:** объединять корневые папки с одинаковыми путями, чтобы избежать
|
||||
дублирующихся деревьев при последовательном выборе.
|
||||
|
||||
Пункты `File.name`, `onError`, fallback-конфигурация, legacy-код и очистка
|
||||
служебных каталогов отнесены ко второй очереди.
|
||||
|
||||
## Итог
|
||||
|
||||
Уточнение подтвердило, что главным техническим finding является ZIP-фильтрация
|
||||
до декомпрессии. Пункты про `set_status.js` и явный `process.exit(1)` не являются
|
||||
активными production-дефектами. Исправления кода в рамках этой записи не
|
||||
выполнялись.
|
||||
Reference in New Issue
Block a user