Перейти до основного вмісту
OpenAI

13 травня 2026 р.

ІнженеріяЗахист

Створення безпечного й ефективного ізольованого середовища для запуску Codex у Windows

Автор: Девід Візен, член технічної команди

Завантаження…

Коли я приєднався до інженерної команди Codex у вересні 2025 року, у Codex для Windows не було реалізації ізольованого середовища, а це означало, що користувачі Windows були змушені обирати між двома невдалими варіантами під час використання агентів OpenAI для програмування:

  1. Погоджувати майже кожну команду, яку агент для програмування хотів виконати (навіть читання), що неефективно й виснажливо. Одна з головних переваг використання Codex полягає в тому, що вам не доведеться виконувати всю виснажливу рутинну роботу самостійно.
  2. Увімкнення режиму повного доступу: Codex може виконувати будь-які команди без погодження чи обмежень, що зменшує кількість зайвих дій, але водночас послаблює контроль.

Codex, наш агент для програмування, працює на ноутбуках розробників — чи то через CLI, розширення IDE, чи настільний застосунок. Він підтримує взаємодію між людиною за клавіатурою та моделлю, що працює в хмарі й виконує інференс.

За замовчуванням Codex працює з дозволами реального користувача, тобто може робити все, що може робити користувач. Це потужно й потенційно небезпечно. Модель для програмування може доручати середовищу виконання запуск локальних команд — від запуску тестів до читання чи редагування файла або створення гілки Git, — тому режим Codex за замовчуванням намагається знайти правильний баланс між ефективністю та безпекою. Цей режим за замовчуванням дозволяє Codex читати файли майже будь-де й записувати файли у вашому робочому просторі (тобто в каталозі, де ви запускаєте Codex), без доступу до інтернету, якщо тільки ви самі не вкажете, що він потрібен. Щоб автоматично обмежувати запис файлів і доступ до мережі в безпечних межах, Codex потребує ізольованого середовища, яке справді забезпечує дотримання цих обмежень.

Ізольоване середовище — це середовище виконання з обмеженнями. Коли розробник використовує Codex, операційна система його комп’ютера запускає команду зі зменшеними дозволами, і ці обмеження поширюються вниз по дереву процесів. Кожна команда Codex із самого початку виконується в ізольованому середовищі, а кожен дочірній процес залишається в тих самих межах.

Діаграма, що показує межі ізоляції ізольованого середовища Codex на рівні операційної системи.

Щоб реалізувати ефективне ізольоване середовище, Codex потребує функцій ізоляції, які забезпечує операційна система комп’ютера. Деякі операційні системи надають утиліти, що добре це роблять (наприклад, Seatbelt у MacOs, seccomp або bubblewrap у Linux); однак Windows наразі не надає таких можливостей за замовчуванням.

Щоб зробити Codex таким самим безпечним і приємним у використанні на Windows, як і всюди інде, нам потрібно було реалізувати власне ізольоване середовище.

Де наявні інструменти Windows не впоралися

Windows пропонує певні інструменти й базові механізми для ізоляції. Хоча жоден із них повністю не відповідав нашим вимогам, ми розглянули низку потенційних рішень — а саме AppContainer, Windows Sandbox і мітки Mandatory Integrity Control.

AppContainer

  • Що це: AppContainer — це вбудоване середовище Windows, модель ізоляції на основі можливостей, створена для застосунків, які заздалегідь точно знають, до яких ресурсів їм потрібен доступ.
  • Чому: Привабливий варіант, бо пропонує справжню межу ОС замість часткових або неповних обмежень.
  • Чому ні: Codex — це не один вузькоспеціалізований застосунок. Він керує відкритими робочими процесами розробника: оболонками, Git, Python, менеджерами пакетів, інструментами збірки та будь-якими іншими бінарними файлами, які агент вирішить, що йому потрібні. На практиці це означало, що AppContainer не підходив для цієї задачі. Це була сильна ізоляція, але для значно вужчого класу навантажень, ніж «дати агенту працювати як розробник».

Windows Sandbox

  • Що це: Windows Sandbox — це легка тимчасова VM від Microsoft. Ви отримуєте чисте середовище Windows із надійною ізоляцією, і все, що ви робите всередині, зникає після завершення сеансу.
  • Чому: Цікавий варіант з очевидних причин — значно сумісніший із довільним програмним забезпеченням, ніж AppContainer, і з погляду безпеки це набагато сильніша ізоляція.
  • Чому ні: Codex має діяти безпосередньо з реальною робочою копією репозиторію користувача, інструментами та середовищем користувача, а не всередині окремого тимчасового робочого стола, який потребував би налаштування та зв’язку між хостом і гостем. Була й фундаментальна продуктова проблема: Windows Sandbox узагалі недоступний у версіях Windows Home.

Мітки цілісності Mandatory Integrity Control (MIC)

  • Що це: У Windows є поняття «рівнів цілісності», як-от low, medium і high, які визначають, наскільки система довіряє об’єктам і процесам. Базове правило полягає в тому, що процес із нижчим рівнем цілісності не може записувати в об’єкт із вищим рівнем цілісності, навіть якщо звичайний ACL інакше це дозволяв би. Наприклад, процес із низьким рівнем цілісності вважається менш довіреним, тому Windows блокує йому запис у звичайні об’єкти з середнім рівнем цілісності, якщо тільки ці об’єкти явно не перемарковано, щоб це дозволити.
  • Чому: На папері MIC виглядав елегантно — запустити Codex з низьким рівнем цілісності, позначити кореневі каталоги для запису як об’єкти з низьким рівнем цілісності і дозволити Windows заборонити запис деінде. Це дало б нам спосіб роботи без прав адміністратора з реальним механізмом ОС.
  • Чому ні: Як і ACL, мітки цілісності змінюють реальну файлову систему хоста, і в цьому разі семантична зміна особливо широка. Призначення робочому простору низького рівня цілісності означає не лише «Codex може тут записувати». Це означає, що запис у цей каталог отримують процеси з низьким рівнем цілісності загалом. На реальній машині розробника це перетворює фактичну робочу копію репозиторію користувача на точку запису для процесів із низьким рівнем цілісності для хоста, що набагато ризикованіше, ніж надавати ретельно націлені ACL одній конструкції ізольованого середовища. Навіть якщо інструменти розробника із середнім рівнем цілісності і далі працюватимуть, базова модель довіри до робочого простору змінюється так, що це важко локалізувати й ще важче виправдати.

Оцінивши всі ці варіанти як непридатні, ми почали проєктувати власне рішення, щоб забезпечити хороший досвід використання Codex для користувачів Windows.

Перший прототип: ізольоване середовище без підвищених привілеїв

Наш перший робочий прототип використовував поєднання концепцій та інструментів Windows, щоб реалізувати потрібну нам ізоляцію. Від самого початку однією з цілей було змусити це працювати без потреби в підвищенні привілеїв, тобто Codex не мав би запитувати в користувача права адміністратора лише для налаштування чи запуску ізольованого середовища. Це означало, що треба було знайти спосіб розумно обмежити дві речі: запис файлів і доступ до мережі.

Обмеження запису файлів

Якби ми зовсім не обмежували запис файлів, виникла б проблема безпеки. Якби ми обмежили запис надто сильно, ізольоване середовище шкодило б продуктивності користувача, постійно вимагаючи підтверджень. Щоб розв’язати цю проблему, ми спиралися на два важливі будівельні блоки Windows: SID і токени з обмеженням запису.

SID дають змогу надати ізольованому середовищу ідентичність

SID, або ідентифікатор безпеки, — це ідентифікатор, до якої Windows прив’язує дозволи. Кожен користувач має SID, групи мають SID, і навіть окремий сеанс входу має власний SID. Наприклад, поточний активний сеанс може мати SID на кшталт S-1-5-5-X-Y. SID, призначений локальній групі адміністраторів, може бути S-1-5-32-544.

Windows також дозволяє створювати синтетичні SID, які не відповідають реальному користувачу, але все одно можуть з’являтися в ACL (списках керування доступом), що визначають, хто може читати/записувати/виконувати конкретні файли чи каталоги. Це робить SID корисним базовим механізмом для нашого ізольованого середовища: ми можемо створювати SID виключно для ізольованого середовища Codex, не заважаючи нічому іншому на машині.

Токени з обмеженням запису обмежують місця, де Codex може змінювати файли

Токени процесів — це об’єкти безпеки в Windows, які визначають ідентичність і привілеї запущеного процесу. Вони визначають, які дії процес може виконувати. Токен з обмеженням запису — це особливий тип токена процесу, який змушує Windows виконувати додаткову перевірку доступу під час операцій запису.

Щоб запис був успішним, мають пройти дві перевірки:

  1. Звичайній ідентичності користувача (власнику токена) це має бути дозволено
  2. Принаймні одному SID зі списку обмежених SID у токені також має бути надано доступ
Діаграма під назвою «Для запису в ізольованому середовищі потрібен і звичайний доступ користувача, і доступ SID sandbox-write».

На практиці ці перевірки дали нам змогу використовувати ACL для точного визначення того, де пісочниця може змінювати файлову систему, а це забезпечило потрібну нам гранулярність для операцій запису.

Завдяки SID і токенам з обмеженням запису наше ізольоване середовище без підвищених привілеїв працювало так:

  1. Під час налаштування ізольованого середовища створювався синтетичний SID із назвою sandbox-write.
  2. SID sandbox-write було надано доступ із правами запису, виконання та видалення для
    1. Поточний робочий каталог
    2. Будь-які додаткові writable_roots, налаштовані у config.toml.
  3. Під час налаштування ізольованого середовища цьому самому SID явно заборонявся доступ на запис до місць «лише для читання всередині дозволених для запису», як-от:
    1. <cwd>/.git
    2. <cwd>/.codex
    3. <cwd>/.agents
  4. Codex запускав команди під токеном з обмеженням запису, список обмежених SID якого містив «Всі», SID поточного сеансу входу та синтетичний SID sandbox-write.

Цей потік ефективно розв’язав проблему обмеження запису файлів і виглядав перспективно. Тепер нам було потрібне рішення для обмеження мережевого доступу ізольованого середовища.

Обмеження мережевого доступу

Обмеження мережевого доступу — важлива частина ізольованого середовища; без нього шкідливий код міг би виводити дані з комп’ютера в інтернет. Оскільки ми хотіли уникнути вимоги щодо підвищених привілеїв, у нас було мало варіантів для надійного блокування мережевого трафіку. Інструменти, які ми хотіли використати, як-от Windows Firewall, зазвичай не можна було встановити без прав адміністратора.

Без Windows Firewall наш контроль був обмежений. Ми намагалися зробити так, щоб дочірнє середовище відмовляло за замовчуванням для типових мережевих інструментів, якими реально користуються розробники, щоб команди Git, інсталятори пакетів тощо в ізольованому середовищі завершувалися помилкою, а користувач мав би підтверджувати будь-які операції з виходом в інтернет. Ідея полягала в тому, щоб «отруїти» очевидні шляхи обходу: спрямовувати proxy-aware трафік на недоступну кінцеву точку, змусити HTTP(S)-транспорт Git робити те саме, а Git через SSH — негайно завершуватися помилкою. Додатково ми підставляли на початок PATH невеликий каталог denybin і змінювали порядок PATHEXT, щоб stub-скрипти SSH і SCP знаходилися раніше за реальні бінарні файли.

Наприклад, ось деякі з конкретних перевизначень середовища, які ми використовували для обмеження мережевого доступу:

  • HTTPS_PROXY=http://127.0.0.1:9
  • ALL_PROXY=http://127.0.0.1:9
  • GIT_HTTPS_PROXY=http://127.0.0.1:9
  • NO_PROXY=localhost,127.0.0.1,::1
  • GIT_SSH_COMMAND=cmd /c exit 1
Діаграма, що показує архітектуру ізольованого середовища із підвищеними привілеями з правилами брандмауера та окремим користувачем Windows.

Це перехоплювало багато звичайного трафіку, ініційованого інструментами, але все одно було лише рекомендаційним механізмом. Процес міг проігнорувати середовище, обійти PATH або просто відкривати сокети безпосередньо — занадто ризиковано.

Підхід без підвищених привілеїв мав компроміси

Як і в будь-якій цікавій програмній реалізації, перший прототип мав свої плюси й мінуси. Хоча він вирішував задачу за допомогою лише кількох стандартних можливостей Windows, дозволяв дуже явно й гранулярно контролювати записи у файловій системі та працював без підвищених привілеїв — позбавляючи користувачів потреби погоджувати надмірну кількість запитів на підвищення прав або бути адміністраторами на своїй локальній машині, — він мав певні суттєві недоліки, деякі з яких позбавили його можливості стати нашим остаточним проєктом:

  • Швидкість налаштування: застосування ACL до робочого простору може бути дорогим залежно від топології каталогу робочого простору.
  • Слід у системі: ми застосовували реальні ACL у системі розробника, хоча цей слід не є особливо нав’язливим, оскільки всі застосовані ACL стосуються спеціально створеного синтетичного SID, який використовує лише ізольоване середовище.
  • Складна для зміни семантика: залежність від ACL для файлових обмежень означає, що змінювати семантику ізольованого середовища дорого й складно. У macOS ми можемо динамічно змінювати спосіб генерації файла .sbpl, що використовується для налаштування Seatbelt, тоді ж як у Windows-середовищі для зміни ACL може знадобитися повільна й ресурсоємна операція.
  • Мережевий захист слабкий. Як уже згадувалося, він був «рекомендаційним»: деякі програми, що реалізовували власний мережевий стек, точно обходили б його, і він не був призначений для протидії ворожому коду.

Перші три проблеми притаманні кастомній реалізації ізольованого середовища, достатньо гнучкій для агентних сценаріїв. Історія з обмеженням доступу до мережі, однак, була іншою.

Контроль мережевого доступу є критично важливим

Окрім того, що зловмисний агент міг легко обійти обмеження мережевого доступу на основі змінних середовища, чимало коду/бінарних файлів із безпечними намірами також обходили б його просто тому, що не враховували proxy-змінні середовища або реалізовували власний мережевий код на сокетах. Ми відчули, що цього аспекту вже достатньо, щоб інвестувати в кращий режим ізольованого середовища.

Щоб отримати краще обмеження мережевого доступу, ми хотіли використати Windows Firewall, який дозволяє блокувати вихідний мережевий трафік для користувачів або програм. На жаль, ми не могли ефективно створити робоче правило брандмауера, яке застосовувалося б лише до команд, запущених через середовище виконання Codex, з кількох причин:

  • Windows не дозволяє застосовувати правила брандмауера до непринципальної ідентичності обмеженого токена. Це означає, що ми не могли застосувати правило брандмауера до «будь-якого токена, який містить наш синтетичний SID у списку обмежених SID».
  • Хоча ми могли створити правило брандмауера, яке зіставляється з конкретним бінарним файлом, це дозволяло обмежувати мережу лише для самого codex.exe. Воно не поширювалося б на процеси, які агент запускає від імені користувача, як-от процеси Git чи Python.
  • Інші виміри зіставлення правил брандмауера також не підходили. Правила з областю дії користувача в дизайні без підвищення привілеїв усе одно збігалися з реальним користувачем Windows, а не лише з обмеженим дочірнім процесом. Правила за шляхом до програми були надто грубими: вони могли блокувати codex.exe або python.exe загалом, але не саме цей один запуск python.exe у ізольованому середовищі. Правила на основі портів або адрес теж реалізовували зовсім не ту політику. Наприклад, ми не хотіли блокувати порт 443; ми хотіли блокувати довільний вихідний доступ саме для цього конкретного дерева обмежених процесів.

Щоб застосувати правило брандмауера саме до наших команд у ізольованому середовищі, нам потрібно було запускати їх як окремий суб’єкт безпеки, а не як «реального» користувача. Цей підхід привів нас на новий шлях, де ми послабили наше обмеження без підвищення привілеїв.

Перероблена архітектура: ізольоване середовище з підвищеними привілеями

Наступна ітерація ізольованого середовища, яка є нашою поточною реалізацією, вимагає підвищених прав адміністратора на етапі налаштування. Тому я називаю її ізольованим середовищем з підвищеними привілеями. На межі, де Codex запускає команду в системі, ізольоване середовище з підвищеними привілеями виглядає як варіант без підвищених привілеїв. Воно все ще запускає дочірні процеси під обмеженим токеном — подібним токеном write_restricted із тим самим списком обмежених SID [Everyone, Logon, Synthetic], — однак суб’єктом безпеки цього токена тепер є уже не фактичний користувач Windows, а один із двох локальних користувачів, яких створює сам Codex:

  • CodexSandboxOffline (користувач, для якого діють правила брандмауера)
  • CodexSandboxOnline (користувач, для якого не діють правила брандмауера)

Ця на перший погляд невелика деталь насправді має великі наслідки для ізольованого середовища, того, хто може нею користуватися, і складності її налаштування та виконання під час роботи.

Діаграма, що показує перевизначення мережевого середовища для ізольованого середовища без підвищених привілеїв.

Візуально це схоже на прототип без підвищених привілеїв, але з додаванням правил брандмауера та виділеного користувача Windows, який фактично й запускає команди. (Однак поява цих нових концепцій означає, що перед тим, як ізольоване середовище зможе запускати й захищати команди, потрібно виконати більше підготовчої роботи.)

Тепер нам потрібен повноцінний окремий крок налаштування

У дизайні без підвищених привілеїв крок налаштування був простим, але відносно невеликим:

  • Створити синтетичний SID за потреби
  • Застосувати ACL для синтетичного SID sandbox-write

Однак ізольоване середовище з підвищеними привілеями має більше роботи.

  • Створити синтетичний SID, якщо його ще не створено
  • Створити онлайн- і офлайн-користувачів ізольованого середовища, якщо їх ще не створено
  • Локально зберегти облікові дані новостворених користувачів і зашифрувати їх за допомогою Windows Data Protection API (DPAPI) у місці, яке користувачі ізольованого середовища фактично не можуть читати
  • Створити правила брандмауера, що блокують увесь вихідний мережевий доступ для користувача CodexSandboxOffline, або, якщо вони вже існують, перевірити, що вони коректні

На етапі налаштування є ще один нюанс. Очікується, що ізольоване середовище Codex матиме доступ на читання, еквівалентний доступу фактичного користувача Windows. В ізольованому середовищі без підвищених привілеїв, де суб’єктом безпеки SID обмеженого токена був користувач Windows, це забезпечувалося. Однак коли суб’єктом безпеки стає новим користувачем CodexSandbox, це вже не працює автоматично. Багато важливих каталогів у Windows надають дозволи на читання/виконання для групи «Автентифіковані користувачі». Один помітний приклад — каталог профілю користувача. За замовчуванням користувачі Windows не можуть читати каталоги профілів інших користувачів Windows, тому в багатьох сценаріях навіть просте читання файлів завершувалося б помилкою.

Щоб це виправити, ми додали ще один рівень до процесу налаштування ізольованого середовища — для надання ACL на читання користувачам ізольованого середовища там, де таких дозволів може ще не бути. Наприклад, для деяких поширених каталогів Windows:

  • C:\Users\<real-user>
  • C:\Windows\
  • C:\Program Files\
  • C:\Program Files (x86)\
  • C:\ProgramData\

Оскільки цей список каталогів не є вичерпним, а застосування ACL для кожного з них може потребувати значних ресурсів, ми запускаємо цей процес асинхронно, щоб крок налаштування ізольованого середовища, який блокує користувачів, не мусив чекати завершення всіх операцій.

Ми винесли логіку налаштування в окремий бінарний файл частково для того, щоб перетинати межу UAC лише за потреби. Але глибша причина була архітектурною: налаштування ізольованого середовища має принципово іншу задачу, ніж codex.exe. Виділення логіки налаштування ізольованого середовища в окремий бінарний файл дозволило codex.exe залишатися звичайним керуючим процесом без підвищених привілеїв; уникнути перевантаження codex.exe Windows-специфічною логікою налаштування на інших платформах; відокремити довготривалі процеси налаштування від життєвого циклу головного процесу; а також централізувати всі різні сценарії налаштування ізольованого середовища в одному місці.

Діаграма, що показує крок налаштування ізольованого середовища з підвищеними привілеями.

Виконавець команд — це новий бінарний файл, який фактично запускає команди користувача

Через те, як у Windows працюють межі входу користувачів та токенів, ми вже не могли й далі створювати обмежений токен і запускати під ним процес так, як могли в ізольованому середовищі без підвищених привілеїв. Щоб реально запускати команди від імені іншого користувача Windows, нашою першою ідеєю був такий підхід:

  • codex.exe запускається від імені реального користувача Windows. Далі Codex послідовно:
    • Викликає LogonUserW(...) для користувача ізольованого середовища.
    • Викликає CreateRestrictedToken(...) для цього токена користувача ізольованого середовища.
    • Використовуючи той обмежений токен користувача ізольованого середовища, викликає CreateProcessAsUserW(...) для запуску кінцевого дочірнього процесу.

На практиці цей сценарій не спрацював через обмеження привілеїв на рівні CreateProcessAsUserW(...). Це означає, що codex.exe міг створити обмежений токен для користувача ізольованого середовища, але не міг надійно запустити дочірній процес із цим токеном з боку реального користувача. Нам був потрібен процес, який уже працював би від імені користувача ізольованого середовища — це дозволило б виконати крок обмеження та фінальний запуск на боці користувача ізольованого середовища, а не на боці реального користувача.

Ця вимога привела до створення codex-command-runner.exe, нового бінарного файла, єдина задача якого полягає в тому, щоб створити обмежений токен і запустити потрібну команду. Замість того щоб змушувати codex.exe виконувати весь ланцюг самостійно (реальний користувач → користувач ізольованого середовища → обмежений токен → дочірній процес), ми розділили його на дві частини:

Частина 1

  • codex.exe викликає CreateProcessWithLogonW(...), щоб запустити codex-command-runner.exe від імені користувача ізольованого середовища, поки що без використання обмеженого токена.

Частина 2

  • Усередині runner виклик OpenProcessToken(GetCurrentProcess(), ...) відкриває власний токен процесу runner, який уже належить користувачу ізольованого середовища.
  • Runner викликає GetTokenInformation(...), щоб отримати logon SID ізольованого середовища, а потім CreateRestrictedToken(...) для створення фінального обмеженого токена.
  • Все ще всередині runner він викликає CreateProcessAsUserW(...) із цим обмеженим токеном, щоб запустити реальний дочірній процес.
Діаграма, що показує процес command runner для запуску команд з обмеженим токеном.

Повна картина

Альберт Ейнштейн сказав: «Усе слід робити настільки простим, наскільки це можливо, але не простішим». У цьому дусі наш дизайн адекватно розв’язав кожну проблему. Фінальна архітектура має чотири рівні, які ми вже розглянули:

  • сам codex.exe
  • codex-windows-sandbox-setup.exe для виконання всіх робіт із налаштування, пов’язаних із підвищеними привілеями
  • codex-command-runner.exe для запуску команд із обмеженим токеном
  • дочірній процес

Коли я вперше взявся за цей проєкт, я не мав чіткого уявлення, до чого все зрештою прийде. Мій підхід полягав у тому, щоб почати з інструментування можливостей ізольованого середовища на межі між Codex та операційною системою. Цей підхід дуже схожий на те, як ізольоване середовище Codex реалізовано в MacOs і Linux.

У міру того як я більше дізнавався про конкретні інструменти, які надає Windows, і через десятки рішень, що балансували між безпекою та зручністю використання, система набула нинішньої форми — кілька бінарних файлів, користувацькі облікові записи, правила брандмауера, крок налаштування з підвищеними правами, асинхронні процеси тощо.

Це не особливо проста система, але кожен елемент складності було додано з необхідності — щоб створити ізольоване середовище, яка є і безпечним, і, наскільки це можливо, не заважає користувачу.

Діаграма, що показує фінальну архітектуру ізольованого середовища Windows.

Балансування безпеки з реальною корисністю

Працюючи над тим, щоб забезпечити хороший користувацький досвід для користувачів Codex у Windows, ми прагнули створити щось безпечне, не жертвуючи корисністю — увесь сенс використання Codex полягає в тому, щоб агенти могли виконувати роботу без вашої постійної уваги.

Один із найбільших уроків цього проєкту полягав у тому, що Windows не надає готового механізму, який можна було б просто використати для створення «безпечного автономного агента для програмування». Ми поєднали кілька інструментів і концепцій, щоб побудувати щось цілісне. Деякі ранні ідеї виявилися безперспективними. Фінальний дизайн став гібридом попередніх прототипів, кожен із яких вирішував частину проблеми.

Інший урок полягав у тому, що безпека для агента програмування — це зовсім інша річ, ніж класична безпека застосунків. Codex має працювати для реальних робочих процесів розробників. Інженерна робота полягала в балансуванні сумісності з агентними навантаженнями та реального примусу до дотримання правил. Саме ця напруга сформувала компроміси у фінальному дизайні.

Цікаво побачити ізольоване середовище Codex у дії? Спробуйте.