MLSecRecommendations
Глава 04 · MLOps жизненный цикл

Рекомендации ИБ: Этап 2 - Операции с моделями (Model Operations)

~44 мин44 мин осталось 9 798 словОбновлено 13 мая 2026 г.MLflowBanditpip-auditARTSafeTensorssupply chain

Рекомендации ИБ: Этап 2 - Операции с моделями (Model Operations)

Версия: 2.0 · Обновлено: 2026-04-23 · Теги: MLflow, Bandit, pip-audit, ART, SafeTensors, supply chain, adversarial training · Tier: 1-4

TL;DR. Безопасное обучение и хранение моделей: реестр MLflow, подпись артефактов, SafeTensors вместо pickle, adversarial testing (ART, CleverHans), ModelScan/picklescan для входных чекпоинтов. Этап 2 - последняя точка до production, где можно отсечь скомпрометированные веса.

Навигация: Разделы 1-3 - архитектура, требования · Раздел 4 - CI/CD gates · Раздел 5 - Model Security Card · Разделы 6-7 - чек-лист, ошибки · Раздел 8 (новый) - интерактивные сценарии supply chain атак · Раздел 10 (новый) - "С чего начать по вашей роли" (7 ролей × Day 1 / Week 1 / Month 1).

1. Краткое содержание этапа

Безопасный цикл Model Operations

flowchart LR
    A["Выбор алгоритма<br/>+ threat model"] --> B["Обучение<br/>изолированная sandbox"]
    B --> C["Adversarial training<br/>ART / TextAttack"]
    C --> D["Оценка<br/>metrics + bias + robustness"]
    D --> GATE{"Security<br/>gates"}
    GATE -- pass --> E["Подпись артефакта<br/>SafeTensors + Sigstore"]
    GATE -- fail --> B
    E --> F["Model Registry<br/>MLflow / Vertex AI"]
    F --> G["Model Card<br/>+ SBOM + provenance"]
    G --> H["CI/CD pipeline<br/>canary + rollback"]

Этап 2 охватывает полный цикл работы с моделью: от выбора алгоритма до регистрации готового артефакта в Model Registry. На этом этапе модель проходит через следующие фазы:

Фаза Описание Ключевые риски ИБ
Выбор алгоритма Определение архитектуры модели с учётом требований бизнеса и безопасности Model inversion, скрытое поведение (backdoor), утечка градиентов при federated learning
Обучение Тренировка модели на подготовленных данных, включая adversarial training и RLHF Poisoning через adversarial-примеры, утечка данных из train в validation, подмена гиперпараметров
Оценка Функциональное и security-тестирование, трекинг экспериментов Пропуск уязвимых версий в production, недостаточное покрытие adversarial-тестами
Регистрация Версионирование и документирование модели в Model Registry Отсутствие provenance, неподписанные артефакты, вредоносный код в сериализованных моделях
CI/CD Автоматизация pipeline с обязательными security gates Обход gates, недостаточная изоляция среды, избыточные привилегии сервис-аккаунтов

Принцип этапа: модель не продвигается в staging или production без прохождения всех security gates. Безопасность является обязательным критерием качества наравне с метриками точности.


2. Верификация инструментов

Все инструменты, используемые на данном этапе, прошли предварительную верификацию по критериям: лицензионная чистота, возможность self-hosted развёртывания, активность сообщества и поддержка.

2.1. ART (Adversarial Robustness Toolbox)

Параметр Значение
Разработчик IBM Research
Лицензия Apache 2.0
Репозиторий github.com/Trusted-AI/adversarial-robustness-toolbox
Поддерживаемые фреймворки TensorFlow, Keras, PyTorch, scikit-learn, XGBoost, LightGBM, MXNet
Типы атак Evasion (FGSM, PGD, C&W, DeepFool), Poisoning, Extraction, Inference
Self-hosted Да, Python-пакет, не требует внешних зависимостей

Назначение в контексте этапа: генерация adversarial-примеров для тестирования устойчивости модели, проведение membership inference атак, adversarial training.

Рекомендация ИБ: использовать ART как основной инструмент adversarial-тестирования. Минимальный набор проверок: FGSM (epsilon=0.1, 0.2, 0.3), PGD (iterations=40), Membership Inference. Для NLP-моделей дополнительно использовать TextAttack.

2.2. MLflow

Параметр Значение
Разработчик Databricks / LF AI & Data Foundation
Лицензия Apache 2.0
Компоненты Tracking, Projects, Models, Model Registry
Self-hosted Да, поддерживает PostgreSQL/MySQL + S3/MinIO/NFS для артефактов

Назначение в контексте этапа: трекинг экспериментов (параметры, метрики, артефакты), версионирование моделей, управление lifecycle (Staging -> Production -> Archived).

Рекомендация ИБ:

  • Развернуть MLflow Tracking Server в изолированном контуре с аутентификацией.
  • Настроить RBAC: ML-инженеры - запись экспериментов, SecOps - управление тегами безопасности, Compliance - только чтение.
  • Хранилище артефактов (S3/MinIO) должно иметь шифрование at-rest и версионирование объектов.
  • Все переходы между стадиями (None -> Staging -> Production) должны требовать approval от SecOps.

2.3. Bandit

Параметр Значение
Лицензия Apache 2.0
Тип SAST (Static Application Security Testing) для Python
Репозиторий github.com/PyCQA/bandit
Покрытие Обнаружение небезопасных вызовов (pickle.load, eval, exec, subprocess), hardcoded credentials, слабые хэши

Назначение в контексте этапа: статический анализ Python-кода обучения и инференса на предмет уязвимостей.

Рекомендация ИБ: запускать Bandit на каждый коммит в CI/CD. Обязательные проверки:

  • B301 (pickle) - критически важно для ML, где pickle используется повсеместно;
  • B602, B603 (subprocess) - предотвращение command injection;
  • B105, B106, B107 (hardcoded passwords) - ключи API, токены MLflow.
  • Настроить severity threshold: bandit -r . -ll (medium и выше блокируют pipeline).

2.4. pip-audit

Параметр Значение
Разработчик Trail of Bits (при поддержке PyPA)
Лицензия Apache 2.0
Тип SCA (Software Composition Analysis)
Источники данных PyPI Advisory Database, OSV (Open Source Vulnerability)

Назначение в контексте этапа: проверка зависимостей Python-проекта на известные уязвимости (CVE).

Рекомендация ИБ:

  • Запускать pip-audit на каждый коммит и перед каждым обучением.
  • Для критичных проектов: pip-audit --strict --desc - блокировка при любой уязвимости.
  • Интегрировать с requirements.txt и pyproject.toml.
  • Периодический (еженедельный) audit уже задеплоенных зависимостей.

2.5. Trivy

Параметр Значение
Разработчик Aqua Security
Лицензия Apache 2.0
Язык Go
Возможности Сканирование Docker-образов, файловых систем, Kubernetes, IaC (Terraform, Dockerfile)

Назначение в контексте этапа: сканирование Docker-образов обучения и инференса на CVE, misconfiguration.

Рекомендация ИБ:

  • Сканировать все базовые образы (nvidia/cuda, python, pytorch) перед использованием.
  • Настроить severity threshold: trivy image --severity HIGH,CRITICAL --exit-code 1.
  • Использовать --ignore-unfixed только в обоснованных случаях с документированным risk acceptance.
  • Вести приватный реестр верифицированных базовых образов.

2.6. Anchore Engine

Параметр Значение
Разработчик Anchore, Inc.
Лицензия Apache 2.0
Возможности Глубокий анализ Docker-образов, policy enforcement, SBOM generation

Назначение в контексте этапа: дополняет Trivy углублённым анализом содержимого образов и policy-based enforcement.

Рекомендация ИБ:

  • Использовать для генерации SBOM (Software Bill of Materials) всех ML-образов.
  • Настроить policy bundles: запрет на latest теги, обязательное наличие HEALTHCHECK, запрет на root-пользователя.
  • Интегрировать с Model Registry: SBOM привязывается к версии модели.

2.7. Checkov

Параметр Значение
Разработчик Prisma Cloud (Palo Alto Networks)
Лицензия Apache 2.0
Тип SAST/SCA для IaC
Покрытие Terraform, Kubernetes manifests, Dockerfile, Helm, CloudFormation

Назначение в контексте этапа: проверка конфигураций инфраструктуры обучения (Kubernetes, Terraform) на соответствие best practices безопасности.

2.8. OpenAI Evals

Параметр Значение
Разработчик OpenAI
Лицензия Apache 2.0 (по состоянию на момент публикации - проверять актуальную лицензию)
Назначение Фреймворк оценки LLM по параметрам: точность, токсичность, утечка данных, следование инструкциям

Рекомендация ИБ: применять для LLM-моделей как дополнительный gate: проверка на jailbreak-устойчивость, токсичность выходных данных, утечку PII из обучающего набора.

2.9. TRL (Transformer Reinforcement Learning)

Параметр Значение
Разработчик Hugging Face
Лицензия Apache 2.0
Методы PPO, Юрист, ORPO, KTO
Назначение RLHF для дообучения LLM с учётом предпочтений и безопасности

Рекомендация ИБ: при использовании RLHF обязательно включать в reward model штраф за генерацию PII, токсичного контента и конфиденциальных данных. Датасет для reward model должен проходить те же проверки, что и основной обучающий набор (см. Этап 1).


3. Рекомендации ИБ

3.1. Обязательный adversarial testing перед promotion

Требование: ни одна модель не может быть переведена из стадии None в Staging или из Staging в Production без прохождения adversarial-тестирования.

Минимальный набор тестов:

Тип модели Обязательные тесты Инструмент
CV (классификация изображений) FGSM (eps=0.1, 0.2, 0.3), PGD (iter=40, eps=0.3), C&W (L2) ART
NLP (классификация текста) TextBugger, DeepWordBug, TextFooler TextAttack + ART
Табличные данные HopSkipJump, ZOO ART
LLM (генеративные) Jailbreak prompts, prompt injection, PII extraction OpenAI Evals, Garak

Критерий прохождения:

  • Для evasion attacks: снижение accuracy на adversarial-примерах не более чем на 15% по сравнению с clean test set. Порог определяется совместно ML-инженерами и SecOps для каждого проекта.
  • Если порог превышен - модель блокируется и возвращается на adversarial training.

Пример интеграции в pipeline:

from art.attacks.evasion import FastGradientMethod, ProjectedGradientDescent
from art.estimators.classification import PyTorchClassifier

# Оборачиваем модель для ART
classifier = PyTorchClassifier(
    model=model,
    loss=loss_fn,
    optimizer=optimizer,
    input_shape=(3, 224, 224),
    nb_classes=10,
)

# FGSM
fgsm = FastGradientMethod(estimator=classifier, eps=0.2)
x_adv_fgsm = fgsm.generate(x=x_test)
acc_fgsm = evaluate(classifier, x_adv_fgsm, y_test)

# PGD
pgd = ProjectedGradientDescent(estimator=classifier, eps=0.3, max_iter=40)
x_adv_pgd = pgd.generate(x=x_test)
acc_pgd = evaluate(classifier, x_adv_pgd, y_test)

# Gate criterion
THRESHOLD = 0.85 * clean_accuracy
assert acc_fgsm >= THRESHOLD, f"FGSM test failed: {acc_fgsm} < {THRESHOLD}"
assert acc_pgd >= THRESHOLD, f"PGD test failed: {acc_pgd} < {THRESHOLD}"

mlflow.log_metric("adversarial_acc_fgsm", acc_fgsm)
mlflow.log_metric("adversarial_acc_pgd", acc_pgd)
mlflow.set_tag("security.adversarial_test", "passed")

Какие adversarial-атаки тестировать вашу модель

{
  "id": "ch04-adv-attacks",
  "title": "Подбор adversarial-test suite под тип модели",
  "start": "q1",
  "nodes": {
    "q1": {
      "type": "question",
      "text": "Какой тип модели вы выводите в production?",
      "sub": "От типа модели зависит набор атак, инструменты и метрики прохождения. Tier-1 модели — расширенный набор; для прототипов — минимум.",
      "choices": [
        { "label": "CV: классификация / детекция / сегментация изображений", "next": "q2-cv" },
        { "label": "NLP: классификация / NER / sentiment текста", "next": "leaf-nlp" },
        { "label": "Табличные данные: скоринг / классификация / регрессия", "next": "leaf-tabular" },
        { "label": "LLM: генеративная (chat / code / RAG)", "next": "q2-llm" },
        { "label": "Multimodal: VLM / audio + text / vision-LLM", "next": "leaf-multimodal" }
      ]
    },
    "q2-cv": {
      "type": "question",
      "text": "Это white-box scenario (атакующий знает архитектуру и веса)?",
      "sub": "В реальности часто гибрид: архитектура известна (ResNet50, EfficientNet), веса — нет. Тестируйте оба сценария.",
      "choices": [
        { "label": "Да — open-weight модель или модель с доступным API + извлекаемой архитектурой", "next": "leaf-cv-whitebox" },
        { "label": "Нет — модель только за inference API (black-box)", "next": "leaf-cv-blackbox" }
      ]
    },
    "q2-llm": {
      "type": "question",
      "text": "Какой основной риск для бизнеса?",
      "choices": [
        { "label": "Jailbreak / обход системного промпта (репутационный + compliance)", "next": "leaf-llm-jailbreak" },
        { "label": "Утечка training data / system prompt (приватность)", "next": "leaf-llm-leak" },
        { "label": "Prompt injection через RAG / tool calls (агентские риски)", "next": "leaf-llm-injection" }
      ]
    },
    "leaf-cv-whitebox": {
      "type": "leaf",
      "tone": "warn",
      "title": "White-box CV: расширенный suite",
      "summary": "Полный gradient-based набор: FGSM, PGD, C&W, AutoAttack. Метрика — robust accuracy на ε-perturbation budget; нижний bound через certified defenses (randomized smoothing).",
      "details": [
        "FGSM (ε=0.03, 0.06, 0.1): быстрая baseline-проверка",
        "PGD (40+ iters, ε=0.03): золотой стандарт",
        "AutoAttack: ансамбль 4 атак, оценивает true robustness — ниже всех остальных",
        "C&W (L2): для proof-of-concept в Tier-1 моделях",
        "Critical Tier-1: certified accuracy через CROWN-IBP, randomized smoothing (Gaussian noise σ=0.25)"
      ],
      "links": [
        { "label": "Глава 07. Red Teaming methods", "href": "/ch/07-red-teaming-testing-methods" }
      ]
    },
    "leaf-cv-blackbox": {
      "type": "leaf",
      "tone": "info",
      "title": "Black-box CV: query-efficient атаки",
      "summary": "Реалистичный сценарий через API. Атакующий ограничен числом запросов (typical budget: 10⁴–10⁵). Тестируйте на фиксированном бюджете.",
      "details": [
        "HopSkipJump: query-efficient, без gradients",
        "Boundary attack: декрементальный поиск минимальной перturbации",
        "Square Attack: state-of-the-art black-box (≥AutoAttack для same budget)",
        "Defense: rate limiting per-IP/per-token, anomaly detection на patterns probing"
      ]
    },
    "leaf-nlp": {
      "type": "leaf",
      "tone": "info",
      "title": "NLP-классификация: текстовые adversarial-атаки",
      "summary": "Текст — дискретный, поэтому gradient-based атаки не работают напрямую. Используйте character-level и synonym-based атаки.",
      "details": [
        "TextAttack ансамбль: TextFooler (synonym), DeepWordBug (typo), BERT-Attack",
        "Метрика: accuracy drop при maximum 10% modified tokens",
        "Robustness: adversarial training через TextAttack training augmentation",
        "Для русского: Natasha + DeepPavlov synonym lookup; стандартные library’и работают только на английском"
      ]
    },
    "leaf-tabular": {
      "type": "leaf",
      "tone": "info",
      "title": "Табличные модели: HopSkipJump + ZOO",
      "summary": "Часто игнорируется, но table-данные тоже подвержены evasion (особенно при integer/categorical constraints). Тестируйте на реалистичных perturbation-бюджетах.",
      "details": [
        "ART HopSkipJump для black-box scenario",
        "Constraint-aware perturbations: численные поля — Δ ≤ 5%, категориальные — флипы только в feasible category",
        "Особенно важно для скоринга: атака может стоить копейки в реальном мире (изменить декларируемую сумму на $100 — обойти fraud detection)"
      ]
    },
    "leaf-multimodal": {
      "type": "leaf",
      "tone": "err",
      "title": "VLM / multimodal: расширенная поверхность атаки",
      "summary": "Multimodal модели уязвимы к adversarial perturbation в любой из модальностей + к cross-modal injection (изображение с скрытыми инструкциями).",
      "details": [
        "Visual injection: текст в изображении (OCR-readable + invisible через alpha-channel)",
        "Adversarial patches: локализованная perturbation в углу изображения, активирующая backdoor",
        "Audio: imperceptible perturbations в спектре (CommanderSong, Carlini-Wagner audio)",
        "Защита: pre-process pipeline (re-encode lossy + OCR-scan + sanitization), а не только output filter"
      ],
      "links": [
        { "label": "Глава 26. Multimodal CV security", "href": "/ch/26-multimodal-cv-security" },
        { "label": "Глава 27. Voice AI security", "href": "/ch/27-voice-ai-security" }
      ]
    },
    "leaf-llm-jailbreak": {
      "type": "leaf",
      "tone": "err",
      "title": "LLM jailbreak: garak + PyRIT + Promptfoo",
      "summary": "Тестируйте против известных техник + custom-набор под ваш системный промпт. Для Tier-1 — continuous red teaming, не одноразовая проверка.",
      "details": [
        "Garak (NVIDIA): probes для DAN, leetspeak, multi-turn jailbreak; 50+ детекторов",
        "PyRIT (Microsoft): orchestrators для adversarial conversations, multi-turn",
        "Promptfoo: regression тестинг — фиксированный набор jailbreak-промптов в CI",
        "2025 техники: Crescendo (multi-turn gradual), Skeleton Key, Policy Puppetry"
      ],
      "links": [
        { "label": "Глава 11. Чат-боты", "href": "/ch/11-chatbot-conversational-security" }
      ]
    },
    "leaf-llm-leak": {
      "type": "leaf",
      "tone": "warn",
      "title": "LLM data leak: extraction tests",
      "summary": "Тестируйте на восстановление training data и system prompt. Метрики — exact match рейт при probing.",
      "details": [
        "Training Data Extraction: probing с префиксами из подозреваемых документов",
        "System Prompt Leak: классические «repeat above», role-confusion атаки",
        "Membership Inference (MIA): для PII-чувствительных моделей с ART MIA tests",
        "Защита: anti-echoleak filter, output DLP, периодический re-test после fine-tune"
      ],
      "links": [
        { "label": "§3.2 Membership Inference (ниже)", "href": "#3-2-membership-inference-testirovanie-kak-gate-criterion" }
      ]
    },
    "leaf-llm-injection": {
      "type": "leaf",
      "tone": "err",
      "title": "Indirect prompt injection: RAG + agent test",
      "summary": "Самый сложный класс — атака приходит из доверенного RAG-источника или web-страницы, прочитанной агентом.",
      "details": [
        "Тестируйте инъекции в RAG-источниках, web-pages, email-сниппетах, изображениях с OCR-текстом",
        "Test suite: Garak rag-injection probes, custom Promptfoo с poisoned документами",
        "Метрика: % успешных инъекций до output guardrails / после",
        "Защита на pipeline: pre-retrieval ACL, untrusted-маркер в context window, dual-LLM pattern"
      ],
      "links": [
        { "label": "Глава 10. Agent protection", "href": "/ch/10-llm-agent-protection" },
        { "label": "Глава 16. RAG / Multimodal", "href": "/ch/16-ml-attacks-rag-multimodal" }
      ]
    }
  }
}

3.2. Membership Inference тестирование как gate criterion

Проблема: модель может «запоминать» обучающие примеры, что приводит к утечке конфиденциальных данных через API инференса. Атакующий, отправляя запросы к модели, может определить, использовалась ли конкретная запись в обучении.

Требование: перед promotion в Staging проводить Membership Inference Attack (MIA) с использованием ART.

Порядок проведения:

from art.attacks.inference.membership_inference import (
    MembershipInferenceBlackBox,
)

# Подготовка данных: равные выборки из train и test
attack = MembershipInferenceBlackBox(
    estimator=classifier,
    attack_model_type="rf",  # Random Forest как shadow model
)

# Обучение attack model
attack.fit(
    x=x_train_sample,
    y=y_train_sample,
    test_x=x_test_sample,
    test_y=y_test_sample,
)

# Оценка: может ли атакующий отличить train от test
inferred_train = attack.infer(x_train_sample, y_train_sample)
inferred_test = attack.infer(x_test_sample, y_test_sample)

# Precision атаки: чем ближе к 0.5, тем лучше (модель не "запоминает")
mi_precision = compute_precision(inferred_train, inferred_test)
assert mi_precision < 0.65, f"MIA precision {mi_precision} exceeds threshold 0.65"

mlflow.log_metric("membership_inference_precision", mi_precision)
mlflow.set_tag("security.mia_test", "passed")

Пороговое значение: precision атаки Membership Inference не должна превышать 0.65. При превышении:

  1. Применить регуляризацию (dropout, L2, label smoothing).
  2. Уменьшить количество эпох обучения.
  3. Применить дифференциальную приватность (см. п. 3.9).
  4. Повторить тестирование.

Калькулятор: trade-off Differential Privacy vs MIA AUC

{
  "id": "ch04-dp-mia",
  "title": "DP-budget ε против Membership Inference и качества модели",
  "description": "DP-обучение (Opacus / TF Privacy) защищает от MIA, но снижает accuracy. Покрутите ползунок ε, чтобы увидеть оптимальную точку. Числа — для типичной CV-классификации с DP-SGD на CIFAR-10 (Abadi et al. 2016 + последующие улучшения 2024).",
  "min": 0.1,
  "max": 20,
  "step": 0.1,
  "default": 3,
  "unit": " ε",
  "axisLabel": "Privacy budget ε (меньше = строже, больше шум)",
  "tracks": [
    { "label": "MIA AUC (атакующий, чем ниже — лучше)", "compute": "0.5 + 0.18 * (1 - Math.exp(-x/4))", "format": "fixed2", "tone": "warn", "hint": "AUC=0.5 — атакующий не отличает train от test (идеально). При ε→∞ AUC растёт до ~0.68. Threshold gate в книге: AUC < 0.65." },
    { "label": "Accuracy на test set (%)", "compute": "70 + 22 * (1 - Math.exp(-x/3))", "format": "%", "tone": "info", "hint": "Без DP типичная accuracy ≈ 92%. DP-SGD с ε=3 теряет ~3 п.п., при ε=1 — 5–8 п.п. После 2024 (DP-FTRL, DP-MF) разрыв сократился вдвое." },
    { "label": "Соответствие EU AI Act / 152-ФЗ", "compute": "x <= 1 ? 100 : (x <= 3 ? 80 : (x <= 10 ? 50 : 20))", "format": "%", "tone": "ok", "hint": "ε ≤ 1 — academic-grade, считается «strong DP» в литературе. ε ≤ 3 — industry sweet spot (Apple, Google). ε > 10 — формально DP, но аудитор может усомниться в реальной защите." }
  ],
  "regions": [
    { "from": 0.1, "to": 1, "label": "Strong DP — для медицины, биометрии, спец. категорий ПДн", "tone": "ok" },
    { "from": 1, "to": 3, "label": "Industry sweet spot — баланс privacy и utility", "tone": "info" },
    { "from": 3, "to": 10, "label": "Weak DP — приемлемо для Tier-3, потеря accuracy < 1 п.п.", "tone": "warn" },
    { "from": 10, "to": 20, "label": "Формально DP, но защита слабая — пересмотрите подход", "tone": "err" }
  ]
}

3.3. Model Provenance: полная трассировка от данных до артефакта

Требование: для каждой версии модели в Model Registry должна быть восстановимая цепочка: исходные данные -> код предобработки -> код обучения -> гиперпараметры -> артефакт модели.

Реализация через MLflow:

with mlflow.start_run() as run:
    # 1. Трассировка данных
    mlflow.log_param("dataset_name", "customer_transactions_v3")
    mlflow.log_param("dataset_hash_sha256", dataset_sha256)
    mlflow.log_param("dataset_dvc_version", "v2.3.1")
    mlflow.log_param("data_pipeline_commit", "abc123def")

    # 2. Трассировка кода
    mlflow.log_param("training_code_commit", git_commit_hash)
    mlflow.log_param("training_code_repo", repo_url)
    mlflow.log_param("preprocessing_script", "preprocess_v2.py")

    # 3. Трассировка окружения
    mlflow.log_param("python_version", sys.version)
    mlflow.log_param("torch_version", torch.__version__)
    mlflow.log_artifact("requirements.txt")
    mlflow.log_artifact("conda.yaml")

    # 4. Гиперпараметры
    mlflow.log_params({
        "learning_rate": 0.001,
        "batch_size": 64,
        "epochs": 50,
        "optimizer": "AdamW",
        "weight_decay": 0.01,
    })

    # 5. Метрики
    mlflow.log_metric("accuracy", accuracy)
    mlflow.log_metric("f1_score", f1)

    # 6. Артефакт модели
    mlflow.pytorch.log_model(model, "model")

Дополнительные требования:

  • Хранить git commit hash кода обучения - обязательно.
  • Хранить SHA-256 хэш обучающего датасета - обязательно.
  • При использовании DVC - фиксировать версию DVC и remote storage URI.
  • Логировать полный requirements.txt или conda.yaml как артефакт.

3.4. Цифровая подпись моделей

Проблема: после обучения и до деплоя модель проходит через несколько систем (Model Registry, CI/CD, container registry). На любом этапе артефакт может быть подменён.

Решение: подписывать артефакты моделей с использованием Sigstore/cosign.

Порядок реализации:

# 1. Подпись артефакта модели (OCI-совместимого)
cosign sign --key cosign.key registry.company.com/ml/fraud-detector:v2.3.1

# 2. Верификация при деплое
cosign verify --key cosign.pub registry.company.com/ml/fraud-detector:v2.3.1

# 3. Для файловых артефактов (не OCI) - подпись через cosign blob
cosign sign-blob --key cosign.key --output-signature model.sig model.onnx
cosign verify-blob --key cosign.pub --signature model.sig model.onnx

Рекомендации по управлению ключами:

  • Приватный ключ подписи хранить в HSM или Vault (HashiCorp Vault, AWS KMS, GCP KMS).
  • Публичный ключ встраивать в CI/CD pipeline для автоматической верификации при деплое.
  • Рассмотреть keyless signing через Sigstore Fulcio (привязка к OIDC-идентичности CI/CD runner).
  • Ротация ключей: не реже чем раз в 12 месяцев или при компрометации.

3.5. Сканирование сериализованных моделей на вредоносный код

Проблема: форматы сериализации Python (pickle, cloudpickle, joblib) позволяют встроить произвольный исполняемый код, который выполняется при десериализации (pickle.load()). Это один из наиболее критичных векторов атаки в ML-экосистеме.

Уязвимые форматы:

  • .pkl, .pickle - стандартный pickle
  • .pt, .pth - PyTorch (использует pickle внутри)
  • .joblib - scikit-learn
  • .npy, .npz - NumPy (при allow_pickle=True)

Безопасные альтернативы:

  • ONNX - открытый формат, не содержит исполняемого кода
  • SafeTensors (Hugging Face) - безопасная сериализация тензоров
  • TensorFlow SavedModel - protobuf-based, не использует pickle
  • PMML/PFA - для классических ML-моделей

Рекомендации:

  1. Предпочитать безопасные форматы. Для новых проектов использовать ONNX или SafeTensors вместо pickle.

  2. Сканировать pickle-файлы перед загрузкой:

    # Использование fickling для анализа pickle-файлов
    pip install fickling
    fickling --check-safety model.pkl
    
    # Использование picklescan
    pip install picklescan
    picklescan --path model.pkl
    
  3. Bandit-правило B301 выявляет вызовы pickle.load() в коде - обеспечить его обязательное включение в CI/CD.

  4. Для PyTorch: использовать torch.load(f, weights_only=True) (доступно с PyTorch 1.13+), что предотвращает выполнение произвольного кода при загрузке.

  5. Политика: модели в формате pickle, полученные из внешних источников (Hugging Face Hub, сторонние поставщики), должны проходить обязательное сканирование в изолированной среде (sandbox) перед использованием.

Форматы сериализации моделей — справочник по рискам

{
  "id": "ch04-model-formats",
  "title": "7 форматов сериализации моделей: риск, сканер, рекомендация",
  "description": "Раскройте запись — внутри: устройство формата, тип риска, инструмент сканирования и когда формат допустим в production. Используйте при выборе формата для нового проекта или при импорте от внешнего вендора.",
  "shuffle": false,
  "cards": [
    {
      "tag": "опасный",
      "front": "pickle / .pt / .pth (joblib)",
      "subFront": "Native Python serialization",
      "back": "Устройство: Python pickle protocol — fully programmable. `__reduce__` метод объекта может выполнить произвольный код при десериализации.\n\nРиск: RCE при загрузке. CVE-2022-3509 (PyTorch), регулярные находки на HF.\n\nСканер: picklescan (HF), modelscan (Protect AI), fickling (Trail of Bits) — статический анализ опасных opcode (REDUCE, INST, OBJ, GLOBAL).\n\nРекомендация: НЕ использовать pickle для моделей из внешних источников. Для собственных артефактов — `weights_only=True` (PyTorch 1.13+), не отключать!"
    },
    {
      "tag": "безопасный",
      "front": "safetensors",
      "subFront": "HF, 2022 → стандарт 2024–25",
      "back": "Устройство: бинарный формат с заголовком JSON + tensor data. Нет executable code в принципе — только tensors.\n\nРиск: zero RCE. Атаки могут быть только на содержимое весов (backdoor через сами параметры) — это уже проблема обучения, не формата.\n\nРекомендация: формат по умолчанию для новых проектов. HF использует safetensors как primary с 2024. Конвертация: `safetensors.torch.save_file()`."
    },
    {
      "tag": "относительно безопасный",
      "front": "ONNX",
      "subFront": "Cross-framework interchange",
      "back": "Устройство: protocol buffers с graph + weights. Не Python-специфичный, не выполняет код при загрузке.\n\nРиск: умеренный — известны атаки через специфические operator definitions (особенно в TF-to-ONNX), CVE-2022-23491 (ONNX Runtime).\n\nСканер: onnx checker, ONNX Runtime в read-only mode + scan для подозрительных custom ops.\n\nРекомендация: подходит для cross-framework deployment, но проверяйте версию ONNX Runtime на актуальные CVE."
    },
    {
      "tag": "относительно безопасный",
      "front": "TensorFlow SavedModel",
      "subFront": "TF native format",
      "back": "Устройство: protobuf graph + variable checkpoints. Может содержать `tf.function` с custom Python operations через ConcreteFunction.\n\nРиск: умеренный — некоторые ops в SavedModel могут выполнять file I/O и system calls (`tf.io.read_file`, lookup tables). Атака редкая, но известная.\n\nСканер: tensorflow-model-analysis для inspection, custom op enumeration через graph traversal.\n\nРекомендация: для собственных моделей безопасен; для внешних — sandbox-проверка."
    },
    {
      "tag": "безопасный",
      "front": "GGUF / GGML",
      "subFront": "llama.cpp ecosystem",
      "back": "Устройство: бинарный формат для квантизованных LLM (llama.cpp, koboldcpp, ollama). Tensor data + metadata в KV-store, без executable code.\n\nРиск: zero RCE. Возможны атаки на метаданные (имя модели, prompt template), но не на загрузку.\n\nРекомендация: безопасный формат для on-prem inference. Проверяйте источник + хеш."
    },
    {
      "tag": "опасный",
      "front": "Keras .h5 (HDF5)",
      "subFront": "Legacy Keras format",
      "back": "Устройство: HDF5-контейнер с весами + сериализованной архитектурой. Architecture может включать `Lambda` layers с pickle-кодом.\n\nРиск: RCE через Lambda layers (CVE-2022-29216). HF / TF Hub отказались от .h5 для пользовательских моделей.\n\nСканер: ручная проверка на наличие Lambda layers, otherwise статический анализ HDF5.\n\nРекомендация: НЕ использовать для внешних моделей. Для собственных — переходить на SavedModel или Keras 3 native format."
    },
    {
      "tag": "опасный",
      "front": "MLflow `mlflow.pyfunc.load_model()`",
      "subFront": "Не формат, а wrapper",
      "back": "Устройство: MLflow упаковывает модель + custom inference logic в Python wrapper. По умолчанию использует pickle для serialization.\n\nРиск: RCE через PyFunc (внутри pickle), плюс возможность load arbitrary Python из conda.yaml.\n\nКонтроль: использовать MLflow с `signature` и `input_example`, верификация подписи Sigstore Model Transparency, сканирование conda.yaml на untrusted dependencies. Modelscan поддерживает MLflow с 2024."
    }
  ]
}

3.6. Security-тесты как обязательные gates в CI/CD

Требование: security-тесты должны быть blocking gates - при их неуспешном прохождении pipeline останавливается, модель не продвигается.

Реализация: см. раздел 4 «Security Gates для CI/CD».

3.7. Model Card с секцией Security Assessment

Требование: каждая модель в Model Registry должна сопровождаться Model Card, содержащей секцию «Security Assessment». Без заполненной секции модель не может быть переведена в Production.

Подробный шаблон - см. раздел 5 «Шаблон Model Security Card».

3.8. Рекомендации по adversarial training

Цель: повысить устойчивость модели к adversarial-атакам путём включения adversarial-примеров в процесс обучения.

Методы:

Метод Описание Применимость
Vanilla Adversarial Training (Madry et al.) Генерация PGD-примеров на каждом шаге обучения, обучение на смеси clean + adversarial CV-модели, классификация
TRADES Баланс между clean accuracy и adversarial robustness через регуляризацию CV-модели, когда важна точность на clean data
Free Adversarial Training Переиспользование градиентов для генерации adversarial-примеров без дополнительных forward/backward pass Ресурсо-ограниченные среды
Adversarial Training for NLP Возмущение эмбеддингов (FreeLB, SMART) NLP-модели

Пример adversarial training с ART:

from art.defences.trainer import AdversarialTrainer
from art.attacks.evasion import ProjectedGradientDescent

# Определяем атаку для генерации adversarial-примеров
pgd_attack = ProjectedGradientDescent(
    estimator=classifier,
    eps=0.3,
    eps_step=0.01,
    max_iter=40,
)

# Adversarial Trainer: 50% clean + 50% adversarial
trainer = AdversarialTrainer(
    classifier=classifier,
    attacks=pgd_attack,
    ratio=0.5,  # доля adversarial-примеров в каждом batch
)

trainer.fit(x_train, y_train, nb_epochs=50, batch_size=128)

Рекомендации:

  • Начинать с ratio=0.3 (30% adversarial) и увеличивать при необходимости.
  • Мониторить trade-off: adversarial training снижает clean accuracy на 2-5%. Это ожидаемо и допустимо.
  • Логировать как clean accuracy, так и adversarial accuracy в MLflow.
  • Проводить adversarial training на финальном этапе обучения (fine-tuning), а не с нуля.

3.9. Рекомендации по дифференциальной приватности

Цель: гарантировать, что наличие или отсутствие одной записи в обучающем наборе не влияет существенно на выходные данные модели, тем самым защищая конфиденциальность индивидуальных записей.

Инструменты:

Инструмент Фреймворк Описание
Opacus PyTorch DP-SGD для PyTorch, поддерживает per-sample gradient clipping
TensorFlow Privacy TensorFlow/Keras DP-SGD оптимизаторы для TensorFlow
diffprivlib scikit-learn DP-версии классических ML-алгоритмов

Пример с Opacus (PyTorch):

from opacus import PrivacyEngine

# Инициализация PrivacyEngine
privacy_engine = PrivacyEngine()

model, optimizer, train_loader = privacy_engine.make_private_with_epsilon(
    module=model,
    optimizer=optimizer,
    data_loader=train_loader,
    target_epsilon=8.0,       # бюджет приватности
    target_delta=1e-5,        # вероятность утечки
    epochs=50,
    max_grad_norm=1.0,        # clipping norm
)

# Обычный цикл обучения - Opacus автоматически применяет DP-SGD
for epoch in range(50):
    for batch in train_loader:
        # ... стандартный training loop ...
        pass

# Получение итогового epsilon
epsilon = privacy_engine.get_epsilon(delta=1e-5)
mlflow.log_metric("dp_epsilon", epsilon)
mlflow.log_param("dp_delta", 1e-5)
mlflow.log_param("dp_max_grad_norm", 1.0)

Рекомендации по выбору параметров:

Параметр Рекомендация
epsilon Для высокочувствительных данных (медицина, финансы): epsilon <= 1.0. Для умеренной чувствительности: epsilon <= 8.0. Значения > 10 обеспечивают слабую приватность.
delta delta < 1/N, где N - размер обучающего набора. Типичное значение: 1e-5.
max_grad_norm Начинать с 1.0, калибровать по распределению норм градиентов.

Когда применять DP:

  • Модель обучается на персональных данных (PII, медицинские записи, финансовые транзакции).
  • Модель будет доступна через public API (риск Membership Inference).
  • Регуляторные требования (GDPR Art. 25 - Privacy by Design, ФЗ-152).

3.10. Ограничение доступа к GPU-кластерам

Требование: доступ к вычислительным ресурсам обучения (GPU-серверы, кластеры) должен быть строго контролируемым.

Меры:

  1. Аутентификация: доступ к GPU-кластерам только через корпоративный SSO с MFA. Запрет на SSH по паролю.
  2. Авторизация: RBAC на уровне namespace в Kubernetes. ML-инженеры получают доступ только к своим проектным namespace.
  3. Квоты: ResourceQuota и LimitRange для каждого namespace - предотвращение злоупотребления ресурсами и DoS.
  4. Аудит: все команды на GPU-серверах логируются (auditd, Falco). SSH-сессии записываются.
  5. Сетевая изоляция: GPU-кластер в выделенном VLAN/VPC. Доступ только через VPN или bastion host.
  6. Управление секретами: ключи API (MLflow, S3, Registry) передаются через Kubernetes Secrets или Vault, не через переменные окружения в открытом виде.

3.11. Изоляция среды обучения

Требование: для моделей, обучающихся на конфиденциальных данных (PII, коммерческая тайна, медицинские данные), среда обучения должна быть изолирована от внешних сетей.

Реализация:

flowchart TB
    NET[Интернет]
    PROXY["Proxy / Air-gap<br/>только верифицированные пакеты"]
    MIRROR["Приватный PyPI mirror<br/>Nexus / DevPI"]
    subgraph CORE[Изолированный контур обучения]
        direction LR
        TRAIN["Training Environment<br/>GPU nodes<br/>egress: deny all"]
        MLF["MLflow Tracking<br/>PostgreSQL + MinIO"]
    end
    STO["(#quot;Data Storage<br/>S3 / MinIO / NFS<br/>encryption at rest<br/>audit logging#quot;)"]

    NET --> PROXY --> MIRROR
    MIRROR --> TRAIN
    MIRROR --> MLF
    TRAIN --> STO
    TRAIN <--> MLF

Kubernetes Network Policy (пример):

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: training-isolation
  namespace: ml-training
spec:
  podSelector:
    matchLabels:
      role: training-job
  policyTypes:
    - Egress
    - Ingress
  egress:
    # Разрешить доступ только к внутренним сервисам
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: ml-platform
      ports:
        - port: 5000    # MLflow
          protocol: TCP
        - port: 9000    # MinIO
          protocol: TCP
    # DNS — обязательно, иначе резолв ml-platform-сервисов не работает
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - port: 53      # DNS
          protocol: UDP
  ingress:
    # Разрешить только от CI/CD runners
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: ci-cd

Дополнительные меры:

  • Приватный зеркало PyPI (Nexus Repository, DevPI) с только верифицированными пакетами.
  • Запрет на pip install из внешних источников на GPU-нодах.
  • Запрет на mount host filesystem (PodSecurityPolicy / PodSecurityStandards).
  • Запрет на privileged containers.
  • Seccomp/AppArmor профили для training pods.

3.12. Рекомендации по безопасному хранению моделей

Требование: артефакты моделей (веса, конфигурации, токенизаторы) должны храниться с обеспечением конфиденциальности, целостности и доступности.

Меры:

Аспект Рекомендация
Шифрование at rest AES-256 (SSE-S3, SSE-KMS для S3/MinIO). Ключи в HSM/KMS.
Шифрование in transit TLS 1.2+ для всех соединений с хранилищем. Mutual TLS для внутренних сервисов.
Контроль доступа IAM-политики с принципом least privilege. Раздельные bucket/prefix для каждого проекта.
Версионирование S3 Object Versioning включён. Запрет на delete без MFA (MFA Delete).
Аудит S3 Server Access Logging или CloudTrail. Логирование всех операций read/write/delete.
Резервное копирование Cross-region replication для production-моделей. RPO не более 1 часа.
Retention Хранить все версии production-моделей минимум 3 года (или в соответствии с регуляторными требованиями).
Целостность SHA-256 checksum для каждого артефакта, хранится в Model Registry как метаданные.

Доступ по подписке#04-stage2-model-operations

Дальше — практика и артефакты

Полная версия главы «Рекомендации ИБ: Этап 2 - Операции с моделями (Model Operations)» с готовыми артефактами, шаблонами, чек-листами и подробными процедурами доступна по подписке.

49% прочитано51% в подписке
Внутри:Шаблоны документовЧек-листыDetection-правилаCI/CD конфиги
8код-блоков28таблиц38чек-пунктов7интерактивов
  • Полный доступ ко всем главам и обновлениям 30 дней
  • Готовые playbook'и, шаблоны и runbook'и под копирование
  • Поддержка автора — paywall не для заработка, а для развития справочника

Можно отменить в любой момент. Возврат средств в первые 7 дней без вопросов.