Материал

Как проверять PR, если AI изменил GitHub Actions, Dockerfile, Terraform или миграции

Рабочий pull request — не значит безопасный. Особенно если его написал ИИ

Введение: почему именно сейчас это важно

Команды, которые внедрили AI-ассистентов в разработку, получили реальное ускорение. По данным исследований, количество PR на разработчика выросло примерно на 20% год к году [6]. Но одновременно выросло число инцидентов на PR — и именно в той части, которую обычно читают невнимательно: служебные файлы инфраструктуры.

GitHub Actions, Dockerfile, Terraform-модули, SQL-миграции — это не бизнес-логика. Их не тестируют юнит-тестами, их реже изучают на code review, и именно их AI генерирует охотнее всего: они шаблонны по форме, понятны модели синтаксически, но критичны по содержанию.

Veracode в исследовании 2025 года протестировали более 100 больших языковых моделей на 80 реальных задачах кодирования. Вывод: AI-генерируемый код содержит уязвимости в 45% случаев, и этот показатель практически не улучшился с ростом размеров моделей [1]. Это не означает, что AI плохой инструмент. Это означает, что контроль изменений не успел вырасти с той же скоростью, что скорость генерации.

Эта статья — для тех, кто принимает решения по безопасности и инженерные решения: что проверять в PR с AI-правками инфраструктурных файлов, как выстроить process, и где автоматика не заменит человека.

Масштаб проблемы: цифры, которые нельзя игнорировать

Прежде чем разбирать каждый тип файла отдельно, стоит понять общий контекст.

Исследование Apiiro по предприятиям из Fortune 50 показало, что в AI-генерируемом коде пути привилегированной эскалации встречаются в 3,22 раза чаще, чем в человеческом, а экспозиция секретов выросла на 40% [6]. Академическое исследование 117 062 изменений зависимостей из 33 596 PR, написанных AI-агентами, показало: агенты выбирают уязвимые версии пакетов вдвое чаще людей (2,46% против 1,64%), и их уязвимые выборы сложнее исправить — 36,8% требуют major-version upgrade против 12,9% у людей [2].

Важный нюанс из того же исследования: агенты создали net increase в количестве уязвимостей на 98, тогда как человеческие PR дали net reduction на 1 316 [2]. Это не повод отказаться от AI — это повод поставить review gate.

При этом атаки на инфраструктуру CI/CD растут. По данным Wiz и Dark Reading, число supply chain атак через GitHub Actions увеличилось в 2025 году [5]. В марте 2025 года атака на tj-actions/changed-files (CVE-2025-30066) одновременно скомпрометировала более 23 000 репозиториев, включая проекты Fortune 500 [7, 9, 10].

GitHub Actions: зона повышенного риска

Что конкретно генерирует AI — и что может пойти не так

AI-ассистенты прекрасно знают структуру YAML и синтаксис GitHub Actions. Они генерируют рабочие workflow за секунды. Проблема в том, что рабочий — не значит безопасный.

Главные риски AI-генерируемых workflow-файлов:

Триггер pull_request_target с небезопасным checkout. Это классический «pwn request». GitHub Security Lab описывает комбинацию pull_request_target с явным checkout untrusted PR как опасную практику, ведущую к компрометации репозитория [12]. AI часто генерирует именно эту конфигурацию, когда ему дают задание «запускать workflow на PR». Результат: код из PR форкнутого репозитория выполняется с повышенными правами.

Чрезмерные permissions. AI по умолчанию склонен выставлять permissions: write-all или не ограничивать GITHUB_TOKEN вообще. Orca Security фиксирует, что подавляющее большинство workflow используют mutable references вместо pin по commit hash, и это молчаливо доверяет любому коду, на который указывает тег [4].

Использование actions по tag, а не по commit hash. Атака на tj-actions наглядно показала: тег v35 или v45 может быть перенаправлен на вредоносный коммит. Атакующий модифицировал код action и ретроактивно обновил существующие теги, чтобы они указывали на вредоносный коммит [9]. Пользователи с pin по тегу оказались уязвимы. Пользователи с pin по commit hash — нет.

Секреты в логах. Миллионы секретов ежегодно утекают через GitHub Actions — они оказываются в hardcoded workflow, логах или неправильно обрабатываются в CI/CD процессах [4]. AI генерирует echo $SECRET в debug-шагах и не всегда корректно использует ${{ secrets.NAME }}.

Script injection через ${{ github.event.pull_request.title }} и другие untrusted inputs напрямую в run: — ещё один паттерн, который AI воспроизводит из обучающих данных без понимания последствий.

Чек-лист проверки GitHub Actions в PR

Просматривая PR с изменёнными .github/workflows/*.yml:

  1. Проверить триггеры: есть ли pull_request_target? Если да — есть ли в том же job actions/checkout с ref: ${{ github.event.pull_request.head.sha }}? Это pwn request.
  2. Проверить permissions: на уровне job и workflow. Нет явного объявления = слишком широкие права. Правило: начинать с permissions: {}, добавлять только необходимое.
  3. Все внешние actions должны быть закреплены по полному SHA (формат uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683). Tag pinning недостаточен.
  4. Нет ли untrusted input в run: напрямую? Все переменные из github.event.* должны передаваться через env:, не inline.
  5. Нет ли секретов, выводимых в логи через echo или cat?
  6. Нет ли новых сторонних actions, которых раньше не было? Каждый новый action — это dependency в вашей supply chain. Проверьте reputation, дату последнего коммита, наличие CVE.
  7. Минимальный scope для GITHUB_TOKEN: contents: read, если workflow только читает код.

Dockerfile: атака поверхность в контейнере

Что AI делает неправильно с Dockerfile

По данным Sysdig 2025 Cloud-Native Security Report, количество пакетов в образах контейнеров выросло на 300% — и часть этого роста объясняется AI-генерируемыми Dockerfile, где модель добавляет зависимости по аналогии, не оптимизируя размер [3].

Основные проблемы AI-генерируемых Dockerfile:

Отсутствие pinning базового образа. FROM ubuntu:latest или FROM python:3.11 — это mutable reference. Docker Docs прямо указывают: для полной гарантии supply chain integrity нужно закреплять образ по digest в формате FROM alpine@sha256:... [13]. AI крайне редко генерирует digest-pinning.

Запуск от root. По умолчанию контейнеры запускаются от root. AI нередко пропускает директиву USER в Dockerfile, особенно в быстро написанных скриптах. Если атакующий получит доступ к контейнеру, root = root на уровне намного большем, чем нужно [14].

Секреты в слоях образа. Паттерн COPY .env . или ARG API_KEY=... в Dockerfile создаёт слой с секретами, который остаётся в image history даже после последующих RUN. Исследование 2025 года показало: 54% облачных сред содержат credentials, захардкоженные в конфигурационных файлах или контейнерах [8].

Избыточные expose и привилегии. AI генерирует EXPOSE 22 (SSH), --privileged, монтирование /var/run/docker.sock — паттерны, которые встречаются в обучающих данных, но создают серьёзные уязвимости в production.

Устаревшие базовые образы. 75% образов в production содержат хотя бы одну уязвимость высокой или критической степени серьёзности по данным Aikido Security [8]. AI не знает актуального состояния advisories.

Игнорирование multi-stage builds. AI генерирует простые однослойные Dockerfile, включая build-зависимости в финальный образ. OWASP Docker Security Cheat Sheet рекомендует multi-stage builds для минимизации attack surface [11].

Чек-лист проверки Dockerfile в PR

  1. Базовый образ: закреплён ли по digest? Если нет — минимум по конкретному minor-тегу (не latest).
  2. Есть ли директива USER с non-root пользователем перед CMD/ENTRYPOINT?
  3. Есть ли явное --no-install-recommends при apt/apk install? Это снижает attack surface.
  4. Нет ли секретов в ARG, ENV, COPY на строках, которые попадут в финальный image layer?
  5. Используется ли multi-stage build? Особенно для compiled languages.
  6. Нет ли --privileged, --cap-add=ALL, монтирования /var/run/docker.sock без явной необходимости?
  7. Нет ли EXPOSE портов, которые не нужны приложению?
  8. Прогоните образ через Trivy или Grype как часть pipeline — до merge, не после.

Terraform: инфраструктурный blast radius

Comprehension gap: главная проблема AI-generated IaC

Cloudmagazin точно описывает проблему: «AI-generated Terraform code is faster to write than to read — exactly what makes it dangerous» [16]. Команды, делегирующие написание IaC Copilot, Cursor или Claude, получают скорость, но теряют mental model инфраструктуры. Comprehension Gap расширяется с каждым принятым suggestion и обнаруживает себя в момент инцидента.

Особая опасность AI-генерируемого Terraform:

Семантически невалидный, но синтаксически правильный код. LLM иногда генерирует несуществующие атрибуты Terraform-провайдеров. terraform plan их молча игнорирует — не отвергает. Результат: security policy, которую разработчик намеревался сконфигурировать через AI-suggestion, просто не применяется [16]. Policy-as-Code инструменты вроде OPA/Rego или Sentinel поймали бы это — но большинство команд, внедряющих AI-assisted IaC, не имеют их на момент старта.

Избыточные IAM permissions. AI генерирует Action: "" и Resource: "" — wildcard-политики, которые нарушают принцип least privilege. Endor Labs описывает типичный пример: AI pushes Terraform PR, который даёт full access ко всем AWS actions и ресурсам [15]. Если задеплоить — IAM-роль позволяет привилегированную эскалацию, exfiltration данных, компрометацию других сервисов.

Незашифрованные remote state файлы. Terraform state может содержать plaintext secrets, если команда использует S3-бэкенд без encryption. Wiz отмечает: незашифрованные и незащищённые state files — одна из ведущих проблем IaC-безопасности [17]. AI не знает, настроен ли encryption в вашем S3 bucket.

Небезопасные defaults. Открытые security groups (0.0.0.0/0 на ingress), публичные S3 buckets, незашифрованные RDS-инстансы — классика AI-generated IaC. Gartner прогнозирует: до 2027 года 99% облачных security failures будут вызваны misconfiguration, а не уязвимостями [18].

Drift и автономная remediation. Если команда добавляет AI-агента для автоматической drift-remediation, он может откатить ночной emergency patch — то самое намеренное отклонение от state, которое дежурный инженер применил для устранения инцидента. Это задокументированный production риск [16].

Распространение на все среды. Ошибка в shared Terraform module реплицируется во все окружения, которые его используют. Один misconfigured модуль = fifty раз ошибка при деплое в fifty сред [18].

Чек-лист проверки Terraform в PR

  1. Есть ли wildcard permissions (Action: "", Resource: "")? Это блокирующее замечание.
  2. Все ресурсы следуют принципу least privilege?
  3. Remote state: encryption enabled, DynamoDB locking настроен?
  4. Нет ли hardcoded secrets в .tf-файлах? Все чувствительные значения должны приходить из Vault, AWS Secrets Manager или переменных окружения.
  5. Нет ли открытых security groups на 0.0.0.0/0?
  6. Все storage-ресурсы: шифрование at-rest включено?
  7. Запустите terraform plan вручную и прочитайте plan output до terraform apply — никогда не применяйте AI-generated IaC без review плана.
  8. Используйте Checkov или tfsec в CI как обязательный gate. Они поймают большинство known-bad patterns [16, 17].
  9. Попросите любого члена команды объяснить изменённый модуль построчно. Если больше 20% конфигурации не объясняется без документации — Comprehension Gap критичен [16].

Database migrations: необратимые действия

Почему миграции — отдельная история

Миграции базы данных занимают особое место в этом ряду: они необратимы по природе в production (даже если технически содержат rollback-скрипт), выполняются в момент деплоя и могут заблокировать production-базу на часы при неправильной реализации.

AI хорошо генерирует синтаксически корректный SQL и понимает DDL. Но он не знает:

  • объём данных в таблице и ожидаемое время выполнения ALTER TABLE;
  • active workload и пиковую нагрузку в момент деплоя;
  • cross-PR зависимости: другой PR может одновременно изменять ту же таблицу [19];
  • организационный контекст: «мы никогда не меняем эту таблицу без уведомления billing team» [19].

Специфические риски AI-generated migrations:

Блокирующие DDL. ALTER TABLE ADD COLUMN NOT NULL DEFAULT 'value' без null-friendly default на большой таблице = full table lock. AI пишет синтаксически правильный запрос, не учитывая, что на таблице 500 млн строк.

Permission grants с избыточным scope. GRANT EXECUTE ON SCHEMA или WITH GRANT OPTION — AI генерирует по аналогии, не понимая эффективных permissions в контексте конкретной СУБД и ролей.

Потеря ссылочной целостности. AI может сгенерировать DROP COLUMN или RENAME без проверки foreign key constraints в других таблицах или сервисах.

Секреты в миграциях. AI иногда генерирует INSERT с тестовыми данными, включая пароли или API ключи из контекста.

Отсутствие идемпотентности. CREATE TABLE вместо CREATE TABLE IF NOT EXISTS — миграция упадёт при повторном запуске.

Чек-лист проверки database migrations в PR

  1. DDL на большие таблицы: есть ли оценка времени выполнения? Подготовлено ли окно для деплоя?
  2. Все NOT NULL columns добавляются с compatible default или в два шага (добавить nullable → populate → add constraint)?
  3. Нет ли GRANT/REVOKE без явного обоснования? Проверьте effective permissions.
  4. DROP/RENAME операции: проверены ли foreign key dependencies и зависимые сервисы?
  5. Нет ли INSERT с тестовыми данными, содержащими чувствительную информацию?
  6. Все CREATE TABLE/CREATE INDEX используют IF NOT EXISTS?
  7. Есть ли rollback-план для production?
  8. Для больших миграций: запускайте в staging с production-size данными перед merge.

Decision framework: что блокировать, что помечать, что принимать

Не все находки требуют одинакового ответа. Ключевой вопрос при PR review: это блокирующая проблема или предупреждение?

Блокировать merge:

  • pwn request pattern в GitHub Actions (pull_request_target + checkout PR head)
  • wildcard IAM permissions в Terraform (Action: "*")
  • hardcoded secrets в любом из файлов
  • Dockerfile с --privileged или монтированием docker.sock без обоснования
  • DDL-миграция на большую таблицу без оценки lock time и окна деплоя

Требовать объяснений/уточнений:

  • новые сторонние GitHub Actions без pin по commit hash
  • базовый образ Docker без digest pinning
  • незашифрованный remote state в Terraform
  • IAM-изменения без явного least-privilege обоснования
  • GRANT/REVOKE в миграциях без контекста

Принимать с замечанием:

  • мелкие оптимизации Dockerfile без security impact
  • добавление IF NOT EXISTS там, где это улучшение, а не fix
  • изменение таймаутов и retry логики в workflow

Автоматизация: где она помогает, а где нет

Автоматизация покрывает значительную часть механических проверок. Вот минимальный стек для команды, использующей AI-assisted IaC:

GitHub Actions:

  • Checkov или Semgrep с правилами для GitHub Actions (флагирует pwn request patterns, отсутствие pinning)
  • GitHub GHAS с dependency review для Actions
  • StepSecurity Harden-Runner для runtime-мониторинга CI workflows

Dockerfile:

  • Trivy или Grype в CI — сканирование образа до merge
  • Hadolint — linter для Dockerfile, интегрируется в pipeline
  • Docker Scout для continuous monitoring в registry

Terraform:

  • Checkov или tfsec в CI как required check
  • OPA/Sentinel для policy-as-code: no 0.0.0.0/0, no unapproved regions, required tags
  • terraform plan output review как обязательный шаг перед apply (никогда no auto-apply)

Database migrations:

  • Flyway или Liquibase с их built-in validation
  • Для больших изменений — staging run с production-size данными

Автоматика хорошо ловит known-bad patterns: известные CWE, misconfigured defaults, секреты в открытом виде. Она плохо работает с:

  • workload-specific performance impact (AI-generated tool тоже не знает ваши query patterns)
  • cross-PR dependencies
  • организационным контекстом и неявными договорённостями команды
  • намеренными отклонениями от best practices с обоснованием

Именно здесь необходим человек-ревьюер, понимающий контекст.

Место HighVibe в этой картине

Когда команда активно использует AI для написания кода, объём PR растёт, а служебные файлы — Actions, Dockerfile, Terraform, миграции — попадают в ревью вместе с бизнес-логикой. Дочитывают не до конца. Именно здесь появляется слепая зона.

HighVibe — это слой контроля до merge и релиза, который анализирует конкретное изменение: что именно изменилось в PR, какие зависимости появились, какой контекст релиза. Он не заменяет SAST, Checkov или Trivy — он работает рядом с ними, добавляя короткий и понятный сигнал для команды: можно ли безопасно принять именно это изменение сейчас. Не длинный отчёт, а практический ответ.

Для команд, где AI уже ускорил разработку, но контроль изменений не успел вырасти с той же скоростью — это именно тот gap, который нужно закрыть.

Ошибки, которые команды совершают снова и снова

Ошибка 1: «Оно работает, значит безопасно». Terraform plan прошёл. Dockerfile строится. Workflow выполняется. Но ни один из этих фактов не означает, что конфигурация безопасна для production.

Ошибка 2: Доверять pinning по тегу как иммутабельному. Атака на tj-actions показала: теги GitHub Actions мутабельны. Атакующий с push access может переместить тег на вредоносный коммит [9, 10]. Только SHA hash immutable.

Ошибка 3: Отдельный security review только для бизнес-логики. Служебные файлы часто попадают в категорию «технические изменения» и проходят ревью быстрее. Но именно они несут инфраструктурный blast radius.

Ошибка 4: Auto-apply для AI-generated IaC. Никакого авто-применения без human review terraform plan. AI-агент, выполняющий drift remediation, не отличает намеренное отклонение от случайного [16].

Ошибка 5: Отсутствие SBOM и inventarizации Actions. После CVE-2025-30066 CISA выпустило advisory, рекомендующее организациям проводить аудит всех репозиториев с использованием tj-actions [7]. Если у вас нет inventory, вы не можете быстро ответить на такой инцидент.

Ошибка 6: Игнорировать transitive dependencies. AI-generated Terraform может подтянуть community module, который тянет ещё один module. Wiz отмечает: untrusted modules могут содержать malicious logic или unverified configurations [17].

Тренды: что изменится в ближайшие 12–18 месяцев

Несколько направлений, которые стоит отслеживать.

AI-агенты в CI/CD будут брать на себя больше автономных действий — от dependency updates до drift remediation. Это означает, что attack surface CI/CD продолжит расти, а компрометация CI-агента станет ещё более ценной для атакующего [5].

Policy-as-Code (OPA, Sentinel, Kyverno) перестаёт быть экзотикой и становится базовым контролем для команд с AI-assisted IaC. Cloudmagazin напрямую связывает отсутствие policy enforcement с опасностью AI-генерируемого Terraform [16].

Image signing (Sigstore, Cosign) и SBOM generation переходят из nice-to-have в compliance requirement для regulated industries. Docker Docs и OWASP Docker Cheat Sheet включают их в основные рекомендации [11, 13].

Более новые LLM с reasoning-подходом (GPT-5 reasoning class по данным Veracode) показывают первые значимые улучшения в security pass rate — до 72% [1]. Это обнадёживает, но не отменяет need for review: 28% failure на критической инфраструктуре — это всё ещё слишком много.

Заключение: контроль не мешает скорости

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

Три операционных вывода:

Первый: служебные файлы (Actions, Dockerfile, Terraform, миграции) требуют отдельного внимания в PR review, потому что AI-генерируемые изменения в них несут непропорционально высокий риск относительно их размера.

Второй: автоматизированные инструменты (Checkov, Trivy, Hadolint, semgrep) покрывают known-bad patterns, но не покрывают организационный контекст и cross-PR зависимости. Оба слоя нужны.

Третий: pin по commit hash, не по тегу — для GitHub Actions это не рекомендация, это baseline после CVE-2025-30066. Для Docker-образов — тоже.

Скорость разработки с AI — это преимущество, которое стоит сохранить. Контроль изменений до merge — это то, что позволяет его сохранить без ночных инцидентов.

Источники

[1] Veracode — "2025 GenAI Code Security Report" — https://www.veracode.com/resources/analyst-reports/2025-genai-code-security-report/

[2] arXiv / Academic — "Understanding Security Risks of AI Agents' Dependency Updates" — https://arxiv.org/html/2601.00205v1

[3] Sysdig — "Top 21 Dockerfile best practices for container security" — https://www.sysdig.com/learn-cloud-native/dockerfile-best-practices

[4] Orca Security — "GitHub Actions Security: A Guide to Common Risks" — https://orca.security/resources/blog/github-actions-security-risks/

[5] Dark Reading — "Supply Chain Attacks Targeting GitHub Actions Increased in 2025" — https://www.darkreading.com/application-security/supply-chain-attacks-targeting-github-actions-increased-in-2025

[6] 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/

[7] CISA — "Supply Chain Compromise of Third-Party tj-actions/changed-files (CVE-2025-30066)" — https://www.cisa.gov/news-events/alerts/2025/03/18/supply-chain-compromise-third-party-tj-actionschanged-files-cve-2025-30066-and-reviewdogaction

[8] Container Security (Complete Guide 2026) — "The Complete Guide to Container Security" — https://arnav.au/2026/05/14/container-security-guide/

[9] Wiz — "GitHub Action tj-actions/changed-files supply chain attack" — https://www.wiz.io/blog/github-action-tj-actions-changed-files-supply-chain-attack-cve-2025-30066

[10] The Hacker News — "GitHub Action Compromise Puts CI/CD Secrets at Risk in Over 23,000 Repositories" — https://thehackernews.com/2025/03/github-action-compromise-puts-cicd.html

[11] OWASP — "Docker Security Cheat Sheet" — https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html

[12] GitHub Security Lab — "Keeping your GitHub Actions and workflows secure: Preventing pwn requests" — https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/

[13] Docker Docs — "Building best practices" — https://docs.docker.com/build/building/best-practices/

[14] IntelligenceX — "How to Secure Docker Containers: Best Practices for 2025" — https://blog.intelligencex.org/how-to-secure-docker-containers-best-practices-for-2025

[15] Endor Labs — "How to Detect Infrastructure as Code Misconfigurations with AI Security Code Review" — https://www.endorlabs.com/learn/how-to-detect-infrastructure-as-code-iac-misconfigurations-with-ai-security-code-review

[16] Cloudmagazin — "AI-Generated Terraform Code Is the Cloud Stack's Biggest Unspoken Risk" — https://www.cloudmagazin.com/en/2026/04/02/ai-generated-terraform-code-is-the-cloud-stacks-biggest-unspoken-risk/

[17] Wiz — "Terraform Security Best Practices for Multi-Cloud Teams" — https://www.wiz.io/academy/application-security/terraform-security-best-practices

[18] DEV Community — "IaC Security in 2026: Terraform, Checkov, and Cloud Drift Detection" — https://dev.to/matheus_releaserun/iac-security-in-2026-terraform-checkov-and-cloud-drift-detection-5n

[19] SQL Server Science — "AI-Assisted Pull Request Reviews for Database Code" — https://www.sqlserverscience.com/ai-for-dbas/ai-assisted-pr-reviews/

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

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

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

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

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

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

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

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

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

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

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

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

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

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