关于 Valca
Valca 是面向 AI 编码环境的只读安全扫描工具,可检查代码、基础设施即代码和 Agent 配置,并在 Claude Code 写入文件前拦截严重发现。核心扫描离线运行,依赖项检查会向外部服务发送包名和版本。
主要功能
- 01扫描代码、IaC 和 Agent 配置
- 02写入前拦截高危和严重发现
- 03涵盖秘密、提示注入及 MCP 安全规则
- 04提供扫描历史、日志和统计
- 05支持 JSON 扫描结果
适用场景
- 01在 AI 生成文件写入前检查安全问题
- 02扫描 Docker、Terraform 和 CI 配置
- 03审查 Agent 提示词及工具处理逻辑
- 04查看本地发现记录和规则命中情况
MCP 相关
Valca 可扫描 MCP 服务配置、工具描述和处理器等相关代码;它不是 MCP 服务,也不向 MCP 客户端提供工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Valca
AI 编码安全副驾——在代码生成时阻止不安全代码。
此前以
vigilsec发布。 现在包名为valca。valca和vigil命令均可使用,因此现有钩子和脚本无需修改即可继续运行。
Valca 会拦截 AI 编码助手写入的每个文件,并在检测到严重或高危安全问题时阻止写入——文件尚未写入磁盘时就会拦截。它是唯一一款在生成时而非提交后发挥作用的工具。
AI writes file → valca scan → exit 2 → Claude Code blocks the write
问题
AI 编码助手会复现训练数据中最常见的模式,而最常见的模式往往是不安全的默认设置。
最明显的例子是:所有现有的 IaC 扫描器(Checkov、Trivy、Snyk、Semgrep)都会漏掉 docker-compose 中将数据库暴露到互联网的端口绑定:
ports:
- "5432:5432" # ← binds to 0.0.0.0, bypasses UFW, reachable from anywhere
正确写法是 "127.0.0.1:5432:5432"。Valca 能发现这个问题,其他工具都不能。
安装
pip install valca
配置 Claude Code 钩子(只需一次):
valca init --global # `valca init --global` also works
就这样。现在,Claude Code 写入的每个文件都会在保存前接受扫描。重新加载 Claude Code 即可启用。
网络访问
Valca 的核心扫描完全离线运行——该包没有任何运行时依赖,引擎也绝不会将你的代码、文件路径或扫描结果发送到任何地方。
有三条规则需要访问网络,因为离线时无法检查依赖是否存在漏洞或系伪造。扫描清单文件(requirements.txt、package.json、锁文件)时,这些规则只会将包名和版本字符串发送到:
| 主机 | 用途 | 发送内容 |
|---|---|---|
api.osv.dev | VGL-PKG001(固定版本中存在已知 CVE) | 包名 + 版本 |
pypi.org | VGL-PKG002/003/004(虚构、过时或可疑的包) | 包名 |
registry.npmjs.org | VGL-PKG002/003/004 | 包名 |
你的源代码、文件内容、文件路径和扫描结果绝不会被传输。如果你的依赖清单本身也属于敏感信息,请在 .valcarc 中关闭这些规则,这样 Valca 就会完全离线运行:
disabled_rules = ["VGL-PKG001", "VGL-PKG002", "VGL-PKG003", "VGL-PKG004"]
用法
# Scan a single file
valca scan docker-compose.yml
# Scan a directory
valca scan ./my-project/
# JSON output (for CI / dashboards)
valca scan ./my-project/ --format json
# SARIF output (for GitHub Advanced Security)
valca scan ./my-project/ --format sarif > results.sarif
# Only report HIGH and above
valca scan ./my-project/ --severity HIGH
# Open feedback & waitlist form
valca feedback
查看一段时间内发现的问题。 两条命令都会读取本地扫描历史记录——不会有任何数据离开你的设备。
# Findings log — what was caught, where, and when
valca log # 20 most recent findings
valca log --severity CRITICAL # only criticals
valca log --project api --since 2026-09-01
valca log --limit 100 --format json # for dashboards
# Aggregate stats — rule frequency, severity mix, precision per rule
valca stats
valca stats --format json
valca stats 会报告每条规则的触发次数和抑制次数,让你了解哪些规则在你的代码库中精确度较低,而不是靠猜测。
退出代码:
| 代码 | 含义 |
|---|---|
0 | 未发现问题——继续写入 |
1 | 仅有提示级问题(中 / 低 / 信息) |
2 | 发现严重或高危问题——Claude Code 会阻止写入 |
实际效果
在写入时阻止存在漏洞的 GitHub Actions 工作流:

2026 年 4 月,研究人员发现,所有三种主流 AI 编码 Agent(Claude Code、Gemini CLI、Copilot)都可能被劫持,通过 GitHub issue 中隐藏的 HTML 注释窃取 ANTHROPIC_API_KEY 和 GITHUB_TOKEN。CVSS 评分为 9.4。无需特殊访问权限。
Valca 会在存在漏洞的工作流进入 git 之前将其拦截(issues: 触发器 + AI Agent + 环境变量中的 API 密钥)——这是唯一能做到这一点的工具。
→ 完整分析:通过 GitHub Issue 评论窃取 API 密钥的攻击
规则
27 个类别中共有 116 条规则。 全部内置,仅使用标准库,零运行时依赖。
此目录由规则注册表生成,因此不会与已发布的引擎不一致。
密钥与凭据泄露(14 条规则)
| 规则 | 严重性 | 检查内容 |
|---|---|---|
| VGL-I001 | CRITICAL | eval() 或 exec() —— 代码注入风险 |
| VGL-I002 | HIGH | subprocess 使用 shell=True |
| VGL-I003 | HIGH | 调用 os.system() |
| VGL-S001 | CRITICAL | 硬编码 AWS 访问密钥 |
| VGL-S002 | CRITICAL | 硬编码密码 |
| VGL-S003 | CRITICAL | 硬编码 API 密钥 |
| VGL-S004 | CRITICAL | 硬编码 bearer 令牌 |
| VGL-S005 | CRITICAL | 硬编码 JWT 密钥 |
| VGL-S006 | CRITICAL | 源代码中包含 PEM 私钥 |
| VGL-S007 | CRITICAL | 数据库 URL 中嵌入凭据 |
| VGL-S008 | CRITICAL | Stripe 实时密钥 |
| VGL-S009 | CRITICAL | 硬编码 Slack 令牌 |
| VGL-S010 | CRITICAL | 硬编码提供商 API 密钥(OpenAI / GitHub / GitLab / Google) |
| VGL-S012 | HIGH | 安全关键配置使用不安全的占位符默认值 |
GitHub Actions — AI Agent 攻击面(13 条规则)
| 规则 | 严重性 | 检查内容 |
|---|---|---|
| VGL-GHA001 | CRITICAL | Pwn Request——pull_request_target 使用攻击者可控的检出 ref |
| VGL-GHA002 | CRITICAL | 脚本注入——run: 步骤中使用用户可控的上下文表达式 |
| VGL-GHA004 | HIGH | 在 run: 步骤中直接插入密钥(会显示在进程表中) |
| VGL-GHA005 | MEDIUM | 工作流缺少显式 permissions 块(GITHUB_TOKEN 权限范围为隐式设置) |
| VGL-GHA006 | HIGH | 在 pull_request 工作流中使用缓存(缓存投毒攻击途径) |
| VGL-GHA007 | HIGH | pull_request 触发器使用自托管运行器(运行器持久化风险) |
| VGL-GHA008 | HIGH | workflow_run 触发器未验证 ref/repo |
| VGL-GHA009 | CRITICAL | AI Agent 连接到不可信输入触发器(issues/pull_request_target),且在 env 中设置了 API 密钥 |
| VGL-GHA010 | HIGH | pull_request_target 上的 AI Agent 未检查 fork 来源 |
| VGL-GHA011 | CRITICAL | 将不可信的 GitHub 事件数据插入 AI Agent 提示词 |
| VGL-GHA012 | HIGH | 不可信触发器上的 AI Agent 未限制 --allowedTools |
| VGL-GHA013 | MEDIUM | 不可信触发器上的 AI Agent 未限制 --max-turns |
| VGL-GHA014 | HIGH | 不可信触发器上的 AI Agent 拥有 contents: write 权限 |
AI Agent — 提示词注入(9 条规则)
| 规则 | 严重性 | 检查内容 |
|---|---|---|
| VGL-PI001 | CRITICAL | 将用户输入插入大模型系统提示词 |
| VGL-PI002 | HIGH | 将原始 HTTP 请求正文用作大模型消息内容 |
| VGL-PI003 | HIGH | 使用字符串格式化将用户数据构造为提示词 |
| VGL-PI004 | MEDIUM | 未经清理便将工具输出附加到对话中 |
| VGL-PI005 | CRITICAL | HTTP 请求数据未经清理便流入大模型提示词 |
| VGL-PI006 | CRITICAL | 大模型响应流入 subprocess、exec 或 eval |
| VGL-PI007 | HIGH | Webhook 负载直接流入 AI Agent |
| VGL-PI008 | HIGH | 将数据库内容插入提示词——二阶注入 |
| VGL-PI009 | HIGH | 将用户输入写入向量存储——记忆投毒 |
Dockerfile 加固(8 条规则)
| 规则 | 严重性 | 检查内容 |
|---|---|---|
| VGL-DF001 | HIGH | Dockerfile 以 root 身份运行——未设置 USER 指令 |
| VGL-DF002 | MEDIUM | Dockerfile 使用未固定版本的 :latest 基础镜像 |
| VGL-DF003 | HIGH | Dockerfile 在 ENV 或 ARG 层中嵌入密钥 |
| VGL-DF004 | HIGH | Dockerfile 的 RUN 指令中通过管道执行 curl |
| VGL-DF005 | HIGH | Dockerfile 的 RUN 下载操作中禁用 TLS 验证 |
| VGL-DF006 | MEDIUM | 使用 ADD 处理本地文件——应改用 COPY |
| VGL-DF007 | HIGH | 使用 COPY . 但没有 .dockerignore——可能泄露 .git、.env 和凭据 |
| VGL-DF008 | MEDIUM | 在 Dockerfile 中设置对所有用户可写的权限(chmod 777) |
Docker Compose(7 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-D001 | 严重 | Docker 公共端口绑定——绕过 UFW,使服务暴露于互联网 |
| VGL-D002 | 高 | docker-compose 环境块中包含硬编码密钥 |
| VGL-D003 | 严重 | Docker 容器以特权模式运行 |
| VGL-D004 | 高 | Docker 容器使用主机网络模式 |
| VGL-D005 | 严重 | 将 Docker 套接字挂载到容器中——可导致完全逃逸容器 |
| VGL-D006 | 高 | 将敏感主机路径挂载到容器中 |
| VGL-D007 | 高 | 将 AWS 凭证目录(~/.aws)挂载到容器中——暴露所有配置文件 |
Terraform(7 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-TF001 | 严重 | Terraform 中的硬编码密钥值 |
| VGL-TF002 | 高 | Terraform 资源启用了公共访问 |
| VGL-TF003 | 高 | Terraform 中明确禁用了加密 |
| VGL-TF004 | 严重 | EC2 实例启用了 IMDSv1——易受 SSRF 元数据窃取攻击 |
| VGL-TF005 | 高 | Terraform S3 状态后端未加密存储 |
| VGL-TF006 | 中 | 托管资源禁用了删除保护 |
| VGL-TF007 | 中 | Terraform 管理的资源禁用了审计日志记录 |
反序列化与路径遍历(5 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-DESER001 | 严重 | 不安全的反序列化——pickle.loads / pickle.load |
| VGL-DESER002 | 高 | 不安全的 YAML 反序列化——yaml.load() 未使用 SafeLoader |
| VGL-DESER003 | 高 | 不安全的反序列化——marshal.loads 使用了不可信数据 |
| VGL-PATH001 | 高 | 路径遍历——未经验证便将用户输入传递给文件打开操作或路径拼接 |
| VGL-SSTI001 | 严重 | 服务器端模板注入——将用户输入渲染为 Jinja2 模板 |
MCP 服务安全(5 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-MCP001 | 严重 | MCP 工具描述中嵌入了提示词注入 |
| VGL-MCP002 | 高 | MCP 工具描述由用户可控数据构建 |
| VGL-MCP003 | 高 | MCP 工具处理程序中未经沙箱保护地执行 Shell 命令 |
| VGL-MCP004 | 高 | MCP 服务配置使用了未固定版本的包或明文 HTTP 端点 |
| VGL-MCP005 | 高 | MCP 抓取工具接受由 Agent 控制且未设允许列表的 URL |
Web 应用安全(5 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-CORS001 | 高 | CORS 通配符——allow_origins=['*'] |
| VGL-SQL001 | 严重 | SQL 注入——使用 f-string 或字符串拼接构建查询 |
| VGL-SQL002 | 严重 | SQL 注入——ORM 原始查询使用了 f-string |
| VGL-SSL001 | 高 | 禁用了 SSL 验证 |
| VGL-SSRF001 | 严重 | SSRF——使用用户可控的 URL 发起 HTTP 调用 |
AI Agent——过度自主权(4 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-A001 | 严重 | 将大模型输出传入 Shell 命令执行 |
| VGL-A002 | 高 | 硬编码的自动批准禁用了人工参与环节 |
| VGL-A003 | 高 | Agent 循环无迭代次数限制 |
| VGL-A004 | 高 | 未经验证便将大模型响应写入磁盘 |
身份验证与会话(4 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-AUTH001 | 严重 | JWT algorithm=none——绕过签名验证 |
| VGL-AUTH002 | 严重 | JWT verify_signature 已禁用——接受任何令牌 |
| VGL-AUTH003 | 高 | Web 框架密钥强度弱或为硬编码值 |
| VGL-AUTH004 | 高 | 框架代码中启用了调试模式 |
依赖完整性(4 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-PKG001 | CRITICAL | 软件包审计(CVE · 幻觉 · 过时 · 供应链) |
| VGL-PKG002 | CRITICAL | 在注册表中找不到软件包 — 幻觉或抢注相似名称的目标 |
| VGL-PKG003 | HIGH | 软件包版本明显落后于最新版本 — AI 训练数据过时 |
| VGL-PKG004 | HIGH | 软件包刚刚注册且发布版本很少 — 供应链风险 |
Kubernetes(4 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-K001 | CRITICAL | 特权容器或主机命名空间访问 |
| VGL-K002 | CRITICAL | 在 Kubernetes securityContext 中启用了 allowPrivilegeEscalation |
| VGL-K003 | HIGH | 在 Kubernetes securityContext 中添加了危险的 Linux capabilities |
| VGL-K004 | HIGH | Kubernetes 清单中包含敏感的 hostPath 卷 |
日志记录与数据泄露(4 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-LOG001 | HIGH | 将敏感数据写入日志(CWE-532) |
| VGL-LOG002 | HIGH | 在 HTTP 响应正文中泄露错误详情(CWE-209) |
| VGL-LOG003 | MEDIUM | 在身份验证/安全上下文中静默吞掉异常 |
| VGL-LOG004 | MEDIUM | CRLF 注入风险 — 记录用户控制的输入时未清理换行符 |
Swift / iOS(4 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-SW001 | CRITICAL | Swift 字符串字面量中硬编码了机密 |
| VGL-SW002 | HIGH | Swift 网络代码中使用了普通 HTTP URL |
| VGL-SW003 | HIGH | 将敏感值写入 UserDefaults(未加密) |
| VGL-SW004 | CRITICAL | 在 URLSession 代理中绕过了 SSL 证书验证 |
依赖项 CVE 扫描器(3 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-DEP001 | HIGH | 存在漏洞的 Python 软件包(pip-audit) |
| VGL-DEP002 | HIGH | 存在严重漏洞的 npm 软件包(npm audit) |
| VGL-DEP003 | HIGH | 锁定文件中的软件包存在漏洞(osv-scanner) |
GitHub Actions — 工作流规范(3 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-GH001 | HIGH | 在 run 步骤中打印 GitHub Actions 机密(日志泄露) |
| VGL-GH002 | HIGH | GitHub Actions 工作流权限过多 |
| VGL-GH003 | HIGH | GitHub Actions 使用可变的 action 引用(标签或分支) |
AI Agent — 配置文件(2 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-AGENT001 | CRITICAL | AI Agent 配置文件中包含 Shell 执行或数据外传指令 |
| VGL-AGENT002 | HIGH | Agent 代码中的异常处理程序泄露了凭据 |
JavaScript / TypeScript(2 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-JS001 | HIGH | process.env 机密使用了硬编码字符串回退值 |
| VGL-JS004 | HIGH | eval() 或 new Function() 使用了动态参数(CWE-95) |
行级安全(2 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-RLS001 | CRITICAL | 明确禁用了 PostgreSQL 行级安全 |
| VGL-RLS002 | HIGH | 多租户 ORM 查询缺少用户/租户筛选条件 |
跨站脚本攻击(1 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-XSS001 | HIGH | 跨站脚本攻击 — 不安全的 HTML 注入(CWE-79) |
密码学(1 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-RAND001 | HIGH | 安全敏感值使用了弱随机数(CWE-330) |
IAM 策略(1 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-IAM001 | CRITICAL | IAM 策略的 Action 或 Resource 中使用了通配符 |
Python(1 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-PY001 | HIGH | 未受环境变量保护的调试绕过 — 有条件地禁用身份验证/安全检查 |
Shell 脚本(1 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-S011 | HIGH | 将机密变量内联传递给子进程/SSH(泄露至 ps aux) |
Trivy IaC 深度扫描(1 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-T001 | HIGH | Trivy IaC 深度扫描 — Dockerfile / Terraform 配置错误 |
nginx(1 条规则)
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| VGL-N001 | HIGH | nginx 配置缺少安全标头或 TLS 配置较弱 |
配置
在项目根目录(或任意上级目录)中放置 .valcarc 文件:
# .valcarc
disabled_rules = ["VGL-T001"] # skip trivy scan for this project
min_severity = "HIGH" # only report HIGH and above
exclude_paths = ["vendor", "legacy"]
telemetry = false # opt out of anonymous local telemetry
Valca 会沿目录树向上查找最近的 .valcarc(仍会读取旧名称 .vigilrc)。子级配置始终优先于父级配置。单体仓库可以在工作区默认配置旁为各个项目设置覆盖项。
行内抑制 — 用于已审查并接受的特定行:
auto_approve = True # vigil: ignore
与 # noqa(flake8)和 # nosec(bandit)的模式相同。
退出遥测
Valca 会收集匿名、仅限本地的遥测数据:规则 ID、严重性和文件扩展名。不包含文件路径、代码或可识别个人身份的数据。数据存储在 ~/.valca/events.jsonl 中,不会发送到任何地方。旧位置 ~/.vigil/ 中的历史记录会自动迁移。
永久退出:
export VALCA_NO_TELEMETRY=1 # VIGIL_NO_TELEMETRY still works
或在 .valcarc 中设置:
telemetry = false
添加规则
# src/valca/rules/my_category.py
from pathlib import Path
from .base import Finding, Rule, Severity
class MyRule(Rule):
id = "VGL-X001"
name = "Descriptive rule name"
severity = Severity.HIGH
def applies_to(self, path: Path) -> bool:
return path.suffix == ".yml"
def check(self, path: Path) -> list[Finding]:
findings = []
for i, line in enumerate(path.read_text().splitlines(), 1):
if "bad_pattern" in line:
findings.append(Finding(
rule_id=self.id,
severity=self.severity,
message="Found bad pattern",
file_path=path,
line=i,
snippet=line.strip(),
fix="Do this instead.",
))
return findings
然后将其添加到 src/valca/rules/__init__.py 中的 DEFAULT_RULES。编写测试。完成。
GitHub Actions
使用此 action — PranLabs/valca-action:
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v7
- uses: PranLabs/valca-action@v1
with:
severity: HIGH
version: "0.6.0" # pin for reproducible CI
- uses: github/codeql-action/upload-sarif@v4
if: always()
with:
sarif_file: valca-results.sarif
category: valca
或者不使用 action,直接调用:
- run: pip install valca --quiet
- run: valca scan . --no-color
- run: valca scan . --format sarif > valca-results.sarif
检测结果会以内联注释的形式显示在 PR 差异中,也会显示在仓库的 Security 选项卡中。
MCP 服务
钩子会阻止 Agent。MCP 服务则允许 Agent 发起扫描。
pip install "valca[mcp]"
valca-mcp
使用任意 MCP 客户端注册该服务 — 对于 Claude Code,命令为 claude mcp add valca -- valca-mcp。
它提供两个工具,均为只读:
| 工具 | 返回内容 |
|---|---|
scan(path) | 文件或目录的检测结果:规则、严重性、消息、文件、行号、建议的修复方法 |
list_rules() | 完整目录 — 每条规则的 ID、严重性和检测内容 |
没有任何工具会编辑、修复或写入内容。能够修改代码的扫描器会构成新的攻击面,而 VGL-MCP003 和 VGL-MCP005 正是为检测这种情况而存在的。
以下三个限制是内置的,不可配置:
- 扫描不能超出根目录。 根目录是启动
valca-mcp时所在的目录;若设置了VALCA_MCP_ROOT,则使用该变量指定的目录。Agent 可以指定scan的参数,因此如果没有边界,它就能遍历到~/.ssh,并探查原本并未授权访问的 文件系统。 - 返回的路径均相对于该根目录。 绝对路径会暴露你的用户名和目录结构。
- 绝不返回匹配到的源代码行。 对于机密信息规则,该行本身就是机密信息。
无论你的配置如何设置,通过此路径运行时都会关闭遥测。仍会遵循你的 .valcarc —
disabled_rules、exclude_paths 和 min_severity 均会生效。
mcp 是可选附加组件,因此正常安装 Valca 仍不会拉取任何运行时依赖。
钩子仍是执行强制检查的途径。无论模型是否愿意,它都会在每次写入时运行;MCP 则由 Agent 选择是否启用,而 Agent 可以拒绝执行的检查不构成强制执行。
开发
git clone https://github.com/PranLabs/valca.git
cd vigil
python3 -m venv venv && source venv/bin/activate
pip install -e ".[dev]"
pytest tests/ -v
许可证
Business Source License 1.1 — 可免费用于非商业用途。商业用途需要签订许可协议。将于 2030-06-26 转为 MIT 许可证。
反馈
发现误报?想添加尚不存在的规则?使用 AI Agent 构建时遇到 Valca 应当检测的模式?
提交问题 → github.com/PranLabs/valca/issues
或者运行:valca feedback
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。