Skip to main content
Glama

mcp-server-gitlab

sensitive.ts6.34 kB
import { isGitlabUrl } from './is'; /** * 敏感内容处理工具类 * 提供对敏感内容的检测和掩码处理功能 */ export class SensitiveContentHandler { /** * 需要打码的敏感字段名称模式 */ private static readonly sensitiveFieldPatterns = [ // 路径相关 /path/i, /url/i, /link/i, /location/i, // 描述相关 /description/i, /content/i, /text/i, /body/i, /message/i, /comment/i, // 用户相关 /user/i, /author/i, /owner/i, /assignee/i, /creator/i, /email/i, // 地址相关 /address/i, /location/i, // 其他敏感信息 /token/i, /secret/i, /key/i, /password/i, /credential/i, ]; /** * 不打码的安全字段 */ private static readonly safeFields = [ 'id', 'name', 'visibility', 'state', 'status', 'createdAt', 'updatedAt', 'closedAt', 'mergedAt', 'type', 'count', 'total', 'public' ]; /** * 对敏感内容进行打码处理 * @param obj 需要处理的对象 * @returns 处理后的对象,敏感内容已被打码 */ public static maskSensitiveContent(obj: any): any { if (!obj || typeof obj !== 'object') return obj; // 如果是数组,递归处理每个元素 if (Array.isArray(obj)) { return obj.map(item => this.maskSensitiveContent(item)); } // 处理对象 const result = { ...obj }; for (const key in result) { // 跳过内部字段 if (key.startsWith('__')) continue; // 特殊处理 webUrl 字段 - 保留 GitLab URL if (key === 'webUrl' && typeof result[key] === 'string') { // 如果是 GitLab URL,保持原样 if (isGitlabUrl(result[key])) { // 保留原值 console.log(`保留 GitLab URL: ${result[key]}`); } else { // 非 GitLab URL,打码处理 try { const url = new URL(result[key]); const origin = url.origin; result[key] = `${origin}/***`; } catch (error) { // URL 解析失败时,将整个值打码 result[key] = '***'; } } continue; } // 如果是安全字段,不处理 if (this.safeFields.includes(key)) { continue; } const value = result[key]; // 如果值是对象或数组,递归处理 if (value && typeof value === 'object') { result[key] = this.maskSensitiveContent(value); } // 处理字符串值 else if (typeof value === 'string') { // 检查是否是敏感字段或包含敏感内容 const isSensitiveField = this.sensitiveFieldPatterns.some(pattern => pattern.test(key)); const containsSensitiveContent = this.containsSensitiveContent(value); // 如果是敏感字段或包含敏感内容,则打码 if (isSensitiveField || containsSensitiveContent) { // 保留前后两位,中间打码处理 if (typeof value === 'string' && value.length > 4) { const prefix = value.substring(0, 2); const suffix = value.substring(value.length - 2); result[key] = `${prefix}***${suffix}`; } else { // 对于短字符串,仍然全部打码 result[key] = '***'; } } } } return result; } /** * 检查字符串是否包含敏感内容 * @param str 要检查的字符串 * @returns 是否包含敏感内容 */ public static containsSensitiveContent(str: string): boolean { // 检查是否是 GitLab URL if (isGitlabUrl(str)) { return false; // GitLab URL 不视为敏感内容 } // 从环境变量获取 GitLab 域名 const gitlabHost = process.env.GITLAB_API_URL?.replace(/^https?:\/\//, '').split('/')[0] || "git.xxx.com"; // 检查是否包含 GitLab 域名 try { // 如果字符串包含 GitLab 域名,也不视为敏感内容 if (str.includes(gitlabHost)) { return false; } } catch (error) { // 忽略错误,继续检查其他敏感内容模式 } // 敏感内容模式 const sensitivePatterns = [ // 邮箱 /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/, // URL (非 GitLab 域名的 URL) new RegExp(`https?:\\/\\/(?!${gitlabHost.replace(/\./g, '\\.')})[^\\s]+`), // 路径 (排除常见的 GitLab 路径格式) /\/(?!api\/v\d|projects\/\d+|merge_requests|issues|pipelines|commits)[\w\/-]+/, // IP 地址 /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/, // 可能的用户名 (排除常见的 GitLab 用户引用) /@(?!gitlab|git)[\w-]+/, // 电话号码 /(\+\d{1,3})?[\s-]?\d{3,4}[\s-]?\d{3,4}[\s-]?\d{3,4}/, ]; return sensitivePatterns.some(pattern => pattern.test(str)); } /** * 递归处理嵌套对象 * @param obj 需要处理的对象 * @param processFunc 处理对象的回调函数 */ public static processNestedObjects(obj: any, processFunc: (obj: any) => any): void { if (!obj || typeof obj !== 'object') return; // 处理数组 if (Array.isArray(obj)) { for (let i = 0; i < obj.length; i++) { // 跳过 null 或 undefined 值 if (obj[i] == null) continue; // 先检查当前对象是否需要处理 const processed = processFunc(obj[i]); if (processed !== obj[i]) { // 如果对象被处理,则替换它 obj[i] = processed; } else if (typeof obj[i] === 'object') { // 否则继续递归处理 this.processNestedObjects(obj[i], processFunc); } } return; } // 处理对象属性 for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { // 跳过 null 或 undefined 值 if (obj[key] == null) continue; if (typeof obj[key] === 'object') { // 先检查当前对象是否需要处理 const processed = processFunc(obj[key]); if (processed !== obj[key]) { // 如果对象被处理,则替换它 obj[key] = processed; } else { // 否则继续递归处理 this.processNestedObjects(obj[key], processFunc); } } } } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ZephyrDeng/mcp-server-gitlab'

If you have feedback or need assistance with the MCP directory API, please join our Discord server