Рекомендации ИБ: Этап 2 - Операции с моделями (Model Operations)
Рекомендации ИБ: Этап 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. При превышении:
- Применить регуляризацию (dropout, L2, label smoothing).
- Уменьшить количество эпох обучения.
- Применить дифференциальную приватность (см. п. 3.9).
- Повторить тестирование.
Калькулятор: 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-моделей
Рекомендации:
Предпочитать безопасные форматы. Для новых проектов использовать ONNX или SafeTensors вместо pickle.
Сканировать pickle-файлы перед загрузкой:
# Использование fickling для анализа pickle-файлов pip install fickling fickling --check-safety model.pkl # Использование picklescan pip install picklescan picklescan --path model.pklBandit-правило B301 выявляет вызовы
pickle.load()в коде - обеспечить его обязательное включение в CI/CD.Для PyTorch: использовать
torch.load(f, weights_only=True)(доступно с PyTorch 1.13+), что предотвращает выполнение произвольного кода при загрузке.Политика: модели в формате 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-серверы, кластеры) должен быть строго контролируемым.
Меры:
- Аутентификация: доступ к GPU-кластерам только через корпоративный SSO с MFA. Запрет на SSH по паролю.
- Авторизация: RBAC на уровне namespace в Kubernetes. ML-инженеры получают доступ только к своим проектным namespace.
- Квоты: ResourceQuota и LimitRange для каждого namespace - предотвращение злоупотребления ресурсами и DoS.
- Аудит: все команды на GPU-серверах логируются (auditd, Falco). SSH-сессии записываются.
- Сетевая изоляция: GPU-кластер в выделенном VLAN/VPC. Доступ только через VPN или bastion host.
- Управление секретами: ключи 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 как метаданные. |
Дальше — практика и артефакты
Полная версия главы «Рекомендации ИБ: Этап 2 - Операции с моделями (Model Operations)» с готовыми артефактами, шаблонами, чек-листами и подробными процедурами доступна по подписке.
- Полный доступ ко всем главам и обновлениям 30 дней
- Готовые playbook'и, шаблоны и runbook'и под копирование
- Поддержка автора — paywall не для заработка, а для развития справочника
Можно отменить в любой момент. Возврат средств в первые 7 дней без вопросов.
Упоминается в (13)
- Рекомендации ИБ: Обзор и Архитектура ML SecOps
- Рекомендации ИБ: Этап 1 - Операции с данными (Data Operations)
- Рекомендации ИБ: Этап 3 - Развертывание и обслуживание моделей (Model Deployment and Serving)
- Privacy Enhancing Technologies (PET) для MLSec
- ML Attack Atlas, RAG Security, Multimodal, Fine-tuning Supply Chain
- Глава 25. PromptOps: управление промптами как кодом
- Глава 28. Безопасность синтетических данных
- MLSec Recommendations. Индекс документов
- FAQ
- Безопасность обучающей инфраструктуры
- Глава 30. Интерпретируемость моделей для целей ИБ
- Внедрение MLSec и AI Security в российских компаниях. Практический плейбук
- Глава 29. Watermarking и attribution AI-контента