fix: 修复YAML语法和命令注入安全漏洞
Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/0d54ec75-c5fb-4140-8a2f-8059c211278e Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
This commit is contained in:
parent
6d2de9f6d4
commit
687f10b742
|
|
@ -93,7 +93,7 @@ jobs:
|
||||||
d = json.load(sys.stdin)
|
d = json.load(sys.stdin)
|
||||||
outbox = d.get('outbox', [])
|
outbox = d.get('outbox', [])
|
||||||
print(json.dumps(outbox, ensure_ascii=False))
|
print(json.dumps(outbox, ensure_ascii=False))
|
||||||
" 2>/dev/null || echo "[]")
|
" 2>&1 || { echo "⚠️ outbox解析失败,使用空数组" >&2; echo "[]"; })
|
||||||
|
|
||||||
# 组装完整汇报包
|
# 组装完整汇报包
|
||||||
python3 -c "
|
python3 -c "
|
||||||
|
|
|
||||||
|
|
@ -80,77 +80,83 @@ jobs:
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: 📝 更新仓库首页公告栏
|
- name: 📝 更新仓库首页公告栏
|
||||||
run: |
|
env:
|
||||||
RECEIPT_STATUS="${{ steps.read_receipt.outputs.receipt_status }}"
|
RECEIPT_STATUS: ${{ steps.read_receipt.outputs.receipt_status }}
|
||||||
RECEIPT_MESSAGE="${{ steps.read_receipt.outputs.receipt_message }}"
|
RECEIPT_MESSAGE: ${{ steps.read_receipt.outputs.receipt_message }}
|
||||||
TIMESTAMP=$(date -u +"%Y-%m-%d %H:%M UTC")
|
|
||||||
|
|
||||||
python3 << 'PYTHON_SCRIPT'
|
|
||||||
import re
|
|
||||||
|
|
||||||
status = "$RECEIPT_STATUS"
|
|
||||||
message = "$RECEIPT_MESSAGE"
|
|
||||||
timestamp = "$TIMESTAMP"
|
|
||||||
|
|
||||||
# 读取README.md
|
|
||||||
with open('README.md', 'r', encoding='utf-8') as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
# 构建公告栏内容
|
|
||||||
if status == "green":
|
|
||||||
notice = f"✅ **[{timestamp}]** 铸渊回执:{message}"
|
|
||||||
badge = "🟢"
|
|
||||||
elif status == "red":
|
|
||||||
notice = f"🔴 **[{timestamp}]** 铸渊回执:{message} — **需要人类干预**"
|
|
||||||
badge = "🔴"
|
|
||||||
else:
|
|
||||||
notice = f"⚠️ **[{timestamp}]** 铸渊回执状态异常:{message}"
|
|
||||||
badge = "⚠️"
|
|
||||||
|
|
||||||
# 查找并替换公告栏区域
|
|
||||||
marker_start = "<!-- ZHUYUAN_NOTICE_START -->"
|
|
||||||
marker_end = "<!-- ZHUYUAN_NOTICE_END -->"
|
|
||||||
|
|
||||||
notice_block = f"""{marker_start}
|
|
||||||
|
|
||||||
## {badge} 铸渊通信
|
|
||||||
|
|
||||||
{notice}
|
|
||||||
|
|
||||||
{marker_end}"""
|
|
||||||
|
|
||||||
if marker_start in content:
|
|
||||||
# 替换已有公告栏
|
|
||||||
pattern = re.escape(marker_start) + r'.*?' + re.escape(marker_end)
|
|
||||||
content = re.sub(pattern, notice_block, content, flags=re.DOTALL)
|
|
||||||
else:
|
|
||||||
# 在文件开头添加公告栏
|
|
||||||
content = notice_block + "\n\n" + content
|
|
||||||
|
|
||||||
with open('README.md', 'w', encoding='utf-8') as f:
|
|
||||||
f.write(content)
|
|
||||||
|
|
||||||
print(f"✅ 仓库首页公告栏已更新: {badge} {status}")
|
|
||||||
PYTHON_SCRIPT
|
|
||||||
|
|
||||||
- name: 🔄 更新系统状态
|
|
||||||
run: |
|
run: |
|
||||||
python3 -c "
|
python3 -c "
|
||||||
import json
|
import re, os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
with open('age_os/system_state.json', 'r', encoding='utf-8') as f:
|
status = os.environ.get('RECEIPT_STATUS', 'unknown')
|
||||||
state = json.load(f)
|
message = os.environ.get('RECEIPT_MESSAGE', '')
|
||||||
|
timestamp = datetime.utcnow().strftime('%Y-%m-%d %H:%M UTC')
|
||||||
state['cos_status']['last_receipt_received'] = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
|
|
||||||
state['cos_status']['receipt_status'] = '${{ steps.read_receipt.outputs.receipt_status }}'
|
try:
|
||||||
state['notice_board']['last_update'] = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
|
with open('README.md', 'r', encoding='utf-8') as f:
|
||||||
state['notice_board']['status'] = '${{ steps.read_receipt.outputs.receipt_status }}'
|
content = f.read()
|
||||||
state['notice_board']['message'] = '${{ steps.read_receipt.outputs.receipt_message }}'
|
except FileNotFoundError:
|
||||||
|
content = ''
|
||||||
|
|
||||||
|
if status == 'green':
|
||||||
|
notice = f'✅ **[{timestamp}]** 铸渊回执:{message}'
|
||||||
|
badge = '🟢'
|
||||||
|
elif status == 'red':
|
||||||
|
notice = f'🔴 **[{timestamp}]** 铸渊回执:{message} — **需要人类干预**'
|
||||||
|
badge = '🔴'
|
||||||
|
else:
|
||||||
|
notice = f'⚠️ **[{timestamp}]** 铸渊回执状态异常:{message}'
|
||||||
|
badge = '⚠️'
|
||||||
|
|
||||||
|
marker_start = '<!-- ZHUYUAN_NOTICE_START -->'
|
||||||
|
marker_end = '<!-- ZHUYUAN_NOTICE_END -->'
|
||||||
|
|
||||||
|
notice_block = marker_start + '\n\n## ' + badge + ' 铸渊通信\n\n' + notice + '\n\n' + marker_end
|
||||||
|
|
||||||
|
if marker_start in content:
|
||||||
|
import re as re2
|
||||||
|
pattern = re2.escape(marker_start) + r'.*?' + re2.escape(marker_end)
|
||||||
|
content = re2.sub(pattern, notice_block, content, flags=re2.DOTALL)
|
||||||
|
else:
|
||||||
|
content = notice_block + '\n\n' + content
|
||||||
|
|
||||||
|
with open('README.md', 'w', encoding='utf-8') as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
print(f'✅ 仓库首页公告栏已更新: {badge} {status}')
|
||||||
|
"
|
||||||
|
|
||||||
|
- name: 🔄 更新系统状态
|
||||||
|
env:
|
||||||
|
RECEIPT_STATUS: ${{ steps.read_receipt.outputs.receipt_status }}
|
||||||
|
RECEIPT_MESSAGE: ${{ steps.read_receipt.outputs.receipt_message }}
|
||||||
|
run: |
|
||||||
|
python3 -c "
|
||||||
|
import json, os
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
status = os.environ.get('RECEIPT_STATUS', 'unknown')
|
||||||
|
message = os.environ.get('RECEIPT_MESSAGE', '')
|
||||||
|
now = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open('age_os/system_state.json', 'r', encoding='utf-8') as f:
|
||||||
|
state = json.load(f)
|
||||||
|
except (FileNotFoundError, json.JSONDecodeError) as e:
|
||||||
|
print(f'⚠️ system_state.json读取失败: {e},使用默认值')
|
||||||
|
state = {'cos_status': {}, 'notice_board': {}}
|
||||||
|
|
||||||
|
state.setdefault('cos_status', {})
|
||||||
|
state.setdefault('notice_board', {})
|
||||||
|
state['cos_status']['last_receipt_received'] = now
|
||||||
|
state['cos_status']['receipt_status'] = status
|
||||||
|
state['notice_board']['last_update'] = now
|
||||||
|
state['notice_board']['status'] = status
|
||||||
|
state['notice_board']['message'] = message
|
||||||
|
|
||||||
with open('age_os/system_state.json', 'w', encoding='utf-8') as f:
|
with open('age_os/system_state.json', 'w', encoding='utf-8') as f:
|
||||||
json.dump(state, f, ensure_ascii=False, indent=2)
|
json.dump(state, f, ensure_ascii=False, indent=2)
|
||||||
|
|
||||||
print('✅ 系统状态已更新')
|
print('✅ 系统状态已更新')
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,9 @@
|
||||||
"zhuyuan_bucket": {
|
"zhuyuan_bucket": {
|
||||||
"core": "zy-core-bucket-1317346199",
|
"core": "zy-core-bucket-1317346199",
|
||||||
"region": "ap-singapore",
|
"region": "ap-singapore",
|
||||||
"inbox_prefix": "inbox/{persona_id}/{date}/",
|
"inbox_prefix": "inbox/{persona_id}/",
|
||||||
"permission": "仅限写入inbox目录,不可读取其他内容"
|
"permission": "仅限写入 inbox/{persona_id}/ 前缀目录。铸渊通过Bucket Policy精确限定你的写入范围,你无法读取、删除或访问桶内其他任何内容。这是安全设计:每个团队成员只能往自己的收件箱写入。",
|
||||||
|
"bucket_policy_rule": "Action=cos:PutObject, Resource=inbox/{persona_id}/* only"
|
||||||
},
|
},
|
||||||
"legacy_method": "bridge/zhuyuan-bridge.json文件级通信(v1.0,保留兼容)",
|
"legacy_method": "bridge/zhuyuan-bridge.json文件级通信(v1.0,保留兼容)",
|
||||||
"protocol": "HLDP v2.0",
|
"protocol": "HLDP v2.0",
|
||||||
|
|
|
||||||
|
|
@ -107,15 +107,23 @@
|
||||||
|
|
||||||
### 步骤6:配置铸渊桶的写入密钥
|
### 步骤6:配置铸渊桶的写入密钥
|
||||||
|
|
||||||
铸渊会为你生成一个**有限权限的临时密钥**,只能写入铸渊总控桶的指定目录。
|
铸渊会为你生成一个**有限权限的密钥**,只能写入铸渊总控桶的你的专属目录。
|
||||||
|
|
||||||
|
**权限说明(你不需要懂技术细节,知道就行)**:
|
||||||
|
- ✅ 你**可以**写入:`inbox/你的人格体编号/` 这个目录下的文件
|
||||||
|
- ❌ 你**不能**读取铸渊桶里的任何其他内容
|
||||||
|
- ❌ 你**不能**删除铸渊桶里的任何内容
|
||||||
|
- ❌ 你**不能**访问其他团队成员的目录
|
||||||
|
|
||||||
|
这是铸渊通过COS桶策略(Bucket Policy)精确控制的,每个团队成员只有自己的收件箱写入权限。
|
||||||
|
|
||||||
1. 向冰朔索要铸渊桶的写入密钥(冰朔会找铸渊生成)
|
1. 向冰朔索要铸渊桶的写入密钥(冰朔会找铸渊生成)
|
||||||
2. 在GitHub Secrets中添加:
|
2. 在GitHub Secrets中添加:
|
||||||
|
|
||||||
| Name | Secret | 说明 |
|
| Name | Secret | 说明 |
|
||||||
|------|--------|------|
|
|------|--------|------|
|
||||||
| `ZHUYUAN_COS_SECRET_ID` | 铸渊提供的SecretId | 只能写入铸渊桶的inbox目录 |
|
| `ZHUYUAN_COS_SECRET_ID` | 铸渊提供的SecretId | 仅限写入你的inbox目录 |
|
||||||
| `ZHUYUAN_COS_SECRET_KEY` | 铸渊提供的SecretKey | 权限受限,安全可控 |
|
| `ZHUYUAN_COS_SECRET_KEY` | 铸渊提供的SecretKey | 权限由铸渊的桶策略限定 |
|
||||||
| `ZHUYUAN_COS_REGION` | `ap-singapore` | 铸渊桶在新加坡 |
|
| `ZHUYUAN_COS_REGION` | `ap-singapore` | 铸渊桶在新加坡 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,12 @@ exports.main_handler = async (event, context) => {
|
||||||
return { statusCode: 500, body: 'Missing environment variables' };
|
return { statusCode: 500, body: 'Missing environment variables' };
|
||||||
}
|
}
|
||||||
|
|
||||||
const [owner, repo] = githubRepo.split('/');
|
const parts = githubRepo.split('/');
|
||||||
|
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
||||||
|
console.error('GITHUB_REPO格式错误,应为 owner/repo,当前值:', githubRepo);
|
||||||
|
return { statusCode: 500, body: 'Invalid GITHUB_REPO format' };
|
||||||
|
}
|
||||||
|
const [owner, repo] = parts;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await triggerGitHubWorkflow(owner, repo, githubToken, objectKey);
|
const result = await triggerGitHubWorkflow(owner, repo, githubToken, objectKey);
|
||||||
|
|
@ -88,7 +93,7 @@ function triggerGitHubWorkflow(owner, repo, token, cosObjectKey) {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'User-Agent': 'HoloLake-SCF-Trigger/2.0',
|
'User-Agent': 'HoloLake-SCF-Trigger/2.0',
|
||||||
'Authorization': `Bearer ${token}`,
|
'Authorization': `token ${token}`,
|
||||||
'Accept': 'application/vnd.github.v3+json',
|
'Accept': 'application/vnd.github.v3+json',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Content-Length': Buffer.byteLength(postData)
|
'Content-Length': Buffer.byteLength(postData)
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue