Token导航 LogoToken导航

Agent Skill · 研究检索

security-expert(安全专家)

用于辅助安全审计、权限检查、凭据风险、认证流程和常见漏洞排查。它适合让 Agent 梳理敏感配置、检查依赖风险、分析鉴权逻辑或生成安全复核清单。使用时不能把工具输出直接当最终结论,涉及密钥、令牌、用户数据或生产系统时,应先确认最小权限、脱敏方式和操作边界。

security-expert 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为执行命令;许可证为 MIT,第三方扫描有未通过项,按安装量在研究检索类的 73,675 个 Skill 里排第 30,588。

总安装 2,856周安装 119GitHub Stars 19下载 952核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:security-expert(安全专家)
来源仓库:https://github.com/personamanagmentlayer/pcl
仓库路径:skills/security-expert
安装命令:
npx skills add https://github.com/personamanagmentlayer/pcl --skill security-expert
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/personamanagmentlayer/pcl --skill security-expert

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

用于辅助安全审计、权限检查和常见漏洞排查。security-expert 属于研究检索类 Skill,可作为该场景下的辅助能力补充。适合梳理敏感配置、分析鉴权逻辑或生成安全复核清单。通过 GitHub 安装,支持多种 AI 编程宿主环境。不能将工具输出直接作为最终结论,需人工复核。

涉及密钥、令牌或用户数据时,应先确认最小权限和操作边界。

来源仓库内路径:skills/security-expert

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/personamanagmentlayer/pcl --skill security-exp…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要执行命令,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

security-expert 怎么安装?

在终端执行 npx skills add https://github.com/personamanagmentlayer/pcl --skill security-expert。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

security-expert 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

security-expert 需要什么权限?

权限级别是执行命令。安装流程涉及命令执行,可能通过 npx skills add https://github.com/personamanagmentlayer/pcl --skill security-expert;npx skills add personamanagmentlayer/pcl --skill "security-expert" 联网下载 Skill 或依赖。用户安装前应确认命令来源、仓库内容和执行环境。

security-expert 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

security-expert 用的人多吗?

公开数据是累计安装 2,856 次,近一周安装 119 次,下载 952 次,GitHub 19 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

security-expert 安全吗?

第三方扫描有未通过项,风险较高。除非你确认过源码,否则不建议直接安装到常用环境。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。

先想清楚的地方

  • 需要执行命令,装到常用环境前要先评估影响面。
  • 第三方扫描存在提醒项或未通过项,需要人工逐条确认。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 不能接受 Skill 在你机器上执行命令的人。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
security-expert

安全专家 · 本页

2,85619执行命令MIT未通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Security Expert

Expert guidance for application security, vulnerability assessment, penetration testing, OWASP Top 10, secure coding practices, and security architecture.

Core Concepts

Security Principles

  • Defense in depth
  • Least privilege
  • Secure by default
  • Fail securely
  • Complete mediation
  • Separation of duties
  • Zero trust architecture

OWASP Top 10 (2021)

  1. Broken Access Control
  2. Cryptographic Failures
  3. Injection
  4. Insecure Design
  5. Security Misconfiguration
  6. Vulnerable and Outdated Components
  7. Identification and Authentication Failures
  8. Software and Data Integrity Failures
  9. Security Logging and Monitoring Failures
  10. Server-Side Request Forgery (SSRF)

Security Domains

  • Authentication & Authorization
  • Cryptography
  • Input validation
  • Session management
  • Error handling
  • Secure communications
  • Data protection

OWASP Top 10 Vulnerabilities

1. Broken Access Control

// ❌ Vulnerable: No authorization check
app.get('/api/users/:id/profile', async (req, res) => {
  const profile = await db.users.findById(req.params.id);
  res.json(profile);
});

// ✅ Secure: Verify user owns the resource
app.get('/api/users/:id/profile', authenticate, async (req, res) => {
  if (req.user.id !== req.params.id && !req.user.isAdmin) {
    return res.status(403).json({ error: 'Forbidden' });
  }

  const profile = await db.users.findById(req.params.id);
  res.json(profile);
});

// ✅ Better: Use middleware
const authorizeResource = (resourceType) => async (req, res, next) => {
  const resourceId = req.params.id;
  const resource = await db[resourceType].findById(resourceId);

  if (!resource) {
    return res.status(404).json({ error: 'Not found' });
  }

  if (resource.userId !== req.user.id && !req.user.isAdmin) {
    return res.status(403).json({ error: 'Forbidden' });
  }

  req.resource = resource;
  next();
};

app.delete('/api/posts/:id', authenticate, authorizeResource('posts'), async (req, res) => {
  await req.resource.delete();
  res.status(204).send();
});

2. Injection (SQL, NoSQL, Command)

// ❌ SQL Injection vulnerability
app.get('/users', (req, res) => {
  const query = `SELECT * FROM users WHERE name = '${req.query.name}'`;
  db.query(query, (err, results) => {
    res.json(results);
  });
});
// Attack: ?name=' OR '1'='1

// ✅ Secure: Use parameterized queries
app.get('/users', async (req, res) => {
  const results = await db.query(
    'SELECT * FROM users WHERE name = ?',
    [req.query.name]
  );
  res.json(results);
});

// ❌ Command Injection
const { exec } = require('child_process');
app.post('/convert', (req, res) => {
  exec(`convert ${req.body.filename} output.pdf`, (err, stdout) => {
    res.send(stdout);
  });
});
// Attack: filename="; rm -rf / #"

// ✅ Secure: Use safe APIs, validate input
const { spawn } = require('child_process');
app.post('/convert', (req, res) => {
  const filename = path.basename(req.body.filename); // Remove path traversal
  if (!/^[a-zA-Z0-9_-]+\.(jpg|png)$/.test(filename)) {
    return res.status(400).json({ error: 'Invalid filename' });
  }

  const process = spawn('convert', [filename, 'output.pdf']);
  // Handle process output safely
});

// ❌ NoSQL Injection (MongoDB)
app.post('/login', async (req, res) => {
  const user = await User.findOne({
    username: req.body.username,
    password: req.body.password
  });
});
// Attack: {"username": {"$ne": null}, "password": {"$ne": null}}

// ✅ Secure: Sanitize input, use proper types
app.post('/login', async (req, res) => {
  const { username, password } = req.body;

  if (typeof username !== 'string' || typeof password !== 'string') {
    return res.status(400).json({ error: 'Invalid input' });
  }

  const user = await User.findOne({ username });
  if (!user || !(await bcrypt.compare(password, user.passwordHash))) {
    return res.status(401).json({ error: 'Invalid credentials' });
  }

  // Create session
});

3. Cross-Site Scripting (XSS)

// ❌ Reflected XSS
app.get('/search', (req, res) => {
  res.send(`<h1>Results for: ${req.query.q}</h1>`);
});
// Attack: ?q=<script>alert(document.cookie)</script>

// ✅ Secure: Escape output
const escapeHtml = (unsafe) => {
  return unsafe
    .replace(/&/g, "&")
    .replace(/</g, "<")
    .replace(/>/g, ">")
    .replace(/"/g, """)
    .replace(/'/g, "'");
};

app.get('/search', (req, res) => {
  res.send(`<h1>Results for: ${escapeHtml(req.query.q)}</h1>`);
});

// ✅ Better: Use templating engine with auto-escaping
app.get('/search', (req, res) => {
  res.render('search', { query: req.query.q }); // Automatically escaped
});

// ✅ Content Security Policy
app.use((req, res, next) => {
  res.setHeader(
    'Content-Security-Policy',
    "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;"
  );
  next();
});

4. Cross-Site Request Forgery (CSRF)

// ❌ Vulnerable: No CSRF protection
app.post('/api/transfer', authenticate, async (req, res) => {
  await transferMoney(req.user.id, req.body.to, req.body.amount);
  res.json({ success: true });
});

// ✅ Secure: Use CSRF tokens
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });

app.get('/transfer', csrfProtection, (req, res) => {
  res.render('transfer', { csrfToken: req.csrfToken() });
});

app.post('/api/transfer', csrfProtection, authenticate, async (req, res) => {
  await transferMoney(req.user.id, req.body.to, req.body.amount);
  res.json({ success: true });
});

// ✅ Also use SameSite cookies
app.use(session({
  cookie: {
    httpOnly: true,
    secure: true,
    sameSite: 'strict'
  }
}));

5. Security Misconfiguration

// ❌ Exposed sensitive information
app.use((err, req, res, next) => {
  res.status(500).json({
    error: err.message,
    stack: err.stack  // Exposes internal details
  });
});

// ✅ Secure: Generic error messages
app.use((err, req, res, next) => {
  console.error(err); // Log internally

  if (process.env.NODE_ENV === 'production') {
    res.status(500).json({ error: 'Internal server error' });
  } else {
    res.status(500).json({ error: err.message, stack: err.stack });
  }
});

// ✅ Security headers
const helmet = require('helmet');
app.use(helmet());

// ✅ Disable unnecessary features
app.disable('x-powered-by');

// ✅ Rate limiting
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100 // limit each IP to 100 requests per windowMs
});
app.use('/api/', limiter);

Authentication & Authorization

Password Security

const bcrypt = require('bcrypt');
const SALT_ROUNDS = 12;

// Hash password
async function hashPassword(password) {
  // Validate password strength
  if (password.length < 12) {
    throw new Error('Password must be at least 12 characters');
  }

  if (!/[A-Z]/.test(password) || !/[a-z]/.test(password) ||
      !/[0-9]/.test(password) || !/[^A-Za-z0-9]/.test(password)) {
    throw new Error('Password must contain uppercase, lowercase, number, and special character');
  }

  return await bcrypt.hash(password, SALT_ROUNDS);
}

// Verify password
async function verifyPassword(password, hash) {
  return await bcrypt.compare(password, hash);
}

// Registration
app.post('/register', async (req, res) => {
  const { email, password } = req.body;

  // Check if user exists
  const existingUser = await User.findOne({ email });
  if (existingUser) {
    return res.status(400).json({ error: 'Email already registered' });
  }

  // Hash password
  const passwordHash = await hashPassword(password);

  // Create user
  const user = await User.create({
    email: email.toLowerCase(),
    passwordHash
  });

  res.status(201).json({ id: user.id });
});

JWT Authentication

const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET; // Use strong secret
const JWT_EXPIRY = '15m';
const REFRESH_TOKEN_EXPIRY = '7d';

// Generate tokens
function generateTokens(user) {
  const accessToken = jwt.sign(
    { userId: user.id, email: user.email },
    JWT_SECRET,
    { expiresIn: JWT_EXPIRY }
  );

  const refreshToken = jwt.sign(
    { userId: user.id, type: 'refresh' },
    JWT_SECRET,
    { expiresIn: REFRESH_TOKEN_EXPIRY }
  );

  return { accessToken, refreshToken };
}

// Verify token middleware
function authenticate(req, res, next) {
  const authHeader = req.headers.authorization;

  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'No token provided' });
  }

  const token = authHeader.substring(7);

  try {
    const decoded = jwt.verify(token, JWT_SECRET);
    req.user = decoded;
    next();
  } catch (err) {
    if (err.name === 'TokenExpiredError') {
      return res.status(401).json({ error: 'Token expired' });
    }
    return res.status(401).json({ error: 'Invalid token' });
  }
}

// Login
app.post('/login', async (req, res) => {
  const { email, password } = req.body;

  const user = await User.findOne({ email: email.toLowerCase() });
  if (!user || !(await verifyPassword(password, user.passwordHash))) {
    // Generic error to prevent username enumeration
    return res.status(401).json({ error: 'Invalid credentials' });
  }

  // Update last login
  await user.update({ lastLoginAt: new Date() });

  const tokens = generateTokens(user);
  res.json(tokens);
});

// Refresh token
app.post('/refresh', async (req, res) => {
  const { refreshToken } = req.body;

  try {
    const decoded = jwt.verify(refreshToken, JWT_SECRET);

    if (decoded.type !== 'refresh') {
      return res.status(401).json({ error: 'Invalid token type' });
    }

    const user = await User.findById(decoded.userId);
    if (!user) {
      return res.status(401).json({ error: 'User not found' });
    }

    const tokens = generateTokens(user);
    res.json(tokens);
  } catch (err) {
    return res.status(401).json({ error: 'Invalid refresh token' });
  }
});

Multi-Factor Authentication (MFA)

const speakeasy = require('speakeasy');
const QRCode = require('qrcode');

// Generate MFA secret
app.post('/mfa/setup', authenticate, async (req, res) => {
  const secret = speakeasy.generateSecret({
    name: `MyApp (${req.user.email})`
  });

  // Store secret temporarily
  await redis.setex(`mfa:setup:${req.user.id}`, 300, secret.base32);

  // Generate QR code
  const qrCode = await QRCode.toDataURL(secret.otpauth_url);

  res.json({
    secret: secret.base32,
    qrCode
  });
});

// Verify and enable MFA
app.post('/mfa/verify', authenticate, async (req, res) => {
  const { token } = req.body;
  const secret = await redis.get(`mfa:setup:${req.user.id}`);

  if (!secret) {
    return res.status(400).json({ error: 'MFA setup expired' });
  }

  const verified = speakeasy.totp.verify({
    secret,
    encoding: 'base32',
    token,
    window: 2
  });

  if (!verified) {
    return res.status(400).json({ error: 'Invalid token' });
  }

  // Enable MFA for user
  await User.update(req.user.id, {
    mfaEnabled: true,
    mfaSecret: secret
  });

  await redis.del(`mfa:setup:${req.user.id}`);

  res.json({ success: true });
});

// Login with MFA
app.post('/login/mfa', async (req, res) => {
  const { email, password, mfaToken } = req.body;

  const user = await User.findOne({ email });
  if (!user || !(await verifyPassword(password, user.passwordHash))) {
    return res.status(401).json({ error: 'Invalid credentials' });
  }

  if (user.mfaEnabled) {
    if (!mfaToken) {
      return res.status(401).json({ error: 'MFA token required' });
    }

    const verified = speakeasy.totp.verify({
      secret: user.mfaSecret,
      encoding: 'base32',
      token: mfaToken,
      window: 2
    });

    if (!verified) {
      return res.status(401).json({ error: 'Invalid MFA token' });
    }
  }

  const tokens = generateTokens(user);
  res.json(tokens);
});

Cryptography

Encryption at Rest

const crypto = require('crypto');

const ALGORITHM = 'aes-256-gcm';
const KEY = Buffer.from(process.env.ENCRYPTION_KEY, 'hex'); // 32 bytes

function encrypt(plaintext) {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv(ALGORITHM, KEY, iv);

  let encrypted = cipher.update(plaintext, 'utf8', 'hex');
  encrypted += cipher.final('hex');

  const authTag = cipher.getAuthTag();

  return {
    iv: iv.toString('hex'),
    encrypted,
    authTag: authTag.toString('hex')
  };
}

function decrypt(iv, encrypted, authTag) {
  const decipher = crypto.createDecipheriv(
    ALGORITHM,
    KEY,
    Buffer.from(iv, 'hex')
  );

  decipher.setAuthTag(Buffer.from(authTag, 'hex'));

  let decrypted = decipher.update(encrypted, 'hex', 'utf8');
  decrypted += decipher.final('utf8');

  return decrypted;
}

// Store sensitive data
async function storeSensitiveData(userId, data) {
  const { iv, encrypted, authTag } = encrypt(JSON.stringify(data));

  await db.sensitiveData.create({
    userId,
    iv,
    encrypted,
    authTag
  });
}

Secure Random Generation

// ✅ Cryptographically secure random
const crypto = require('crypto');

function generateSecureToken(length = 32) {
  return crypto.randomBytes(length).toString('hex');
}

function generateSecureId() {
  return crypto.randomUUID();
}

// ❌ Don't use Math.random() for security
const insecureToken = Math.random().toString(36); // Predictable!

Input Validation

const { body, validationResult } = require('express-validator');

app.post('/api/users',
  // Validation rules
  body('email').isEmail().normalizeEmail(),
  body('name').trim().isLength({ min: 2, max: 100 }).escape(),
  body('age').optional().isInt({ min: 18, max: 120 }),
  body('website').optional().isURL(),

  async (req, res) => {
    // Check validation results
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }

    // Process validated data
    const user = await User.create(req.body);
    res.status(201).json(user);
  }
);

// File upload validation
const multer = require('multer');

const upload = multer({
  limits: {
    fileSize: 5 * 1024 * 1024, // 5MB max
  },
  fileFilter: (req, file, cb) => {
    // Check file type
    const allowedMimes = ['image/jpeg', 'image/png', 'image/gif'];
    if (!allowedMimes.includes(file.mimetype)) {
      return cb(new Error('Invalid file type'));
    }

    // Check file extension
    const ext = path.extname(file.originalname).toLowerCase();
    if (!['.jpg', '.jpeg', '.png', '.gif'].includes(ext)) {
      return cb(new Error('Invalid file extension'));
    }

    cb(null, true);
  }
});

app.post('/upload', upload.single('image'), (req, res) => {
  // Verify file content matches extension
  // Store with random filename to prevent path traversal
  const filename = `${crypto.randomUUID()}${path.extname(req.file.originalname)}`;
  // Save file...
});

Security Headers

const helmet = require('helmet');

app.use(helmet({
  contentSecurityPolicy: {
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "'unsafe-inline'"], // Avoid unsafe-inline in production
      styleSrc: ["'self'", "'unsafe-inline'"],
      imgSrc: ["'self'", 'data:', 'https:'],
      connectSrc: ["'self'"],
      fontSrc: ["'self'"],
      objectSrc: ["'none'"],
      mediaSrc: ["'self'"],
      frameSrc: ["'none'"],
    },
  },
  hsts: {
    maxAge: 31536000,
    includeSubDomains: true,
    preload: true
  },
  frameguard: {
    action: 'deny'
  },
  noSniff: true,
  xssFilter: true,
}));

// Additional headers
app.use((req, res, next) => {
  res.setHeader('X-Content-Type-Options', 'nosniff');
  res.setHeader('X-Frame-Options', 'DENY');
  res.setHeader('X-XSS-Protection', '1; mode=block');
  res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
  res.setHeader('Permissions-Policy', 'geolocation=(), microphone=(), camera=()');
  next();
});

Secure Logging

const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

// Log security events
function logSecurityEvent(event, details) {
  logger.warn('Security Event', {
    event,
    ...details,
    timestamp: new Date().toISOString()
  });
}

// Failed login attempts
app.post('/login', async (req, res) => {
  const { email, password } = req.body;
  const user = await User.findOne({ email });

  if (!user || !(await verifyPassword(password, user.passwordHash))) {
    logSecurityEvent('failed_login', {
      email,
      ip: req.ip,
      userAgent: req.headers['user-agent']
    });

    return res.status(401).json({ error: 'Invalid credentials' });
  }

  // Success
  logSecurityEvent('successful_login', {
    userId: user.id,
    ip: req.ip
  });

  // Generate tokens...
});

// ❌ Don't log sensitive data
logger.info('User data', user); // May contain passwordHash, tokens

// ✅ Sanitize before logging
logger.info('User data', {
  id: user.id,
  email: user.email,
  // Omit sensitive fields
});

Best Practices

Secure Development Lifecycle

  1. Threat modeling
  2. Security requirements
  3. Secure coding standards
  4. Code review
  5. Security testing (SAST/DAST)
  6. Vulnerability scanning
  7. Penetration testing
  8. Security monitoring

Defense in Depth

  • Multiple layers of security
  • Assume breach mentality
  • Principle of least privilege
  • Input validation at every layer
  • Output encoding
  • Secure configuration

Security Testing

  • Static Application Security Testing (SAST)
  • Dynamic Application Security Testing (DAST)
  • Interactive Application Security Testing (IAST)
  • Software Composition Analysis (SCA)
  • Penetration testing
  • Bug bounty programs

Anti-Patterns to Avoid

❌ Storing passwords in plaintext: Always hash with bcrypt/argon2 ❌ Rolling your own crypto: Use established libraries ❌ Trusting user input: Validate and sanitize everything ❌ Exposing sensitive errors: Use generic error messages ❌ No rate limiting: Implement rate limiting on all endpoints ❌ Weak session management: Use secure, httpOnly cookies ❌ No logging: Log security events for monitoring ❌ Hardcoded secrets: Use environment variables

Resources

平台分布

Claude Code

29.1%
按下载量换算277

OpenCode

24.04%
按下载量换算229

Codex

15.91%
按下载量换算151

Antigravity

12.65%
按下载量换算120

Gemini CLI

8.34%
按下载量换算79

windsurf

3.19%
按下载量换算30

安全审计

Gen Agent Trust Hub

未通过

Socket

通过

Snyk

通过

权限和风险

执行命令

安装流程涉及命令执行,可能通过 npx skills add https://github.com/personamanagmentlayer/pcl --skill security-expert;npx skills add personamanagmentlayer/pcl --skill "security-expert" 联网下载 Skill 或依赖。用户安装前应确认命令来源、仓库内容和执行环境。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在提醒或未通过项,安装前请自行复核。

继续浏览同类 Skills