security: rustdesk出库+ignore;nginx静态location补齐安全头(修add_header继承丢失);tasks.py原子写;backup.sh可选异地;拍板清单落盘
vscode-planning-ci / planning-smoke (push) Waiting to run

This commit is contained in:
2026-09-25 04:27:42 +08:00
parent 2c9979144f
commit d409606a57
5 changed files with 73 additions and 4 deletions
+3 -1
View File
@@ -6,6 +6,9 @@
(服务器数据)重要!!!禁止上传git/ (服务器数据)重要!!!禁止上传git/
*.pem *.pem
id_ed25519* id_ed25519*
# 远控配置(含中转服务器地址与永久密码哈希,绝不入库)
rustdesk-config-export/
.dsh/ .dsh/
.dsh-runtime-backup/ .dsh-runtime-backup/
.pnpm-store/ .pnpm-store/
@@ -14,7 +17,6 @@ node_modules/
android-chunyu/ android-chunyu/
chunyu_project/ chunyu_project/
chunyu_project_react/ chunyu_project_react/
node_modules/
shots/ shots/
docker.env docker.env
backups/ backups/
+15 -3
View File
@@ -21,8 +21,10 @@ from __future__ import annotations
import argparse import argparse
import json import json
import os
import re import re
import sys import sys
import tempfile
from datetime import date from datetime import date
from pathlib import Path from pathlib import Path
@@ -56,9 +58,19 @@ def load_state() -> dict:
def save_state(state: dict) -> None: def save_state(state: dict) -> None:
STATE.write_text( # 原子写:先落同目录临时文件再 os.replace,避免并发写或中断产生半截 state.json
json.dumps(state, ensure_ascii=False, indent=2) + "\n", encoding="utf-8" payload = json.dumps(state, ensure_ascii=False, indent=2) + "\n"
) fd, tmp = tempfile.mkstemp(dir=str(STATE.parent), prefix=".state-", suffix=".tmp")
try:
with os.fdopen(fd, "w", encoding="utf-8") as f:
f.write(payload)
os.replace(tmp, STATE)
except BaseException:
try:
os.unlink(tmp)
except OSError:
pass
raise
def effective_status(task: dict, state: dict) -> str: def effective_status(task: dict, state: dict) -> str:
+37
View File
@@ -0,0 +1,37 @@
# 安全遗留拍板清单 / SECURITY_DECISIONS.md
日期: 2026-09-25 · 前置: 全局检测报告(架构/安全/业务/部署四方向)
## 本轮已修(仅本仓库,不触碰线上运行)
1. **rustdesk-config-export 出库 + ignore**:远控中转服务器地址与永久密码哈希不再随 HEAD 分发(历史对象仍在,见 D1)。磁盘文件已保留。
2. **nginx-docker.conf**:4 个自带 `add_header` 的 location(/api-directory/、/assets、静态资源、/index.html)补齐 nosniff / X-Frame-Options / Referrer-Policy,修复 add_header 层级覆盖继承导致的静态响应裸奔。
- 生效条件:服务器上 `docker compose restart frontend`(pull 本仓不会热生效,线上运行不受影响)。
3. **PLANNING/tasks.py**:state.json 改为临时文件 + `os.replace` 原子写(防并发/中断写坏;多进程同时读改写的丢失更新窗口仍在,量级可接受)。
4. **infra/backup.sh**:新增可选 `BACKUP_REMOTE_DIR`(设置后自动 rsync 异地副本,不设则行为不变)。
5. **B6 产物出库复核**:当前跟踪的 png/log/tar.gz 为 0,88 项实际已在 6d22fb1 完成,SECURITY_FIX 文档该条滞后。
## 待拍板(不可逆 / 涉及线上或远程仓库,一句话确认即可执行对应项)
### D1 git 历史清理(docker.env 真实密码 + rustdesk 配置仍可从历史取回)
```bash
pip install git-filter-repo
git filter-repo --invert-paths --path docker.env --path rustdesk-config-export --force
git remote add origin https://gitea.mymoyu.top/root/vscode-workbench.git # filter-repo 会移除 remote
git push origin master --force
```
影响:改写远程历史,所有 clone 需重新拉取;需确认无其他协作者持有旧 clone。
### D2 RustDesk 服务器侧加固(需操作远控,改即生效)
- 被控端更换永久密码(客户端 设置→安全→永久密码),更换后本机 rustdesk-config-export 重新导出才会更新。
- 103.40.14.100 的 hbbs/hbbr(51116-51118)加来源 IP 白名单或防火墙限制。
### D3 线上 B1-B5(沿用 SECURITY_FIX_SPEC.md deferred 清单,均需停机/线上授权)
B1 线上密钥全量轮换(含 DJANGO_SECRET_KEY,会使现有 session 失效) / B2 生产 TLS+HSTS / B3 服务器防火墙收紧 / B5 容器 USER 非 root。
### D4 model-registry.json 分值基准(六维合计 42 vs total_max=36)
修哪边决定 grade 换算基准(dim5<50% veto 的分母含义不同),需评分口径拍板后改,未拍板前不动。
### D5 主工程源码仓库归属
chunyu_project / chunyu_project_react 不在本仓版本控制与备份范围(.gitignore),compose build 与 task-manifest 均指向本地目录。需确认是否已有独立 repo;若无,建仓并纳入备份。
## 注意事项
- 本轮提交推送后,其他机器 `git pull` 会从其工作区移除 rustdesk-config-export 目录(git rm --cached 语义);若服务器上有引用请先拷贝。
- nginx-docker.conf 属已跟踪文件,本仓修改不会自动影响线上;需在服务器手动 restart frontend 才生效。
+5
View File
@@ -12,5 +12,10 @@ sha256sum "$ARCHIVE" > "$ARCHIVE.sha256"
# 保留策略:只留最近 7 个归档 # 保留策略:只留最近 7 个归档
ls -1t "$OUT_DIR"/planning-backup-*.tar.gz 2>/dev/null | tail -n +8 | xargs -r rm -f ls -1t "$OUT_DIR"/planning-backup-*.tar.gz 2>/dev/null | tail -n +8 | xargs -r rm -f
ls -1t "$OUT_DIR"/planning-backup-*.tar.gz.sha256 2>/dev/null | tail -n +8 | xargs -r rm -f ls -1t "$OUT_DIR"/planning-backup-*.tar.gz.sha256 2>/dev/null | tail -n +8 | xargs -r rm -f
# 可选异地副本:设置 BACKUP_REMOTE_DIR(形如 user@host:/backups/planning)即同步,不设则跳过
if [ -n "${BACKUP_REMOTE_DIR:-}" ] && command -v rsync >/dev/null 2>&1; then
rsync -a "$OUT_DIR"/planning-backup-*.tar.gz "$OUT_DIR"/planning-backup-*.tar.gz.sha256 "$BACKUP_REMOTE_DIR/"
echo "offsite: $BACKUP_REMOTE_DIR"
fi
echo "backup: $ARCHIVE" echo "backup: $ARCHIVE"
cat "$ARCHIVE.sha256" cat "$ARCHIVE.sha256"
+13
View File
@@ -15,6 +15,10 @@ server {
try_files $uri =404; try_files $uri =404;
expires 1y; expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable" always; add_header Cache-Control "public, max-age=31536000, immutable" always;
# nginx 的 add_header 按层级整体覆盖继承:自带 add_header 的 location 必须重复安全头
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
types { types {
image/avif avif; image/avif avif;
image/gif gif; image/gif gif;
@@ -237,6 +241,9 @@ server {
location ~* ^/assets/.*\.(js|css|png|jpg|jpeg|gif|webp|avif|ico|svg|woff|woff2|ttf|eot)$ { location ~* ^/assets/.*\.(js|css|png|jpg|jpeg|gif|webp|avif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y; expires 1y;
add_header Cache-Control "public, immutable"; add_header Cache-Control "public, immutable";
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
access_log off; access_log off;
} }
@@ -244,12 +251,18 @@ server {
location ~* \.(png|jpg|jpeg|gif|webp|ico|svg|woff|woff2|ttf|eot)$ { location ~* \.(png|jpg|jpeg|gif|webp|ico|svg|woff|woff2|ttf|eot)$ {
expires 7d; expires 7d;
add_header Cache-Control "public"; add_header Cache-Control "public";
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
access_log off; access_log off;
} }
# index.html 不缓存,保证发版后立即生效 # index.html 不缓存,保证发版后立即生效
location = /index.html { location = /index.html {
add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
} }
# SPA 路由回退(放在最后,避免拦截上面的 API 请求) # SPA 路由回退(放在最后,避免拦截上面的 API 请求)