2026年9月3日更新。本文基于 Google 2026年9月2日公开信息,演示如何用 Gemini API 构建一个“只读、可审计、默认不执行命令”的代码安全审查 Agent。示例不包含真实密钥,也不会自动修改生产代码。
一、这次 AI 热点到底是什么
9月2日,Google 公布 Gemini 3.8 Flash 和 Gemini 3.8 Flash Cyber。前者定位为面向 software engineering、agentic workflow 和多步骤推理的 workhorse model;后者面向可信防御方,用于漏洞发现和自动修复场景。
官方公布的一个关键信号是:模型不再只是“回答代码问题”,而是通过长时间运行的 agentic loop,反复评估、执行和改进任务。换句话说,AI 编程正在从“补全一段函数”走向“理解仓库、修改文件、运行测试、提交变更”。
这会带来一个容易被忽略的问题:模型越能干,权限越不能随便给。
过去 Prompt 写得不好,最多得到一段不能运行的代码。现在如果 Agent 同时拥有 Shell、文件系统、Git、云 API 和生产凭据,一个恶意 README、issue 或依赖包中的隐藏指令,就可能把“帮我修 Bug”变成“帮我把密钥打包上传”。这已经不是 Prompt 技巧问题,而是应用安全问题。
二、为什么“全自动执行”不是默认选项
一个 Coding Agent 通常会接触以下四类边界:
| 边界 | Agent可能接触的内容 | 主要风险 |
|---|---|---|
| 输入边界 | issue、README、网页、日志 | 间接 Prompt Injection |
| 工具边界 | Shell、文件读写、Git、网络请求 | 越权执行与数据外传 |
| 身份边界 | SSH Key、云 Token、数据库账号 | 凭据泄露、权限扩大 |
| 发布边界 | CI/CD、镜像仓库、生产环境 | 未审查变更直接上线 |
因此,Agent 的安全默认值应该是:
- 默认只读;
- 命令执行放进隔离容器;
- 网络默认关闭,按域名放行;
- Secret 不进入 Prompt,不写入日志;
- 修改文件前生成 Patch;
- 合并、部署和删除操作必须人工确认。
这套设计看起来保守,但工程上更便宜。让 AI 多问一次确认,只损失几秒;让它删掉生产数据库,损失就不止几秒了。
三、先做一个只读代码审查 Agent
下面使用 Google 官方 google-genai Python SDK。安装依赖:
python -m venv .venv
source .venv/bin/activate
pip install -U google-genai
export GEMINI_API_KEY='你的API密钥'
示例将代码作为普通文本提交给模型,只要求输出结构化审查结果,不授予 Shell、网络或文件写入能力。
import json
import os
from google import genai
MODEL = "gemini-3.8-flash"
SYSTEM_PROMPT = """
你是只读代码安全审查器,不是自动执行器。
只能分析用户提供的代码文本,不得猜测不存在的文件或依赖。
不要输出、复述或变形任何疑似密钥、密码、Token、Cookie。
发现凭据时只写 [REDACTED]。
必须返回 JSON,字段为:
{
"summary": "一句话结论",
"risk_level": "low|medium|high|critical",
"findings": [
{
"severity": "low|medium|high|critical",
"line": 0,
"title": "问题标题",
"evidence": "最小必要证据,不包含秘密",
"fix": "修复建议"
}
],
"needs_human_review": true
}
"""
def review_code(source: str) -> dict:
if len(source) > 120_000:
raise ValueError("输入代码过长,请先按文件或模块拆分")
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
prompt = SYSTEM_PROMPT + "\n待审查代码:\n" + source
response = client.models.generate_content(
model=MODEL,
contents=prompt,
)
text = (response.text or "").strip()
fence = chr(96) * 3
if text.startswith(fence):
text = text.strip(chr(96))
if text.startswith("json"):
text = text[4:].lstrip()
result = json.loads(text)
required = {"summary", "risk_level", "findings", "needs_human_review"}
missing = required - result.keys()
if missing:
raise ValueError(f"模型返回字段缺失: {sorted(missing)}")
return result
if __name__ == "__main__":
sample = """
import subprocess
def run(user_input):
return subprocess.check_output(user_input, shell=True, text=True)
"""
print(json.dumps(review_code(sample), ensure_ascii=False, indent=2))
这里有三个关键点。
第一,GEMINI_API_KEY 从环境变量读取,不能硬编码到代码、README 或 Git 仓库。第二,模型输出必须经过 JSON 解析和字段校验,不能因为模型返回了一段“看起来很像 JSON”的 Markdown 就直接进入后续流程。第三,示例只调用 generate_content,没有注册任何 Function Calling 工具,因此它没有权限执行 Shell。
四、给 Agent 加工具时,先加“闸门”再加能力
如果业务确实需要 Agent 运行测试,可以采用“工具请求—策略校验—隔离执行—结果回传”的链路,而不是把 subprocess 直接暴露给模型。
ALLOWED_COMMANDS = {
"pytest": ["pytest", "-q"],
"ruff": ["ruff", "check", "."],
}
def build_command(tool_name: str) -> list[str]:
"""只允许固定命令,不接受模型拼接的 Shell 字符串。"""
if tool_name not in ALLOWED_COMMANDS:
raise PermissionError("工具不在允许列表中")
return ALLOWED_COMMANDS[tool_name].copy()
实际执行时还应该满足:
- 在临时容器或专用低权限用户中运行;
- 工作目录是临时副本,不是生产仓库;
- 使用
--network=none或显式 egress allowlist; - 设置 CPU、内存、进程数和执行时间上限;
- 挂载源码时使用只读挂载;
- 输出日志做 Secret 脱敏;
- 执行前后记录 Agent、模型、工具、参数、返回码和耗时。
尤其要避免这种写法:
# 不要这样做:模型输出直接进入 Shell
subprocess.run(model_output, shell=True)
模型输出是“不可信输入”,和网页表单、HTTP 参数、用户上传文件属于同一类安全对象。它再聪明,也不能自动变成可信命令。
五、自动修复应该只生成 Patch
“自动修复”最安全的第一步不是直接写文件,而是生成 Patch,并把 Patch 交给现有 Code Review 流程。
推荐流程如下:
代码快照
↓
只读分析
↓
发现问题
↓
生成 unified diff
↓
静态检查与单元测试
↓
人工审核
↓
合并到分支
↓
灰度部署
Patch 至少要经过以下检查:
git diff --check
ruff check .
pytest -q
trivy fs --scanners vuln,secret .
git diff --stat
如果是基础设施代码,还要额外执行对应的格式化、计划预览和策略检查。例如 Terraform 变更要先 terraform plan,Kubernetes 清单要先做 schema 校验和 OPA/Gatekeeper 策略检查。
删除文件、修改 CI 权限、变更 IAM、访问生产数据库、推送远端仓库等动作,不应该因为测试通过就自动放行。测试通过只能说明“这次检查没发现问题”,不代表“这个动作一定应该发生”。
六、如何设计 Agent 的最小权限
可以按任务把权限拆成三档:
| 模式 | 文件 | Shell | 网络 | Git写入 | 适用场景 |
|---|---|---|---|---|---|
| 观察模式 | 只读 | 禁止 | 禁止 | 禁止 | 代码解释、漏洞扫描 |
| 验证模式 | 临时副本 | 白名单 | 默认关闭 | 禁止 | 测试、Lint、构建 |
| 提交模式 | 工作分支 | 白名单 | 受限 | 需确认 | 生成 Patch、创建 PR |
生产部署不建议作为 Agent 的默认模式。即使未来使用更强的模型,也应该让部署系统独立于模型做最终授权:模型只能提交变更请求,CI/CD 根据分支、审批人、策略和环境状态决定是否执行。
七、上线前的验收清单
部署一个可以调用工具的 AI Agent 前,我会至少检查下面这些项目:
- [ ] API Key、SSH Key、Cookie 和数据库密码没有进入 Prompt;
- [ ] Agent 运行账户不是 root,且没有不必要的 sudo;
- [ ] Shell 工具不是任意字符串执行;
- [ ] 代码执行在隔离环境,资源和时间有限制;
- [ ] 网络访问默认关闭,并记录所有放行域名;
- [ ] 读取外部内容后不会自动信任其中的指令;
- [ ] 修改操作先生成 Patch,不直接覆盖生产文件;
- [ ] 高风险动作有人工确认和可回滚版本;
- [ ] 每次模型调用、工具调用和结果都有审计记录;
- [ ] 失败时默认停止,不因为重试而扩大权限。
八、结语:模型能力增长,权限要反向收缩
Gemini 3.8 Flash 这类模型的价值,不只是回答更快、代码写得更多,而是让长链路工程任务真正开始具备自动化可能。与此同时,Agent 的攻击面也从“模型会不会胡说”扩大到了“模型能不能碰到不该碰的东西”。
所以,构建 AI Agent 时不要先问“能不能全自动”,应该先问三件事:它看到了什么、它能调用什么、出了问题能不能撤回。
把模型当成能力很强的实习生,而不是拿着生产钥匙的超级管理员。这样 AI 才是在帮我们写代码,而不是顺手给安全事故写复盘。
参考资料
- Google Blog:Introducing Gemini 3.8 Flash and 3.8 Flash Cyber(2026-09-02)\n https://blog.google/innovation-and-ai/models-and-research/gemini-models/3-8-flash-and-3-8-flash-cyber/
- Google AI for Developers:Gemini API Models\n https://ai.google.dev/gemini-api/docs/models/gemini
- Google AI for Developers:Gemini API Pricing\n https://ai.google.dev/gemini-api/docs/pricing
- OWASP Cheat Sheet Series:Secure Coding with AI\n https://cheatsheetseries.owasp.org/cheatsheets/Secure_Coding_with_AI_Cheat_Sheet.html

435

被折叠的 条评论
为什么被折叠?



