DLP: Предотвращение утечки данных

Техническая документация для команд ИБ и обеспечения соответствия


Содержание

Обзор

Модуль DLP (Data Loss Prevention) в CodeGraph обеспечивает защиту от утечки конфиденциальных данных при работе с LLM. Система сканирует как входящие запросы пользователей, так и исходящие ответы LLM.

Ключевые возможности

  • 17 шаблонов по умолчанию для обнаружения конфиденциальных данных (расширяются через PatternRegistry)
  • Сканирование перед запросом — блокировка до отправки в LLM
  • Сканирование после ответа — маскирование в ответах LLM
  • 4 режима действий: BLOCK, MASK, WARN, LOG_ONLY
  • Интеграция с SIEM — отправка событий в реальном времени
  • Уведомления через веб-хуки — интеграция с внешними DLP-системами

Архитектура

Конвейер обработки

┌─────────────────────────────────────────────────────────────────────────┐
│                          ПОЛЬЗОВАТЕЛЬ                                    │
│                              │                                          │
│                              ▼                                          │
│  ┌───────────────────────────────────────────────────────────────────┐ │
│  │                    PRE-REQUEST SCANNER                             │ │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐               │ │
│  │  │ Credentials │  │    ПДн      │  │Исходный код │               │ │
│  │  │   (HIGH)    │  │  (MEDIUM)   │  │    (LOW)    │               │ │
│  │  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘               │ │
│  │         │                │                │                       │ │
│  │         └────────────────┴────────────────┘                       │ │
│  │                          │                                        │ │
│  │              ┌───────────┴───────────┐                           │ │
│  │              ▼           ▼           ▼                           │ │
│  │          [BLOCK]     [MASK]     [WARN/LOG]                       │ │
│  │              │           │           │                           │ │
│  │              │     ┌─────┴─────┐     │                           │ │
│  │              │     │ Замена на │     │                           │ │
│  │              │     │[REDACTED] │     │                           │ │
│  │              │     └─────┬─────┘     │                           │ │
│  └──────────────┼───────────┼───────────┼────────────────────────────┘ │
│                 │           │           │                              │
│                 │      ┌────┴────┐      │                              │
│                 │      ▼         ▼      │                              │
│           SIEM Event  GigaChat/Yandex   │                              │
│                               │         │                              │
│                               ▼         │                              │
│  ┌───────────────────────────────────────────────────────────────────┐ │
│  │                   POST-RESPONSE SCANNER                           │ │
│  │                          │                                        │ │
│  │              Маскирование конфиденциальных                        │ │
│  │              данных в ответе LLM                                  │ │
│  └───────────────────────────────────────────────────────────────────┘ │
│                              │                                          │
│                              ▼                                          │
│                    ОТВЕТ ПОЛЬЗОВАТЕЛЮ                                   │
└─────────────────────────────────────────────────────────────────────────┘

Категории обнаружения

1. Credentials (Учётные данные) — HIGH Severity

Шаблон Regex Описание
api_key_generic (?i)(api[_-]?key\|apikey)["\s:=]+["\']?([a-zA-Z0-9_\-]{20,})["\']? Универсальный API-ключ
aws_access_key AKIA[0-9A-Z]{16} AWS Access Key ID
aws_secret_key (?i)aws[_\s]*secret[_\s]*access[_\s]*key["\s:=]+["\']?([a-zA-Z0-9/+=]{40})["\']? AWS Secret Access Key
private_key -----BEGIN (RSA \|EC \|OPENSSH \|DSA )?PRIVATE KEY----- Приватный ключ (RSA, EC, DSA)
password_pattern (?i)(password\|passwd\|pwd)["\s:=]+["\']?([^\s"\']{8,})["\']? Пароль в конфиге/коде
bearer_token (?i)bearer\s+[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]+ JWT Bearer токен
github_token gh[pousr]_[A-Za-z0-9_]{36,} GitHub Personal Access Token

Действие по умолчанию: BLOCK

2. ПДн (Персональные данные) — MEDIUM Severity

Шаблон Regex Маска Описание
email [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,} [EMAIL] Email адрес
phone_ru (\+7\|8)?[\s\-]?\(?\d{3}\)?[\s\-]?\d{3}[\s\-]?\d{2}[\s\-]?\d{2} [PHONE] Телефон РФ
phone_us (\+1)?[\s.-]?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4} [PHONE] Телефон США
ssn \b\d{3}-\d{2}-\d{4}\b [SSN] US SSN
credit_card \b(?:\d{4}[\s-]?){3}\d{4}\b [CARD] Банковская карта
ip_address \b(?:\d{1,3}\.){3}\d{1,3}\b [IP] IPv4 адрес
passport_ru \b\d{2}\s?\d{2}\s?\d{6}\b [PASSPORT] Паспорт РФ

Действие по умолчанию: MASK

3. Исходный код — низкая критичность

Шаблон Regex Маска Описание
connection_string (?i)(jdbc\|mysql\|postgresql\|mongodb\|redis)://[^\s"\'<>]+ [CONN_STRING] Строка подключения
internal_path_unix (/home/\|/var/\|/etc/\|/opt/)[^\s"\'<>\|]+ [PATH] Unix путь
internal_path_windows [A-Z]:\\(Users\|Windows\|Program)[^\s"\'<>\|]* [PATH] Windows путь

Действие по умолчанию: WARN


Действия DLP

Иерархия приоритетов

Приоритет Действие Описание Результат
4 (макс.) BLOCK Полная блокировка Запрос отклонён, ошибка клиенту
3 MASK Маскирование Данные заменены на [REDACTED]
2 WARN Предупреждение Запрос пропущен, событие в SIEM
1 LOG_ONLY Только логирование Запись в аудит-лог

Логика выбора действия

# При множественных совпадениях выбирается максимальный приоритет
action_priority = {
    DLPAction.BLOCK: 4,
    DLPAction.MASK: 3,
    DLPAction.WARN: 2,
    DLPAction.LOG_ONLY: 1,
}

# Пример: найдены API-ключ (BLOCK) и email (MASK)
# Результат: BLOCK (приоритет 4 > 3)

Конфигурация

Базовая конфигурация (config.yaml)

security:
  enabled: true

  dlp:
    enabled: true

    # Pre-request сканирование (до отправки в LLM)
    pre_request:
      enabled: true
      default_action: WARN

    # Post-response сканирование (после получения от LLM)
    post_response:
      enabled: true
      default_action: MASK

    # Категории и паттерны
    categories:
      credentials:
        enabled: true
        action: BLOCK
        patterns: []  # Используются паттерны по умолчанию

      pii:
        enabled: true
        action: MASK
        patterns:
          - name: custom_inn
            regex: '\b\d{10,12}\b'
            mask_with: '[INN]'
            description: 'ИНН физ/юр лица'

      source_code:
        enabled: true
        action: WARN
        patterns: []

    # Пользовательские ключевые слова
    keywords:
      sensitive_terms:
        words:
          - "конфиденциально"
          - "секретно"
          - "для служебного пользования"
        case_sensitive: false

    keywords_action: LOG_ONLY

    # Webhook для внешней DLP-системы
    webhook:
      enabled: false
      endpoint: "https://dlp.company.com/api/scan"
      auth_header: "Bearer ${DLP_WEBHOOK_TOKEN}"
      timeout_seconds: 10
      notify_on:
        - BLOCK
        - WARN

Добавление пользовательских шаблонов

from src.security.dlp.patterns import PatternRegistry
from src.security.config import DLPAction, DLPConfig

# PatternRegistry принимает DLPConfig (не словарь конфигурации)
dlp_config: DLPConfig = get_security_config().dlp
registry = PatternRegistry(dlp_config)

# Добавить паттерн для ИНН
registry.add_pattern(
    category="pii",
    name="inn_ru",
    regex=r'\b\d{10,12}\b',
    action=DLPAction.MASK,
    mask_with="[INN]"
)

# Добавить ключевые слова
registry.add_keywords(
    list_name="internal_projects",
    keywords=["Project Alpha", "Codename Beta"],
    case_sensitive=False
)

Справочник API

ContentScanner

from src.security.dlp.scanner import ContentScanner, DLPBlockedException
from src.security.config import get_security_config

# Инициализация сканера
config = get_security_config()
scanner = ContentScanner(config.dlp)

# Pre-request сканирование
result = scanner.scan_request(user_prompt)

if result.blocked:
    # Запрос заблокирован
    raise DLPBlockedException(result.matches)
elif result.action == DLPAction.MASK:
    # Использовать маскированный контент
    user_prompt = result.modified_content

# Отправка в LLM...
llm_response = await llm_client.complete(user_prompt)

# Post-response сканирование
result = scanner.scan_response(llm_response)
if result.has_matches:
    # Маскирование ответа
    llm_response = result.modified_content

return llm_response

ScanResult

@dataclass
class ScanResult:
    has_matches: bool                    # Найдены ли совпадения
    matches: List[DLPMatch]              # Список совпадений
    action: DLPAction                    # Рекомендуемое действие
    modified_content: Optional[str]      # Маскированный контент (None если без маскирования)
    blocked: bool                        # Блокировать ли запрос

DLPMatch

@dataclass
class DLPMatch:
    category: str          # Категория (credentials, pii, source_code)
    pattern_name: str      # Имя паттерна
    match_type: MatchType  # REGEX или KEYWORD
    matched_text: str      # Найденный текст
    start: int             # Позиция начала
    end: int               # Позиция конца
    action: DLPAction      # Действие для этого совпадения
    mask_with: str         # Текст замены
    severity: str          # Критичность (critical, high, medium, low)

Интеграция с SIEM

События DLP

При каждом срабатывании DLP отправляется событие в SIEM через SecurityEventType. Значения типов событий используют формат с точкой в нижнем регистре (dlp.block, а не DLP_BLOCK):

{
  "event_type": "dlp.block",
  "timestamp": "2026-02-26T10:30:00.000Z",
  "severity": "CRITICAL",
  "user_id": "user_123",
  "session_id": "sess_456",
  "category": "credentials",
  "pattern_name": "aws_access_key",
  "action_taken": "BLOCK",
  "match_count": 1,
  "masked_preview": "Found AWS key: AKIA...",
  "request_path": "/api/v1/scenarios/execute",
  "ip_address": "10.0.0.50"
}

Типы событий

Событие Severity Описание
dlp.block CRITICAL Запрос заблокирован
dlp.mask WARNING Данные маскированы
dlp.warn WARNING Предупреждение
dlp.log INFO Только логирование

Интеграция через веб-хуки

Формат DLPAlert

При срабатывании DLP-события система отправляет объект DLPAlert (определён в src/security/dlp/webhook.py) через веб-хук. Структура содержит следующие поля:

{
  "alert_id": "dlp_alert_a1b2c3d4",
  "timestamp": "2026-02-26T10:30:00.000Z",
  "action": "BLOCK",
  "match_count": 1,
  "categories": ["credentials"],
  "patterns": ["aws_access_key"],
  "request_id": "req_789",
  "user_id": "user_123",
  "ip_address": "10.0.0.50",
  "severity": "critical",
  "context": {
    "request_path": "/api/v1/scenarios/execute",
    "content_type": "request"
  }
}

DLPWebhookClient отправляет уведомления на настроенный endpoint для событий, соответствующих списку notify_on.


Лучшие практики

Для настройки

  1. Начните с WARN — установите все категории в WARN для оценки ложных срабатываний
  2. Постепенно ужесточайте — переводите критичные категории в BLOCK после тестирования
  3. Настройте исключения — добавьте белый список для известных безопасных шаблонов
  4. Мониторьте SIEM — отслеживайте статистику срабатываний

Для разработчиков

  1. Не логируйте matched_text в рабочей среде без маскирования
  2. Обрабатывайте DLPBlockedException в API — возвращайте понятную ошибку
  3. Тестируйте шаблоны — используйте regex101.com для проверки

Для обеспечения соответствия

  1. Документируйте шаблоны — ведите реестр используемых шаблонов
  2. Регулярный аудит — проверяйте эффективность обнаружения
  3. Соответствие 152-ФЗ — убедитесь, что шаблоны ПДн покрывают российские типы данных

Мониторинг

События DLP отправляются через интеграцию с SIEM (см. Интеграция с SIEM). Отдельных DLP-счётчиков Prometheus нет — вся активность DLP отслеживается через типы событий SIEM (dlp.block, dlp.mask, dlp.warn, dlp.log).

Для мониторинга активности DLP:

  1. Запросы SIEM — фильтрация по event_type, начинающимся с dlp.
  2. Уведомления через веб-хуки — настройте DLPWebhookClient для оповещений в реальном времени
  3. Аудит-логи — просмотр событий DLP в журнале аудита приложения

Связанные документы


Версия: 1.2 | Март 2026