mistral-security-basics

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Mistral AI Security Basics

Mistral AI 安全基础

Overview

概述

Security best practices for Mistral AI API keys and access control.
Mistral AI API密钥与访问控制的安全最佳实践。

Prerequisites

前提条件

  • Mistral AI SDK installed
  • Understanding of environment variables
  • Access to Mistral AI console
  • 已安装Mistral AI SDK
  • 了解环境变量
  • 有权访问Mistral AI控制台

Instructions

操作步骤

Step 1: Configure Environment Variables

步骤1:配置环境变量

bash
undefined
bash
undefined

.env (NEVER commit to git)

.env (绝对不要提交到git)

MISTRAL_API_KEY=your-api-key-here
MISTRAL_API_KEY=your-api-key-here

.gitignore - Add these lines

.gitignore - 添加以下内容

.env .env.local .env.*.local *.pem *.key secrets/

**Validate .gitignore:**
```bash
.env .env.local .env.*.local *.pem *.key secrets/

**验证.gitignore配置:**
```bash

Check if .env would be committed

检查.env是否会被提交

git check-ignore .env || echo "WARNING: .env is not ignored!"
git check-ignore .env || echo "警告:.env未被忽略!"

Check for exposed secrets in history

检查历史记录中是否有暴露的密钥

git log -p --all -S 'MISTRAL_API_KEY' -- '.ts' '.js' '.py' '.env'
undefined
git log -p --all -S 'MISTRAL_API_KEY' -- '.ts' '.js' '.py' '.env'
undefined

Step 2: Secure Key Loading

步骤2:安全加载密钥

typescript
// src/config/mistral.ts
import { z } from 'zod';

const envSchema = z.object({
  MISTRAL_API_KEY: z.string().min(20, 'Invalid API key format'),
  NODE_ENV: z.enum(['development', 'staging', 'production']).default('development'),
});

export function loadMistralConfig() {
  const result = envSchema.safeParse(process.env);

  if (!result.success) {
    console.error('Environment validation failed:', result.error.format());
    throw new Error('Missing or invalid MISTRAL_API_KEY');
  }

  return result.data;
}

// Usage
const config = loadMistralConfig();
const client = new Mistral({ apiKey: config.MISTRAL_API_KEY });
typescript
// src/config/mistral.ts
import { z } from 'zod';

const envSchema = z.object({
  MISTRAL_API_KEY: z.string().min(20, 'Invalid API key format'),
  NODE_ENV: z.enum(['development', 'staging', 'production']).default('development'),
});

export function loadMistralConfig() {
  const result = envSchema.safeParse(process.env);

  if (!result.success) {
    console.error('Environment validation failed:', result.error.format());
    throw new Error('Missing or invalid MISTRAL_API_KEY');
  }

  return result.data;
}

// 使用示例
const config = loadMistralConfig();
const client = new Mistral({ apiKey: config.MISTRAL_API_KEY });

Step 3: Key Rotation Procedure

步骤3:密钥轮换流程

bash
undefined
bash
undefined

1. Generate new key in Mistral console

1. 在Mistral控制台生成新密钥

2. Test new key before rotation

2. 轮换前测试新密钥

MISTRAL_API_KEY_NEW="new-key-here" curl -H "Authorization: Bearer ${MISTRAL_API_KEY_NEW}"
https://api.mistral.ai/v1/models
MISTRAL_API_KEY_NEW="new-key-here" curl -H "Authorization: Bearer ${MISTRAL_API_KEY_NEW}"
https://api.mistral.ai/v1/models

3. Update environment variable / secrets manager

3. 更新环境变量/密钥管理器

export MISTRAL_API_KEY="${MISTRAL_API_KEY_NEW}"
export MISTRAL_API_KEY="${MISTRAL_API_KEY_NEW}"

4. Deploy with new key

4. 使用新密钥部署

5. Revoke old key in Mistral console

5. 在Mistral控制台吊销旧密钥

undefined
undefined

Step 4: Environment-Specific Keys

步骤4:环境专属密钥

EnvironmentKey TypePermissions
DevelopmentDev keyAll models, low limits
StagingStaging keyAll models, medium limits
ProductionProduction keyRequired models only
typescript
// src/config/environments.ts
interface MistralEnvConfig {
  apiKey: string;
  allowedModels: string[];
  maxTokensPerRequest: number;
}

const configs: Record<string, MistralEnvConfig> = {
  development: {
    apiKey: process.env.MISTRAL_API_KEY_DEV!,
    allowedModels: ['mistral-small-latest', 'mistral-large-latest'],
    maxTokensPerRequest: 1000,
  },
  production: {
    apiKey: process.env.MISTRAL_API_KEY_PROD!,
    allowedModels: ['mistral-small-latest'],
    maxTokensPerRequest: 4000,
  },
};

export function getEnvConfig(): MistralEnvConfig {
  const env = process.env.NODE_ENV || 'development';
  return configs[env] || configs.development;
}
环境密钥类型权限
开发环境开发密钥所有模型,限额较低
预发布环境预发布密钥所有模型,限额中等
生产环境生产密钥仅允许必要模型
typescript
// src/config/environments.ts
interface MistralEnvConfig {
  apiKey: string;
  allowedModels: string[];
  maxTokensPerRequest: number;
}

const configs: Record<string, MistralEnvConfig> = {
  development: {
    apiKey: process.env.MISTRAL_API_KEY_DEV!,
    allowedModels: ['mistral-small-latest', 'mistral-large-latest'],
    maxTokensPerRequest: 1000,
  },
  production: {
    apiKey: process.env.MISTRAL_API_KEY_PROD!,
    allowedModels: ['mistral-small-latest'],
    maxTokensPerRequest: 4000,
  },
};

export function getEnvConfig(): MistralEnvConfig {
  const env = process.env.NODE_ENV || 'development';
  return configs[env] || configs.development;
}

Step 5: Request Validation & Sanitization

步骤5:请求验证与清理

typescript
import { z } from 'zod';

const messageSchema = z.object({
  role: z.enum(['system', 'user', 'assistant']),
  content: z.string().max(100000), // Prevent huge payloads
});

const chatRequestSchema = z.object({
  model: z.enum(['mistral-small-latest', 'mistral-large-latest']),
  messages: z.array(messageSchema).min(1).max(100),
  temperature: z.number().min(0).max(1).optional(),
  maxTokens: z.number().min(1).max(4000).optional(),
});

function validateChatRequest(input: unknown) {
  return chatRequestSchema.parse(input);
}

// Usage in API endpoint
app.post('/api/chat', async (req, res) => {
  try {
    const validated = validateChatRequest(req.body);
    const response = await client.chat.complete(validated);
    res.json(response);
  } catch (error) {
    if (error instanceof z.ZodError) {
      res.status(400).json({ error: 'Invalid request', details: error.errors });
    } else {
      res.status(500).json({ error: 'Internal error' });
    }
  }
});
typescript
import { z } from 'zod';

const messageSchema = z.object({
  role: z.enum(['system', 'user', 'assistant']),
  content: z.string().max(100000), // 阻止超大负载
});

const chatRequestSchema = z.object({
  model: z.enum(['mistral-small-latest', 'mistral-large-latest']),
  messages: z.array(messageSchema).min(1).max(100),
  temperature: z.number().min(0).max(1).optional(),
  maxTokens: z.number().min(1).max(4000).optional(),
});

function validateChatRequest(input: unknown) {
  return chatRequestSchema.parse(input);
}

// 在API端点中使用
app.post('/api/chat', async (req, res) => {
  try {
    const validated = validateChatRequest(req.body);
    const response = await client.chat.complete(validated);
    res.json(response);
  } catch (error) {
    if (error instanceof z.ZodError) {
      res.status(400).json({ error: '无效请求', details: error.errors });
    } else {
      res.status(500).json({ error: '内部错误' });
    }
  }
});

Step 6: Audit Logging

步骤6:审计日志

typescript
interface AuditEntry {
  timestamp: Date;
  action: string;
  userId?: string;
  model: string;
  tokensUsed?: number;
  success: boolean;
  errorCode?: string;
  ipAddress?: string;
}

async function auditLog(entry: Omit<AuditEntry, 'timestamp'>): Promise<void> {
  const log: AuditEntry = { ...entry, timestamp: new Date() };

  // Log to your audit system
  console.log('[AUDIT]', JSON.stringify(log));

  // Optional: send to logging service
  // await loggingService.record(log);
}

// Usage
async function chatWithAudit(
  userId: string,
  messages: Message[],
  ipAddress?: string
): Promise<string> {
  const start = Date.now();
  try {
    const response = await client.chat.complete({
      model: 'mistral-small-latest',
      messages,
    });

    await auditLog({
      action: 'chat.complete',
      userId,
      model: 'mistral-small-latest',
      tokensUsed: response.usage?.totalTokens,
      success: true,
      ipAddress,
    });

    return response.choices?.[0]?.message?.content ?? '';
  } catch (error: any) {
    await auditLog({
      action: 'chat.complete',
      userId,
      model: 'mistral-small-latest',
      success: false,
      errorCode: error.status?.toString(),
      ipAddress,
    });
    throw error;
  }
}
typescript
interface AuditEntry {
  timestamp: Date;
  action: string;
  userId?: string;
  model: string;
  tokensUsed?: number;
  success: boolean;
  errorCode?: string;
  ipAddress?: string;
}

async function auditLog(entry: Omit<AuditEntry, 'timestamp'>): Promise<void> {
  const log: AuditEntry = { ...entry, timestamp: new Date() };

  // 记录到审计系统
  console.log('[AUDIT]', JSON.stringify(log));

  // 可选:发送到日志服务
  // await loggingService.record(log);
}

// 使用示例
async function chatWithAudit(
  userId: string,
  messages: Message[],
  ipAddress?: string
): Promise<string> {
  const start = Date.now();
  try {
    const response = await client.chat.complete({
      model: 'mistral-small-latest',
      messages,
    });

    await auditLog({
      action: 'chat.complete',
      userId,
      model: 'mistral-small-latest',
      tokensUsed: response.usage?.totalTokens,
      success: true,
      ipAddress,
    });

    return response.choices?.[0]?.message?.content ?? '';
  } catch (error: any) {
    await auditLog({
      action: 'chat.complete',
      userId,
      model: 'mistral-small-latest',
      success: false,
      errorCode: error.status?.toString(),
      ipAddress,
    });
    throw error;
  }
}

Security Checklist

安全检查清单

  • API key stored in environment variable (not code)
  • .env
    files in
    .gitignore
  • Different keys for dev/staging/prod
  • Input validation on all requests
  • Output sanitization before display
  • Audit logging enabled
  • Rate limiting implemented
  • Error messages don't expose internals
  • HTTPS enforced for all endpoints
  • Regular key rotation scheduled
  • API密钥存储在环境变量中(而非代码里)
  • 将.env文件添加到.gitignore
  • 开发/预发布/生产环境使用不同密钥
  • 对所有请求进行输入验证
  • 输出内容在展示前进行清理
  • 已启用审计日志
  • 已实施速率限制
  • 错误信息不暴露内部细节
  • 所有端点强制使用HTTPS
  • 已计划定期密钥轮换

Output

输出结果

  • Secure API key storage
  • Environment-specific access controls
  • Input validation
  • Audit logging enabled
  • 安全的API密钥存储
  • 环境专属访问控制
  • 输入验证
  • 已启用审计日志

Error Handling

错误处理

Security IssueDetectionMitigation
Exposed API keyGit scanning, log reviewRotate immediately, revoke old key
Injection attacksInput validationZod schemas, sanitization
Missing audit trailLog reviewImplement comprehensive logging
Excessive permissionsAccess reviewLimit models per environment
安全问题检测方式缓解措施
API密钥泄露Git扫描、日志审查立即轮换密钥,吊销旧密钥
注入攻击输入验证使用Zod schema、内容清理
缺失审计轨迹日志审查实施全面的日志记录
权限过大权限审查按环境限制可访问的模型

Examples

示例

Secrets Manager Integration (AWS)

密钥管理器集成(AWS)

typescript
import { SecretsManager } from '@aws-sdk/client-secrets-manager';

const sm = new SecretsManager({ region: 'us-east-1' });

async function getMistralApiKey(): Promise<string> {
  const secret = await sm.getSecretValue({
    SecretId: 'mistral/api-key',
  });
  return secret.SecretString!;
}
typescript
import { SecretsManager } from '@aws-sdk/client-secrets-manager';

const sm = new SecretsManager({ region: 'us-east-1' });

async function getMistralApiKey(): Promise<string> {
  const secret = await sm.getSecretValue({
    SecretId: 'mistral/api-key',
  });
  return secret.SecretString!;
}

Secrets Manager Integration (GCP)

密钥管理器集成(GCP)

typescript
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';

const client = new SecretManagerServiceClient();

async function getMistralApiKey(): Promise<string> {
  const [version] = await client.accessSecretVersion({
    name: 'projects/my-project/secrets/mistral-api-key/versions/latest',
  });
  return version.payload?.data?.toString()!;
}
typescript
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';

const client = new SecretManagerServiceClient();

async function getMistralApiKey(): Promise<string> {
  const [version] = await client.accessSecretVersion({
    name: 'projects/my-project/secrets/mistral-api-key/versions/latest',
  });
  return version.payload?.data?.toString()!;
}

Content Filtering

内容过滤

typescript
const BLOCKED_PATTERNS = [
  /\b(password|secret|key)\s*[:=]/i,
  /\b\d{16}\b/, // Credit card numbers
  /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z]{2,}\b/i, // Emails
];

function containsSensitiveData(text: string): boolean {
  return BLOCKED_PATTERNS.some(pattern => pattern.test(text));
}

async function safeChatComplete(messages: Message[]): Promise<string> {
  // Check input for sensitive data
  for (const msg of messages) {
    if (containsSensitiveData(msg.content)) {
      throw new Error('Message contains potentially sensitive data');
    }
  }

  return client.chat.complete({ model: 'mistral-small-latest', messages });
}
typescript
const BLOCKED_PATTERNS = [
  /\b(password|secret|key)\s*[:=]/i,
  /\b\d{16}\b/, // 信用卡号码
  /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z]{2,}\b/i, // 邮箱地址
];

function containsSensitiveData(text: string): boolean {
  return BLOCKED_PATTERNS.some(pattern => pattern.test(text));
}

async function safeChatComplete(messages: Message[]): Promise<string> {
  // 检查输入是否包含敏感数据
  for (const msg of messages) {
    if (containsSensitiveData(msg.content)) {
      throw new Error('消息包含潜在敏感数据');
    }
  }

  return client.chat.complete({ model: 'mistral-small-latest', messages });
}

Resources

参考资源

Next Steps

后续步骤

For production deployment, see
mistral-prod-checklist
.
如需生产部署,请参考
mistral-prod-checklist