mcpField
S
security-trust

security-trust

github.com/bartwaardenburg安全0176 次安装1 周前更新
代码仓库

关于 security-trust

用于修复 IsAgentReady.com「Security & Trust」检查项的技能,面向维护网站的人员。它涵盖安全响应头、API CORS、WebMCP 工具定义、表单行为和 OAuth 元数据,并提供验证命令。

主要功能

  1. 01修复 HTTPS 和安全响应头
  2. 02配置 API CORS 策略
  3. 03检查 WebMCP 工具定义
  4. 04审查表单自动提交风险
  5. 05发布 OAuth 元数据与认证说明
  6. 06提供只读验证命令

适用场景

  1. 01处理 Security & Trust 扫描失败项
  2. 02为 Web 服务器补充响应头
  3. 03按来源限制 API 访问
  4. 04为 Agent 准备网站认证

MCP 相关

涉及 WebMCP 工具定义和 Agent 认证就绪度的安全检查;它是修复技能,不是 MCP 服务。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bartwaardenburg/isagentready-skills --skill security-trust

安装后在 Claude Code 中输入/security-trust确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
checkpoints.md
gotchas.md
security-headers.md
server-configs.md

详细介绍

安全与信任

修复 IsAgentReady.com 的“安全与信任”类别。这些检查点会测试 Agent 协议所需的安全基线,以及 Agent 用于登录的身份验证元数据。

适用场景

  • 扫描结果显示“安全与信任”类别存在失败项(旧版 ID 为 5.x)。
  • 缺少 HTTPS、HSTS、CSP 或其他安全标头。
  • 公共 API 需要正确的 CORS 策略。
  • WebMCP 工具定义包含机密信息,或会自动提交存在风险的表单。
  • 网站设有登录功能,且 Agent 必须能够找到 OAuth 元数据。

不适用场景

  • robots.txt 或爬虫访问:使用 ai-content-discovery。
  • JSON-LD:使用 structured-data。
  • 语义化 HTML:使用 content-semantics。
  • MCP、A2A 或 OpenAPI 文档:使用 agent-protocols。

说明

  1. 从扫描结果中获取失败的检查点。每项结果都有一个旧版 ID(5.3)和一个稳定 ID(ia.hsts)。
  2. 对于标头检查点(5.1 至 5.9),使用 references/server-configs.md 中的一种服务器配置。该配置会一次性修复所有标头。
  3. 对于其他检查点,跳转到与稳定 ID 相同的锚点对应的修复工作流。
  4. 将 example.com 替换为网站的域名。运行验证命令。所有验证命令均为只读操作。
  5. 使用 isagentready results <domain> --checkpoint <stable-id> 重新扫描,或前往 isagentready.com。

如果提供了 $ARGUMENTS,请将其用作要修复的网址或检查点。

检查点

强度代表 agentready.org 规范级别(MUST、SHOULD、MAY)。强度不会改变评分。

旧版稳定 ID名称AR ID强度
5.1ia.httpsHTTPS无MUST
5.3ia.hstsHSTS无MUST
5.4ia.cspContent-Security-Policy无MUST
5.5ia.x-content-type-optionsX-Content-Type-Options无MUST
5.6ia.frame-protectionX-Frame-Options / frame-ancestors无MUST
5.7ia.corsCORS无MAY
5.9ia.referrer-policyReferrer-Policy无MUST
5.10ia.tool-definition-security工具定义安全性无MAY
5.11ia.auto-submit-risk自动提交风险无MAY
5.12ia.oauth-discoveryOAuth 发现AR-ACT-01SHOULD
5.13ia.oauth-protected-resourceOAuth 受保护资源AR-ACT-01SHOULD
5.14ia.agent-auth-readinessAgent 身份验证就绪状态AR-ACT-01SHOULD

一次性配置所有标头

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-ancestors 'none'" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

使用 always,这样 Nginx 也会在 3xx、4xx 和 5xx 响应中发送这些标头。Apache、Caddy、Vercel、Netlify、Cloudflare、Express、Next.js 和 Django 的配置见 references/server-configs.md。

验证所有标头:curl -sfI https://example.com/ | grep -iE '^(strict-transport|content-security|x-content-type|x-frame|referrer-policy)'

修复工作流

5.1 HTTPS

重定向后的最终 URL 使用 https:// 且证书有效时,即通过检查。

  1. 获取证书。使用 Let's Encrypt 和 Nginx 时:sudo certbot --nginx -d example.com -d www.example.com。
  2. 将 HTTP 重定向到 HTTPS:
    server { listen 80; server_name example.com; return 301 https://$host$request_uri; }
    

验证:curl -sfI https://example.com/ | head -1

5.3 HSTS

当 Strict-Transport-Security 的 max-age 为 31536000 或更高时通过。设置 includeSubDomains 更佳。较短的 max-age 可获得部分分数。

  1. 添加标头:add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
  2. 所有子域名都使用 HTTPS 时,添加 preload 并在 hstspreload.org 提交域名。

验证:curl -sfI https://example.com/ | grep -i '^strict-transport-security'

5.4 Content-Security-Policy

当 CSP 包含有效指令时通过。仅包含 upgrade-insecure-requests 的 CSP 可获得部分分数。

  1. 先启用仅报告模式,以查明网站所需的来源:
    add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' https://www.googletagmanager.com; report-uri /csp-report" always;
    
  2. 报告没有问题后,改为 Content-Security-Policy。有关 nonce,请参阅 references/security-headers.md。

验证:curl -sfI https://example.com/ | grep -i '^content-security-policy'

5.5 X-Content-Type-Options

当值恰好为 nosniff 时通过。

  1. 添加标头:add_header X-Content-Type-Options "nosniff" always;

验证:curl -sfI https://example.com/ | grep -i '^x-content-type-options: nosniff'

5.6 X-Frame-Options / frame-ancestors

当 X-Frame-Options 为 DENY 或 SAMEORIGIN,或 CSP 包含 frame-ancestors 时通过。

  1. 在 CSP 中添加 frame-ancestors 'none',或添加 add_header X-Frame-Options "DENY" always;。
  2. 必须允许受信任的网站嵌入页面时,使用 frame-ancestors 'self' https://partner.example。不要使用 ALLOW-FROM。

验证:curl -sfI https://example.com/ | grep -iE '^x-frame-options|frame-ancestors'

5.7 CORS

适用于 4.19 验证的公共 API 操作。当预检请求和 GET 返回相同的 Access-Control-Allow-* 标头、不在携带凭据时使用通配符,并且动态来源配置了 Vary: Origin 时通过。

  1. 预检请求和 GET 使用相同的策略进行响应:
    const allowed = new Set(["https://app.example.com", "https://agent.example"]);
    app.use("/api", (req, res, next) => {
      const origin = req.get("Origin");
      if (allowed.has(origin)) res.set({ "Access-Control-Allow-Origin": origin, Vary: "Origin" });
      res.set({ "Access-Control-Allow-Methods": "GET", "Access-Control-Allow-Headers": "Accept" });
      return req.method === "OPTIONS" ? res.sendStatus(204) : next();
    });
    
  2. 对于不使用 Cookie 的公共 API,Access-Control-Allow-Origin: * 是正确的。绝不要将 * 与 Access-Control-Allow-Credentials: true 组合使用。

验证:curl -sI -H 'Origin: https://agent.example' https://example.com/api | grep -iE '^(access-control-|vary)'

5.9 Referrer-Policy

当存在 Referrer-Policy 且其值不是 unsafe-url 时通过。

  1. 添加标头:add_header Referrer-Policy "strict-origin-when-cross-origin" always;

验证:curl -sfI https://example.com/ | grep -i '^referrer-policy'

5.10 工具定义安全性

当页面包含 WebMCP 工具定义时适用。当定义中不含机密信息(JWT、API 密钥、令牌、银行卡号、密码)、名称与描述匹配,且只读工具包含 readOnlyHint 时通过。

  1. 从 toolname、tooldescription 和 registerTool() 代码中移除每个令牌或密钥。在服务器上加载机密信息。
  2. 标记不会更改数据的工具:
    document.modelContext?.registerTool({
      name: "search_products",
      description: "Search the product catalog by keyword",
      annotations: { readOnlyHint: true },
      inputSchema: { type: "object", properties: { query: { type: "string" } }, required: ["query"] },
      execute: async ({ query }) => searchProducts(query),
    });
    

验证:curl -sf https://example.com/ | grep -ciE 'tool(name|description)="[^"]*(token|password|secret|api[_-]?key)'(预期为 0)

5.11 自动提交风险

当页面包含表单时适用。当没有表单使用 toolautosubmit,或仅搜索和筛选表单使用该属性时通过。高风险操作可获得部分分数。包含自动提交的密码或银行卡号输入框则不通过。

  1. 从登录、付款、删除和发送表单中移除 toolautosubmit。搜索表单可以保留:
    <form action="/search" toolname="search_products" tooldescription="Search the catalog" toolautosubmit>
      <input name="q" toolparamdescription="Search keywords">
    </form>
    

验证:curl -sf https://example.com/ | grep -oE '<form[^>]*toolautosubmit[^>]*>'(预期仅包含搜索或筛选表单)

5.12 OAuth 发现

适用于网站存在身份验证信号的情况。如果 /.well-known/oauth-authorization-server 或 /.well-known/openid-configuration 包含 issuer、authorization_endpoint 和 token_endpoint,则通过。

  1. 发布元数据(RFC 8414):
    {
      "issuer": "https://example.com",
      "authorization_endpoint": "https://example.com/oauth/authorize",
      "token_endpoint": "https://example.com/oauth/token",
      "code_challenge_methods_supported": ["S256"],
      "scopes_supported": ["read", "write"]
    }
    

验证:curl -sf https://example.com/.well-known/oauth-authorization-server | jq -e '.issuer and .authorization_endpoint and .token_endpoint'

5.13 OAuth 受保护资源

适用于网站存在身份验证信号的情况。如果 /.well-known/oauth-protected-resource 包含 resource 和 authorization_servers,或主页发送了 WWW-Authenticate,则通过。

  1. 发布元数据(RFC 9728):
    { "resource": "https://example.com/api", "authorization_servers": ["https://example.com"], "scopes_supported": ["read"] }
    
  2. API 返回 401 时,发送 WWW-Authenticate: Bearer resource_metadata="https://example.com/.well-known/oauth-protected-resource"。

验证:curl -sf https://example.com/.well-known/oauth-protected-resource | jq -e '.resource and (.authorization_servers | length > 0)'

5.14 Agent 身份验证就绪情况

适用于网站存在身份验证入口的情况。此检查会综合考量 PKCE S256、作用域元数据、受保护资源元数据或 WWW-Authenticate 标头、有效的 /auth.md,以及适用于 Agent 的授权授予方式。

  1. 在 5.12 中的元数据里添加 "code_challenge_methods_supported": ["S256"] 和 scopes_supported。
  2. 发布 5.13。
  3. 编写 /auth.md:
    # Authentication
    
    - Flow: OAuth 2.1 authorization code with PKCE (S256)
    - Agents: use the device code grant or a user-approved token. Do not ask for passwords.
    - Scopes: read (default), write (needs user approval)
    

验证:curl -sf https://example.com/.well-known/oauth-authorization-server | jq -e '.code_challenge_methods_supported | index("S256")'

关键注意事项

  1. HSTS max-age=86400(一天)只能获得部分分数。请设置为一年。
  2. 仅包含 upgrade-insecure-requests 的 CSP 只能获得部分分数。
  3. Nginx 的 add_header 未使用 always 时,不会应用于错误响应。
  4. Access-Control-Allow-Origin: * 与凭据同时使用无效且不安全。
  5. 不同域名上的 OAuth 元数据不计入此网站。

正确和错误示例请参阅 references/gotchas.md。

参考资料

评论

支持 Markdown