Материал

Код, написанный ИИ: что обязательно проверить перед слиянием изменений

Рабочий PR — это ещё не безопасный PR. Что именно ломается в AI-кодинге и как это остановить до merge

Введение: скорость генерации против скорости контроля

Представьте: разработчик открывает Cursor, пишет несколько строк задачи в чате и через минуту получает готовую реализацию. Он просматривает её по диагонали — код выглядит правильно, тесты зелёные, CI прошёл. Merge.

Именно в этом зазоре между «работает» и «безопасно» живёт большинство проблем AI-кодинга.

По данным Checkmarx (2025), к концу 2024 года более 40% кода в корпоративных репозиториях было сгенерировано с помощью AI-инструментов [1]. Исследование CodeRabbit (декабрь 2025), охватившее 470 открытых Pull Request на GitHub, показало, что AI-код содержит примерно в 1,7 раза больше критических и серьёзных дефектов по сравнению с кодом, написанным людьми [2]. Apiiro, проанализировав данные Fortune 50-компаний, зафиксировала десятикратный рост количества security-находок в месяц — с ~1000 в декабре 2024 до более 10 000 к июню 2025 [3].

Это не повод отказываться от AI-инструментов. Это повод выстроить контроль, который успевает за скоростью генерации.

В этой статье — конкретно: что именно проверять в AI-коде перед merge, почему традиционные инструменты не закрывают все риски, и как выстроить процесс, который не превращается в бюрократический тормоз.

Изображение

Почему AI-код — это отдельная категория рисков

Прежде чем переходить к чек-листу, важно понять: AI-код — это не просто «ещё один источник кода». Это код со специфическим профилем уязвимостей.

Модель обучена на публичном коде — включая небезопасный

Большинство LLM обучены на открытых репозиториях. Публичный код содержит десятилетия накопленного технического долга, небезопасных паттернов и устаревших практик. Модель воспроизводит эти паттерны — не потому что «хочет» выдать уязвимый код, а потому что именно так написано большинство примеров в обучающей выборке [4].

Исследование на основе 733 реальных сниппетов от GitHub Copilot, CodeWhisperer и Codeium (ACTM, 2025) выявило уязвимости в 29,5% Python-фрагментов и 24,2% JavaScript-фрагментов, охватывающих 43 различных типа CWE [5]. Среди наиболее распространённых — недостаточная энтропия (CWE-330), инъекция кода (CWE-94) и межсайтовый скриптинг (CWE-79), восемь из которых входят в CWE Top 25.

AI не видит контекст безопасности вашего приложения

Модель генерирует код изолированно. Она не знает о вашей модели угроз, о том, что конкретный эндпоинт смотрит в интернет, что эта функция обрабатывает платёжные данные, или что вот этот сервис имеет избыточные привилегии в IAM. Результат — «синтаксически правильный» код, который архитектурно сломан для вашего конкретного случая [6].

Профиль уязвимостей AI-кода смещается в сторону архитектурных дефектов

Исследование Apiiro (2025) зафиксировало неожиданный сдвиг: количество тривиальных синтаксических ошибок в AI-коде снизилось на 76%, логических багов — на 60%. Но архитектурные дефекты выросли на 153%, а пути эскалации привилегий — на 322% [3]. Традиционный SAST хорошо ловит первые две категории. С архитектурными дефектами он практически бессилен, потому что код синтаксически корректен.

Автоматизация создаёт автоматизационное смещение

Разработчики склонны доверять AI-предложениям больше, чем следует. Исследования показывают: чем более «умным» выглядит сгенерированный код, тем меньше вероятность, что его тщательно проверят [1]. Это системный риск, встроенный в саму природу инструментов-ассистентов.

Что проверять: семь зон риска

1. Зависимости: галлюцинации и supply chain

Это один из наиболее недооценённых рисков AI-кодинга.

Исследование 2025 года (университеты Техаса, Оклахомы и Виргинии) проанализировало 576 000 сниппетов кода от 16 LLM и обнаружило, что ~20% рекомендованных пакетов не существовали ни в одном публичном реестре [7]. Эта уязвимость получила название slopsquatting: злоумышленники регистрируют пакеты с именами, которые AI стабильно галлюцинирует, — и разработчики, слепо доверяя предложениям модели, устанавливают malware вместо нужной библиотеки.

Что делает риск особенно серьёзным: 43% галлюцинированных имён пакетов повторяются стабильно от запроса к запросу, то есть это предсказуемые, регулярные мишени для атак [8].

Отдельная проблема — транзитивные зависимости. AI добавляет зависимость, которая сама тянет несколько других. Каждую из них нужно проверить через SCA. По данным Endor Labs (2025), только одна из пяти версий зависимостей, предложенных AI-инструментами, оказывается одновременно безопасной и существующей [9].

Что проверять перед merge:

  • Каждый новый пакет существует в официальном реестре (npm, PyPI, crates.io)?
  • У пакета есть история коммитов, мейнтейнеры, нормальная дата создания — это не свежезарегистрированная «пустышка»?
  • SCA-сканер не выдаёт известных CVE для пакета и его транзитивных зависимостей?
  • Lock-файл обновлён и зафиксирован вместе с изменением?

2. Секреты и credentials

AI стабильно воспроизводит паттерны из обучающих данных — включая паттерн «вставить секрет прямо в код». Исследование CUHK (ACM FSE 2024) показало: Copilot воспроизводил работающие credentials, включая Stripe-ключи, в 2702 из 900 протестированных промптов [10].

Согласно отчёту GitGuardian State of Secrets Sprawl 2026, в 2025 году в публичный GitHub было запушено 28,65 млн новых хардкодных секретов — рост на 34% год к году. Коммиты с участием AI-ассистентов содержат секреты вдвое чаще: 3,2% против 1,5% для кода, написанного людьми [11].

При этом 64% валидных секретов из 2022 года по-прежнему активны. Их никто не отозвал.

Что проверять:

  • Сканер секретов (GitGuardian, truffleHog, Gitleaks) запущен на весь diff, а не только на изменённые файлы?
  • В коде нет ни одного значения, похожего на API-ключ, токен, пароль или connection string — даже в тестовых файлах?
  • Конфигурационные файлы и .env.example не содержат реальных значений?
  • Новые переменные окружения документированы и получают значения из vault/secrets manager, а не из дефолтных захардкоженных строк?

3. Архитектурные дефекты и бизнес-логика

Это наиболее сложная для автоматизированного обнаружения категория, и именно здесь AI-код наиболее опасен.

Типичные проблемы:

  • Новый маршрут API добавлен без проверки аутентификации — AI сгенерировал функцию, не зная, что этот эндпоинт должен быть закрыт.
  • Логика авторизации основана на client-supplied параметре вместо server-side проверки контекста.
  • Избыточные разрешения в IAM-политиках, Terraform-манифестах или Kubernetes RBAC — AI склонен давать широкий доступ «чтобы точно работало».
  • Изменение бизнес-логики, которое корректно по синтаксису, но ломает security-инвариант (например, пропускает step в multi-step verification).

Исследование AppSec Engineer (2026) прямо указывает: AI-код следует считать непроверенным по умолчанию, даже если он запускается без ошибок и выглядит правильно [12].

Что проверять:

  • Новый код, касающийся аутентификации, авторизации, платёжной логики или шифрования, прошёл ревью человека с пониманием security-модели системы?
  • Если изменение касается API — все новые эндпоинты требуют аутентификации?
  • Роли и разрешения следуют принципу least privilege, а не «выдать всё нужное + запас»?
  • Есть ли в PR описание, объясняющее логику изменения, а не только «что сделал AI»?

4. Инъекции и обработка пользовательского ввода

AI особенно плохо справляется с валидацией входных данных. Veracode (2025) зафиксировала провал в 86% случаев по Cross-Site Scripting (CWE-80) при тестировании 100+ LLM [13]. SQL-инъекции через конкатенацию строк — ещё один стабильный паттерн.

Что проверять:

  • Пользовательский ввод параметризован в запросах к БД, нет конкатенации строк?
  • HTML-вывод экранируется перед рендерингом?
  • Файловые пути не формируются из user input без санитизации?
  • Если добавлены вызовы к LLM внутри сервиса — входные данные изолированы от системного промпта (защита от prompt injection, OWASP LLM Top 10 2025, LLM01) [14]?

5. Конфигурационные файлы AI-ассистентов

Это зона риска, которая почти не обсуждается на code review, хотя последствия могут быть катастрофическими.

В марте 2025 Pillar Security раскрыла атаку Rules File Backdoor: злоумышленники внедряли скрытые инструкции в файлы правил Cursor и GitHub Copilot (.cursorrules, .github/copilot-instructions.md) через невидимые Unicode-символы (zero-width joiners, bidirectional text markers). AI-ассистент исполнял эти инструкции, вставляя malicious-код в генерации — незаметно для разработчика и не отображаясь в PR-предпросмотре [15]. Обе компании ответили, что ответственность лежит на пользователях.

В августе 2025 CVE-2025-53773 (CVSS 7.8) зафиксировал аналогичный вектор: prompt injection через code comment позволял модифицировать .vscode/settings.json и включать «YOLO mode», после чего Copilot выполнял shell-команды без подтверждения пользователя [16].

Что проверять:

  • Файлы правил AI-ассистентов (.cursorrules, AGENTS.md, copilot-instructions.md) проходят отдельное ревью при изменении?
  • В этих файлах нет невидимых Unicode-символов (проверка hex-дампом или специализированным linter)?
  • Внешние правила, взятые из community-репозиториев, верифицированы?
  • .vscode/settings.json не содержит значения chat.tools.autoApprove: true?

6. CI/CD-файлы, IaC и конфигурации

Служебный код проверяют хуже всего — на code review взгляд «замыливается», когда смотришь на YAML-файл GitHub Actions или Terraform-манифест. AI генерирует их так же легко, как и Python-функции, но проблемы там накапливаются незаметно.

Характерные паттерны:

  • Использование mutable тегов в GitHub Actions вместо закреплённых SHA-хешей (tj-actions/changed-files incident, март 2025, затронул более 23 000 репозиториев) [17].
  • Избыточные права в IAM-политиках: AI добавляет * там, где нужны конкретные ресурсы.
  • Вывод секретов в логи CI/CD-пайплайна через echo или debug-флаги.
  • Insecure defaults в Docker-образах: root-пользователь, открытые порты, отсутствие .dockerignore.

Что проверять:

  • Все Actions-зависимости закреплены на конкретный SHA-коммит, а не на теги v1/v2?
  • В workflow нет run: echo $SECRET или подобных конструкций?
  • IaC-манифесты прошли scan (Checkov, tfsec, kube-score) без критических находок?
  • Политики IAM следуют least privilege?

7. Тесты: покрытие реальных security-сценариев

AI генерирует тесты охотно — но эти тесты проверяют happy path, а не граничные случаи и security-инварианты. Зелёный CI при нулевом покрытии критических путей — ложная безопасность.

Что проверять:

  • Новый код затрагивает аутентификацию, авторизацию или обработку платёжных данных? Есть ли тесты с невалидными/граничными значениями?
  • Тесты проверяют поведение при unexpected input, а не только при корректном?
  • Если изменение ломает существующий тест — это намеренно, и PR-описание объясняет почему?

Что делать на уровне процесса

Разовые проверки не масштабируются. Нужна система.

Разделите PR по категориям риска

Не весь AI-код одинаково опасен. CRUD-операции над внутренними сущностями — одно, изменение логики авторизации — другое. Введите явное разграничение:

  • Критические зоны (auth, payments, crypto, secrets management) — обязательное ревью от человека с AppSec-компетенцией, независимо от того, написан код AI или человеком.
  • Бизнес-логика — ревью разработчика, знающего контекст функции; структурированный PR-шаблон с описанием инвариантов.
  • Инфраструктурный и служебный код — обязательные автоматические gates (IaC-scanner, SCA, secrets).
  • Утилиты и CRUD — стандартный процесс с автоматическими проверками.

Checkmarx прямо рекомендует устанавливать пороги для обязательного ревью исходя из того, касается ли AI-код чувствительных систем или бизнес-логики [1].

Встройте проверки в pipeline, а не в постфактум-аудит

Инструменты, которые живут в конце процесса, читают меньше всего. Работают те, что останавливают разработчика прямо в момент создания PR:

  • Pre-commit hooks для секретов (gitleaks) — быстрые, не блокируют workflow.
  • SCA на уровне PR с блокировкой merge при critical CVE.
  • SAST-сканер на diff, а не на весь репозиторий — это принципиально для скорости.
  • Lint конфигурационных файлов на невидимые Unicode-символы.

Важно: инструменты, которые работают слишком долго, обходят. Semgrep на diff PR работает быстро — это важное качество [18].

Маркируйте AI-коммиты

Часть проблем возникает из-за невидимости: никто не знает, какой процент кода в PR сгенерирован AI. Введите конвенцию тегирования (например, [ai-assisted] в сообщении коммита или label в PR). Это позволяет:

  • таргетировать более жёсткие проверки на AI-контент;
  • собирать метрики по плотности дефектов в AI vs human коде.

Метрики, которые показывают реальную картину

Три показателя, стоит отслеживать:

  • First-pass secure-merge rate: как часто AI-assisted PR проходит security-gates без доработок.
  • Mean time to remediate AI-introduced vulnerabilities.
  • Dependency hygiene score: доля AI-предложенных пакетов, прошедших SCA без CVE и галлюцинаций.

Типичные ошибки и как их избежать

Ошибка 1: считать, что SAST закрывает все риски AI-кода.

SAST отлично видит SQL-инъекции и XSS. Но architectural drift — ситуацию, когда модель вносит тонкие изменения, ломающие security-допущения, не нарушая синтаксис, — не видит никакой статический анализатор [6]. Нужен дополнительный слой: ревью с пониманием архитектурного контекста.

Ошибка 2: проверять только diff, игнорируя транзитивный контекст.

Изменение в одном файле может поменять поведение security-критичного кода в другом месте. AI не знает о cross-file dependencies — и ревьюер тоже часто не проверяет их. Это требует понимания архитектурных зависимостей.

Ошибка 3: не проверять конфигурационные файлы AI-ассистентов.

Файл .cursorrules выглядит безобидно. Но если его содержимое было изменено через атаку Rules File Backdoor, все последующие генерации в проекте будут заражены [15].

Ошибка 4: длинный security-отчёт вместо краткого сигнала.

Отчёт с 200 findings перед релизом не помогает принять решение. Нужен конкретный ответ: «вот что блокирует merge, вот почему, вот следующий шаг». Команда должна понимать, что остановить, а что принять с осознанным решением.

Ошибка 5: думать, что CI прошёл = безопасно.

Зелёный пайплайн означает, что тесты прошли и SAST-правила не сработали. Это не означает отсутствие архитектурных дефектов, галлюцинированных зависимостей или встроенных секретов в переменных окружения.

Инструменты: что встраивать в процесс

Ни один инструмент не закрывает все риски AI-кода в одиночку. Нужен набор.

Обнаружение секретов: GitGuardian, TruffleHog, Gitleaks — запускать на каждый push и в pre-commit.

SCA (Software Composition Analysis): Snyk, OWASP Dependency-Check, Endor Labs — проверять каждую новую зависимость, включая транзитивные, на CVE и существование в публичных реестрах.

SAST: Semgrep, Checkmarx, Mend SAST — на diff PR; важна скорость работы, иначе hooks будут обходить.

IaC scanning: Checkov, tfsec, kube-score — на все Terraform, CloudFormation, Kubernetes-манифесты.

Linting конфигов AI-ассистентов: Unicode-детектор (grep на zero-width characters) — запускать при любом изменении .cursorrules, AGENTS.md, copilot-instructions.md.

Все перечисленные инструменты — это отдельные слои, каждый из которых закрывает свою зону. OWASP напрямую рекомендует интегрировать SAST, DAST и SCA в CI/CD как взаимодополняющие, а не взаимозаменяющие контроли [19].

Дополнительный слой, который становится актуальным при высоком темпе AI-разработки, — анализ конкретного изменения в контексте релиза. Именно это делает HighVibe: вместо тотального сканирования репозитория смотрит на конкретный diff, новые зависимости и конфигурационные изменения, выдаёт короткий ответ «что именно блокирует этот PR» и предлагает конкретный следующий шаг — без длинного отчёта, без лишнего шума.

Что происходит с отраслью: тренды 2025–2026

По данным Stack Overflow Developer Survey 2025, 84% профессиональных разработчиков используют или планируют использовать AI-инструменты для написания кода [20]. При этом доверие к точности AI-генераций снизилось с 40% до 29% за один год — разработчики всё лучше понимают, что инструмент требует проверки.

Параллельно формируется регуляторный контекст. CISA в своём руководстве по безопасности в AI (2025) явно указывает на риски AI-assisted разработки и рекомендует встраивать security-контроли на всех этапах SDLC. OWASP выпустил LLM AI Cybersecurity & Governance Checklist — 32-страничный документ, охватывающий ключевые зоны риска при использовании LLM в разработке [21].

Emerging-риск, который стоит отслеживать: атаки через MCP-серверы (Model Context Protocol). MCP — стандарт 2024 года, позволяющий AI-агентам подключаться к внешним инструментам в реальном времени. Экосистема MCP пока незрелая: проверка безопасности сторонних MCP-серверов, которые подключают в рабочие процессы, становится отдельной задачей [9].

Другая тенденция: agentic coding. Автономные AI-агенты (GitHub Copilot Coding Agent, Devin, аналоги) создают PR без участия человека. Это требует пересмотра всей модели ревью: кто ревьюит PR от агента? Как убедиться, что агент не получил poisoned instructions через атаку на свой context?

Практический чек-лист перед merge: минимально необходимый набор

Блокирующие проверки — без них merge запрещён:

  1. SCA: все новые зависимости существуют в официальных реестрах и не имеют critical CVE.
  2. Secrets scanner: нет хардкодных credentials, токенов или API-ключей в любом файле diff.
  3. SAST: нет критических/высоких severity-находок по OWASP Top 10.
  4. Lock-файл: обновлён и зафиксирован вместе с изменением зависимости.

Обязательные для критических зон (auth, payments, crypto, infra):

  1. Ревью человека с пониманием security-модели, а не только функциональности.
  2. Объяснение логики изменения в PR-описании (что делает код и почему это безопасно).
  3. Проверка IaC-манифестов на избыточные разрешения и mutable теги в CI/CD.

Дополнительно при изменении AI-конфигов:

  1. Проверка файлов правил на невидимые Unicode-символы.
  2. Верификация источника внешних правил-файлов.

Желательно, но не всегда блокирующее:

  1. Метрика test coverage на новый код, особенно граничные случаи.
  2. Архитектурное ревью при изменении cross-service boundaries или security-инвариантов.

Заключение

AI-инструменты делают разработку быстрее. Это необратимо и не нужно останавливать.

Но «работает» и «безопасно для merge» — не одно и то же. AI генерирует код с предсказуемыми слабыми местами: галлюцинированные зависимости, хардкодные секреты, архитектурные дефекты, слепота к бизнес-контексту. При этом традиционный AppSec-стек закрывает далеко не всё: SAST видит синтаксические паттерны, но не архитектурный drift; SCA проверяет известные CVE, но не несуществующие пакеты; code review читает diff, но не всегда понимает security-инварианты, которые он ломает.

Ответ — не замедление. Ответ — контроль, который работает со скоростью AI: автоматические gates на каждый PR, понятный сигнал вместо длинного отчёта, чёткое разграничение того, что требует human-ревью, а что проходит автоматически.

Следующий шаг: возьмите чек-лист из этой статьи и сравните с тем, что реально проверяется в вашем процессе прямо сейчас. Где пробелы — там и приоритет.

Источники

[1] Checkmarx — "2025 CISO Guide to Securing AI-Generated Code" — https://checkmarx.com/blog/ai-is-writing-your-code-whos-keeping-it-secure/

[2] BusinessWire / CodeRabbit — "State of AI vs Human Code Generation Report" — https://www.businesswire.com/news/home/20251217666881/en/CodeRabbits-State-of-AI-vs-Human-Code-Generation-Report-Finds-That-AI-Written-Code-Produces-1.7x-More-Issues-Than-Human-Code

[3] Apiiro — "AI-Generated Code Security: Security Risks and Opportunities" — https://apiiro.com/blog/ai-generated-code-security/

[4] AppSec Engineer — "AI-Generated Code Needs Its Own Secure Coding Guidelines" — https://www.appsecengineer.com/blog/ai-generated-code-needs-its-own-secure-coding-guidelines

[5] Cloud Security Alliance / Vibe Coding Security Research Note — https://labs.cloudsecurityalliance.org/research/csa-research-note-ai-generated-code-security-vibe-coding-202/

[6] SoftwareSeni — "Security Risks in AI-Generated Code and How to Mitigate Them" — https://www.softwareseni.com/security-risks-in-ai-generated-code-and-how-to-mitigate-them/

[7] arXiv / Importing Phantoms: Measuring LLM Package Hallucination Vulnerabilities — https://arxiv.org/pdf/2501.19012

[8] BleepingComputer — "AI-hallucinated code dependencies become new supply chain risk" — https://www.bleepingcomputer.com/news/security/ai-hallucinated-code-dependencies-become-new-supply-chain-risk/

[9] Supply & Demand Chain Executive / Endor Labs — "The Hidden Dependency Risk of AI-Written Code" — https://www.sdcexec.com/software-technology/ai-ar/article/22959921/endor-labs-the-hidden-dependency-risk-of-aiwritten-code

[10] GitGuardian — "Yes, GitHub Copilot Can Leak (Real) Secrets" — https://blog.gitguardian.com/yes-github-copilot-can-leak-secrets/

[11] Build MVP Fast — "Copilot Secrets Leak: 2,702 Hard-Coded Keys Found in AI Code" — https://www.buildmvpfast.com/blog/copilot-secrets-api-key-leak-ai-code-security-2026

[12] AppSec Engineer — "AI-Generated Code Needs Its Own Secure Coding Guidelines" — https://www.appsecengineer.com/blog/ai-generated-code-needs-its-own-secure-coding-guidelines

[13] SoftwareSeni — "AI-Generated Code Security Risks: Why Vulnerabilities Increase 2.74x" — https://www.softwareseni.com/ai-generated-code-security-risks-why-vulnerabilities-increase-2-74x-and-how-to-prevent-them/

[14] OWASP Gen AI Security Project — Top 10 for LLM Applications 2025 — https://genai.owasp.org/llm-top-10/

[15] Pillar Security — "New Vulnerability in GitHub Copilot and Cursor: Rules File Backdoor" — https://www.pillar.security/blog/new-vulnerability-in-github-copilot-and-cursor-how-hackers-can-weaponize-code-agents

[16] Wiz — "CVE-2025-53773 Impact, Exploitability, and Mitigation Steps" — https://www.wiz.io/vulnerability-database/cve/cve-2025-53773

[17] Cycode — "OWASP Top 10 2025: Addressing Software Supply Chain and LLM Risks" — https://cycode.com/blog/the-2025-owasp-top-10-addressing-software-supply-chain-and-llm-risks-with-cycode/

[18] StackHawk — "GitHub Copilot + StackHawk: Secure Code from The Start" — https://www.stackhawk.com/blog/github-copilot-secure-coding-guide/

[19] Cycode — "OWASP Top 10 2025: Addressing Software Supply Chain and LLM Risks" — https://cycode.com/blog/the-2025-owasp-top-10-addressing-software-supply-chain-and-llm-risks-with-cycode/

[20] Cloud Security Alliance / Vibe Coding Security Research Note — https://labs.cloudsecurityalliance.org/research/csa-research-note-ai-generated-code-security-vibe-coding-202/

[21] Infosecurity Magazine — "OWASP Releases Security Checklist Generative AI Deployment" — https://www.infosecurity-magazine.com/news/owasp-security-checklist/

Нужен такой же контроль в ваших изменениях и релизах?

Покажем пример такого замечания на вашем сценарии и соберём пилотный контур без лишней суеты.

Запросить пилот Все статьи
Дальше по теме

Ещё материалы

Все статьи
24 июня 2026 18 мин

Политика использования ИИ в команде разработки: как не опоздать, когда всё уже идёт

Если разработчики уже пишут код с ИИ ассистентами, политика нужна сегодня — а не после первого инцидента TL;DR Более 84% разработчиков уже используют или планируют использовать ИИ инструменты 1 , и большинство делают эт…

Открыть материал
23 июня 2026 16 мин

Регистрация и онбординг пользователей: где появляются первые уязвимости

Форма регистрации выглядит просто. За ней скрывается один из наиболее атакуемых периметров приложения. TL;DR Форма регистрации и онбординг флоу — это первая поверхность атаки, которую видит злоумышленник. Большинство уя…

Открыть материал
23 июня 2026 15 мин

Бизнес-логика и мошенничество в продукте: что проверять до запуска

Ваш продукт работает правильно. Но это не значит, что он работает безопасно. TL;DR Уязвимости бизнес логики — это не сломанный код, а сломанные правила: приложение делает именно то, что написано, но не то, что задумывал…

Открыть материал