Vibe Coding To Sdd
从 Vibe Coding 到 SDD:安全工程师的技能升维实战
以 OpenSpec + OpenCode 为例,融合 Harness Engineering & Ralph Loop
今天我们聊什么
| 环节 | 内容 |
|---|---|
| 🔍 问题 | Vibe Coding 的天花板在哪 |
| 🧠 理念 | SDD + Harness Engineering + Ralph Loop |
| 🛠️ 工具 | OpenSpec(写规格)+ OpenCode(让规格跑起来) |
| 🏋️ 模块一 | 零基础编码速成 |
| 🛡️ 模块二 | 安全场景实战四步法 |
| 🔥 模块三 | 综合实战 |
今天的目标:带走一份能跑在 CI/CD 里的安全策略规格文件
热身:你的”感觉”准不准
{
"code": 200,
"data": {
"name": "张三",
"phone": "13812345678",
"id_card": "310101199001011234",
"email": "zhangsan@example.com"
}
}
✍️ 写出你觉得“不太对劲”的地方(30秒)
什么是 Vibe Coding
Vibe Coding = 凭借感觉、经验、记忆来做事
- 🔧 运维:凭记忆敲命令,行就行,不行再换
- 🛡️ 安全:”我记得上次查过这个,应该没问题”
- 🧪 QA:”凭经验这几个边界值容易出问题”
- 🏗️ 架构师:”图画完了,具体落地你们看着办”
不是贬义词,是技术人的肌肉记忆。 但——肌肉记忆无法大规模、持续生效。
Vibe 的痛点——我们都有体会
| 问题 | 后果 |
|---|---|
| 📋 不成体系 | 查出漏洞,但很难”证明”标准是什么 |
| 👤 不可传承 | 你休假了,你的感觉别人没有 |
| ✅ 不可验证 | 三个月后这条规则还在吗?无法自证 |
| 📈 无法规模化 | 100 个仓库要重复检查多少遍? |
你的经验 → 查出问题 → 发邮件 → 等研发改 → 再查 → 再发邮件 → 循环……
你的经验是你最大的资产,也是你最大的单点故障。
从 Vibe 到 SDD:核心思维跃迁
| Vibe:”我做了什么步骤” | SDD:”最终状态必须是什么” |
|---|---|
| 凭直觉判断”这里可能有问题” | 写规则定义”什么是对,什么是错” |
| 追着研发发整改邮件 | 策略卡在 CI 入口,不合规不能上线 |
| 人工抽查几个接口 | 所有符合 scope 的接口自动检查 |
| 安全基线在 Word 文档里 | 安全策略在 Git 仓库里,可执行、可审计 |
SDD = Specification-Driven Development 先定义”系统必须满足什么”,再由工具去满足这个定义。
SDD 的四个核心概念
| 概念 | 作用 | 一句话 |
|---|---|---|
| 📐 OpenSpec | 写规格 | 定义”对的是什么样” |
| 🛠️ Harness Engineering | 定边界 | 给 AI 上好缰绳 |
| 🔄 OpenCode | 驱动工具 | 把规格翻译成可执行脚本 |
| 🔁 Ralph Loop | 自动执行 | 持续迭代直到合规,不完成不许停 |
OpenSpec(规格 = Harness 定义)
↓
OpenCode(翻译层)
↓
Ralph Loop(执行引擎:扫描→修复→验证→通过/重来)
↓
安全合规 ✅
什么是 Harness Engineering?
Harness = AI 的”缰绳”
| 概念 | 类比赛马 |
|---|---|
| 🐎 AI 模型 | 一匹强壮的马,跑得快但不知道往哪跑 |
| 🏇 人类工程师 | 骑手,指引方向 |
| 🛠️ Harness(马具) | 约束、护栏、反馈回路 |
Dario Amodei(Anthropic CEO):
“Agent = Model + Harness + Context” 真正的工程能力在 Harness——你如何约束它、引导它、验证它。
💡 对安全工程师来说,OpenSpec 规格文件就是你的 Harness。
Harness 在安全场景的落地
| Harness 组件 | 对应 OpenSpec 结构 | 作用 |
|---|---|---|
| 🎯 目标定义 | ## Purpose |
AI 要知道”我要达成什么” |
| 📏 行为边界 | ### Requirement: ... SHALL/MUST |
“只能在这个范围内动手” |
| 🔍 验证条件 | #### Scenario: GIVEN/WHEN/THEN |
“满足这些条件才算合规” |
| 🚦 约束等级 | SHALL(强制)vs SHOULD(建议) | “违规了是拦还是告警” |
你不需要控制 AI 的每一步。你只需要定义好边界。
什么是 Ralph Loop?
Ralph Loop = 让 AI “不完成不许下班”
起源:澳洲开发者 Geoffery Huntley 在农场写出的 5 行 Bash:
while :; do
cat PROMPT.md | claude-code
done
核心逻辑: 读取任务 → AI 执行 → 检查结果 → 不通过就重来 → 直到完成
名字来自《辛普森一家》的 Ralph Wiggum:
“Me fail English? That’s unpossible!” “I’m in danger!”
三个关键设计:
- 🔄 每轮全新上下文
- 🎯 人类定义”完成”
- 👤 人类最终审批
模块一:零基础编码速成
目标:能阅读简单代码,找到安全问题位置
| 你不需要 | 你只需要 |
|---|---|
| 从零搭建 Web 服务 | 能认出”这段代码在处理用户输入” |
| 手写完美算法 | 能认出”这里返回了敏感字段” |
| 理解框架底层 | 能认出”这个函数没有权限检查” |
| 记住所有语法 | 知道去哪查,能看懂大致逻辑 |
安全工程师学编码的核心是”识别坏味道”。
代码的本质:给计算机的”精确菜谱”
给人写的菜谱:
“西红柿炒鸡蛋,先炒蛋盛出,再炒西红柿,混合调味。”
给计算机写的代码:
“鸡蛋 2 个,打入碗中,筷子搅拌 30 秒。油温 180°C,倒入蛋液,翻炒 60 秒,盛出备用……”
代码就是精确到每一步、每一条指令的菜谱。
五大核心概念速览(1)
# 1. 变量:给数据起名字
user_name = "张三"
login_attempts = 0
is_admin = False
# 2. 函数:一段有名字的操作
def mask_phone(phone):
return phone[:3] + "****" + phone[7:]
# 3. 条件判断:做决策
if login_attempts > 5:
print("账号已锁定")
else:
print("请重试")
五大核心概念速览(2)
# 4. 数据结构:装东西的容器
user_info = {
"name": "张三",
"phone": "13812345678",
"email": "zhangsan@example.com"
}
sensitive_fields = ["phone", "email", "id_card"]
# 5. HTTP 请求处理
@app.route("/api/user/profile")
def get_profile(user_id):
user = database.find(user_id)
return user # ⚠️ 返回了什么?脱敏了吗?
互动练习:找出有问题的代码
@app.route("/api/user/profile")
def get_profile(user_id):
user = {
"name": "张三",
"phone": "13812345678",
"id_card": "310101199001011234"
}
return user
安全问题:
- ❌
phone明文返回 - ❌
id_card明文返回 - ❌ 没有鉴权检查
- ❌ 没有输入校验
认识项目结构
user-api/
├── main.py # 入口文件
├── handlers/ # 处理 HTTP 请求
│ ├── login.py # 登录逻辑
│ ├── profile.py # 用户信息查询 ← 重点盯这里
│ └── admin.py # 管理员功能
├── config.yaml # 配置文件
└── README.md
handlers/ 的每个文件 = 一个或一组 API 端点 OpenSpec 文件格式和 README.md 一样是 Markdown
你不需要成为程序员
安全工程师的代码能力 = “阅读 + 模式识别”
| 你的能力 | 代码场景的应用 |
|---|---|
| 👁️ 识别异常 | 认出不正常的返回值、缺失的检查 |
| 🔍 模式匹配 | 认出”这和上次出事的代码长得一样” |
| 📋 规则思维 | 把安全基线转化为可检查的条件 |
| 🤔 批判性阅读 | “这个函数真的做了鉴权吗?” |
模式识别:安全问题的代码特征
| 安全问题 | 代码特征(坏味道) |
|---|---|
| 🔴 明文敏感信息 | return user 没经过 mask() |
| 🔴 权限缺失 | 函数开头没有 if not is_admin: |
| 🔴 SQL 注入 | "SELECT * FROM users WHERE id = " + user_id |
| 🔴 硬编码密钥 | password = "admin123" |
| 🔴 日志泄露 | print(token) |
| 🔴 缺少限流 | 没有 rate_limit() 调用 |
模块二:安全场景实战
四步法:从直觉到自动运行的安全策略
Step 1: 唤醒 Vibe → Step 2: 写成规格 → Step 3: 理解闭环 → Step 4: 构建策略集
(直觉判断) (OpenSpec MD) (OpenCode+Ralph) (完整资产)
每一步都让你离”人盯”更远,离”系统自动盯”更近。
真实业务场景
背景:
- 公司 100+ 个内部微服务 API
- 安全团队仅 3 人
- 安全基线在 Word 文档里
出的事故:
- 5 个 API 没做鉴权
- 3 个返回明文手机号和身份证
- 2 个登录接口没限流,被暴力破解
今天的目标: 把”人追人” → 改成”规格驱动 + AI 循环执行 → 不合规自动拦截”
第一步:唤醒 Vibe 直觉
任务:快速审视 user-api 项目,列出 5 个安全检查点
思考脚手架:
- 🔐 鉴权:admin 接口谁都能调吗?
- 📊 数据:profile 返回了什么字段?脱敏了吗?
- ⚙️ 配置:config.yaml 里有没有密码?
- 🌐 传输:HTTP 还是 HTTPS?
- 🔍 输入:有没有做参数校验?
这些是你脑子里的安全经验——宝贵的起点。下面把它外化出来。
第二步:把”感觉”写成”规格”
核心转变:安全判断从一句话 → 结构化 Markdown 规格
示例:
“API 不能返回明文手机号。”
OpenSpec 的做法: 写一份 Markdown 文件,用 Purpose 描述目标,用 Requirement 声明强制约束,用 Scenario 定义可验证的测试场景。
规格文件既给人读,也给机器解析——是人和 AI 之间的公共语言。
OpenSpec 正确格式速览
---
title: 规范名称
version: 1.0.0
status: approved
domain: security
---
# <能力名称>规范
## Purpose
对这个能力/模块的高层描述。
## Requirements
### Requirement: <需求名称>
系统 SHALL/MUST <行为描述>
#### Scenario: <场景名称>
- **GIVEN** <前置条件>
- **WHEN** <触发动作>
- **THEN** <预期结果>
关键规则:
- Requirements 必须包含 SHALL 或 MUST
- 每个 Requirement 至少一个 Scenario
- Scenario 用 GIVEN/WHEN/THEN 描述
规格推导四维度
| 维度 | 要回答的问题 | OpenSpec 对应 |
|---|---|---|
| 🎯 目标 | 这条规则要达到什么目的? | ## Purpose |
| 📏 约束 | 系统必须做什么? | ### Requirement: ... SHALL/MUST |
| 🔍 验证 | 什么算合规、什么算违规? | #### Scenario: GIVEN/WHEN/THEN |
| ⚠️ 边界 | 有没有例外情况? | 在 Scenario 中定义边界条件 |
OpenSpec 规格示例:数据脱敏规范
# 数据脱敏规范
## Purpose
确保所有 API 响应中的用户敏感数据经过脱敏处理。
## Requirements
### Requirement: 手机号脱敏
系统 SHALL 对所有包含用户信息的 API 响应进行手机号脱敏处理。
#### Scenario: 查询用户信息时返回脱敏手机号
- **GIVEN** 用户信息中存在 "phone": "13812345678"
- **WHEN** 通过用户查询接口返回该用户信息
- **THEN** 手机号字段显示为 "phone": "138****5678"
- **AND** 原始完整手机号不在响应中出现
这就是你的 Harness。每个 Scenario 都是机器可解析的验证条件。
动手:写第一份 OpenSpec(10分钟)
任务:从以下安全要求中选一条,写出 OpenSpec 规格文件
- 🔐 所有管理接口必须有 JWT 鉴权
- 🔒 API 响应中不得包含明文身份证号
- ⏱️ 登录接口限制请求频率
- 🚫 禁止硬编码密码
产出物:一份 spec.md 文件,包含:
- YAML front matter
## Purpose- 至少一个
### Requirement(含 SHALL/MUST) - 每个 Requirement 至少一个
#### Scenario(GIVEN/WHEN/THEN)
第三步:理解执行闭环
你的 OpenSpec 规格文件(= 安全 Harness)
↓
OpenCode 解析
↓
┌────────┼────────┬──────────┐
↓ ↓ ↓ ↓
CI 脚本 测试用例 合规报告 WAF 规则
↓ ↓ ↓ ↓
└────────┴────────┴──────────┘
↓
Ralph Loop 引擎
↓
┌─────────────────────────┐
│ 扫描 → 对照 Scenario 验证 │
│ ↓ │
│ 违规 → 生成修复建议 │
│ ↓ │
│ 验证修复 → 不通过就重来 │
│ ↓ │
│ 全部通过 → 放行 ✅ │
└─────────────────────────┘
演示 A:规格 → CI 检查脚本
opencode generate \
--from security/data-masking.spec.md \
--target ci-script \
--output ci/check-phone-masking.sh
自动生成:
#!/bin/bash
# 对应 Scenario: 查询用户信息时返回脱敏手机号
PATTERN='"phone":\s*"1[3-9]\d{9}"'
if grep -P "$PATTERN" "$API_RESPONSE_FILE"; then
echo "FAIL: 检测到明文手机号"
exit 1
fi
echo "PASS: 手机号脱敏合规"
你只写了 Markdown,脚本自动生成。每个 Scenario 对应一段检查逻辑。
演示 B:规格 → 测试用例
opencode generate \
--from security/data-masking.spec.md \
--target test-case \
--framework pytest \
--output tests/test_data_masking.py
自动生成:
- 明文手机号 → 预期 Scenario 失败
- 已脱敏手机号 → 预期 Scenario 通过
- 非手机号数字不误报 → 边界 Scenario
- 空响应、嵌套数据等边界情况
一份规格,多方消费。QA 也能用。
演示 C:规格合规报告
opencode audit \
--specs security/*.spec.md \
--repo ../user-api \
--format report
输出:
规范: 数据脱敏策略 (v1.0.0)
Status: FAILED
Requirement: 手机号脱敏 [SHALL]
Scenario: 查询用户信息时返回脱敏手机号
- handlers/profile.py:47: FAILED
- handlers/admin.py:112: FAILED
Remediation: 使用 phone_mask() 函数脱敏
以前的流程:发现漏洞 → 写邮件 → 追着改 现在的流程:Scenario 自动验证 → 失败即报告具体行号
Ralph Loop 在安全场景的落地
OpenSpec 规格(定义每个 Scenario)
↓
OpenCode 生成检查脚本
↓
Ralph Loop 执行引擎 ——
├─ 🔍 逐条验证 Scenario
├─ 🚨 THEN 不满足 → 违规
├─ 🔧 生成修复建议 → 修复后重验
└─ ✅ 全部 Scenario 通过 → 放行
Harness 的缰绳作用:
- 🔄 每轮全新上下文
- 🎯 Scenario 的 THEN 就是”完成”的定义
- 👤 最终部署由人审批
你的 Scenario 就是派出去的 24 小时值班安全员。
第四步:构建安全策略集
小组任务(3-4 人一组)
维度(至少选三个):
- 🔐 鉴权与授权
- 🔒 数据保护(脱敏)
- ⏱️ 速率限制
- 🛡️ 输入校验
产出物:
- 每个维度的
.spec.md文件 - 策略索引 README
小组展示任务(5分钟/组)
展示内容:
- 选了哪条 Requirement?
- 对应项目的哪段代码?
- Scenario 如何定义”对”和”错”?
评价标准:
- ✅ Purpose 清楚吗?
- ✅ SHALL/MUST 用得对吗?
- ✅ Scenario 的 THEN 可验证吗?
- ✅ 边界 Scenario 考虑了吗?
模块三:综合实战
场景:新项目 order-api 需上线前安全检查
| 阶段 | 任务 | 时间 |
|---|---|---|
| 🔍 代码审计 | 找出安全问题(预埋 5 个) | 15 分钟 |
| 📋 编写规格 | 选 2 个问题写 OpenSpec | 15 分钟 |
| 🎤 展示汇报 | 问题→代码位置→Requirement→Scenario | 15 分钟 |
预埋问题:明文身份证号、无鉴权、SQL 拼接、日志泄露 token、硬编码密码
从 Vibe 到 SDD:完整路径回顾
Vibe 时代(靠人盯): 经验在脑子里 → 人工抽查 → 发邮件 → 追着改 → 祈祷别忘 → 再抽查 → 循环……
SDD 时代(靠系统跑): 经验写成 OpenSpec → 提交 Git → CI 解析 Scenario → Ralph Loop 验证 → 不满足 THEN 就拦截 ✅
| 以前 | 以后 |
|---|---|
| 🔍 漏洞发现者 | 📐 安全标准定义者 |
| 📧 整改督促员 | 🤖 策略自动化运营者 |
| 👤 依赖个人经验 | 🏛️ 安全能力变成组织资产 |
你今天学到的完整技术栈
安全经验(在脑子里)
↓
OpenSpec 规格文件(Markdown)
= Harness 定义
↓
OpenCode 生成(Scenario → 检查逻辑)
↓
Ralph Loop 循环(逐条验证 THEN)
= Harness 执行
↓
安全合规报告 ✅
| 技术 | 解决的问题 |
|---|---|
| 📐 OpenSpec | “规是什么” |
| 🛠️ Harness | “边界在哪” |
| 🔄 OpenCode | “怎么翻译” |
| 🔁 Ralph Loop | “怎么做到位” |
今天你带走的不只是一份 MD
- 🧠 能读懂简单代码,定位安全问题
- 📋 能把安全经验转化为 OpenSpec 规格
- 🔧 理解 Scenario 如何变成自动化检查
- 🔄 理解 Harness + Ralph Loop 的 7×24 运转
- 🚀 获得从”靠人盯”到”靠系统跑”的迁移路径
你写下的每个 Scenario,在你睡觉时仍然在被 Ralph Loop 逐条验证。
回到岗位后的第一件事
本周:
- 找出团队最头疼的一个安全问题
- 用 OpenSpec 格式写出第一份规格文件
- 跑一次
opencode audit - 在团队分享会上展示
一个月:
- TOP 3 安全事件 → OpenSpec 规格
- 接入 CI,至少一条实现”不合规不能上线”
- 建立团队规格仓库
哪怕只有一个 Scenario 跑起来,都是一次职业能力的实质性升维。
Q&A / 附录资源
随堂资料:
- 📋 代码速查卡(Python 语法)
- 🕵️ 安全模式匹配表
- 📐 OpenSpec 格式速查卡
- 🗂️ 模拟项目仓库地址
延伸阅读:
- OpenSpec 官方文档
- Harness Engineering(Anthropic 博客)
- Ralph Loop 社区演进
- GIVEN/WHEN/THEN 在 BDD 中的应用
谢谢!欢迎随时交流 🛡️
Harness 定义”什么是对的”,Ralph Loop 确保”对的一定被验证”。 安全工程师的未来,不是做更多的检查,而是定义让系统自动遵守的边界。