残留批次A:成员删除、PR needs_local_worker 落库、推送 DNS TOCTOU
- 成员删除:DELETE /projects/{id}/members/{user_id},限 owner 或
全局管理员,禁删唯一 owner,记 remove_member 审计
(AuthStore.remove_member + server 分发,沿用 PATCH 守卫口径)
- PR needs_local_worker 落库:非 local 扫到 queued 任务时 CAS
写行状态为 needs_local_worker;claim/find_open 同步认该状态,
标记过的行仍可被 local worker 认领、不被搁置;另修
claim/find_open 对裸 sqlite3 tuple 行的 dict() 兜底
(TypeError/ValueError)
- 推送 DNS TOCTOU:发送改走建连时解析+判段的连接类,解析
一次、只拨判过的 IP,Host/SNI 仍为原域名;opener 直接构造
以排除 ProxyHandler 改写(build_opener 默认会塞代理)
This commit is contained in:
1 parent
6e3eb7ba11
commit
9bb9a50e4e
10 files changed
+725
-38
No files matched your search
+27
-15
@@ -153,7 +153,8 @@ from cloud.sub2api import gateway_name as _gateway_name
|
||||
from cloud.sub2api import gateway_origin as _gateway_origin
|
||||
from cloud.sub2api import list_gateway_models as _list_gateway_models
|
||||
from cloud.pr import PrSkipped, PrStepError
|
||||
from cloud.pr_exec import (claim_pr_job, execute_task_pr, finish_pr_job)
|
||||
from cloud.pr_exec import (claim_pr_job, execute_task_pr, finish_pr_job,
|
||||
mark_pr_job_needs_local_worker)
|
||||
from cloud.queue import budget_exceeded, ready_tasks
|
||||
from cloud.repos import RepoError, checkout_dir, resolve_repo
|
||||
from cloud.sandbox import CloudExecutor, DockerExecutor, LocalExecutor
|
||||
@@ -3547,19 +3548,15 @@ class Worker:
|
||||
P1 非 local 通道:旧版非 local worker 直接返回 [],
|
||||
排队的 pr 任务看起来像“没人处理”且无任何痕迹——
|
||||
静默未完成。现在改为显式 needs_local_worker:只读
|
||||
peek 本主机 queued 的 pr 任务,逐条记审计 + 日志并
|
||||
返回 needs_local_worker 条目,任务本身保持 merged、
|
||||
pr 任务保持 queued(留给 local worker 认领),绝不
|
||||
把它标 failed(failed 会让调用方以为 PR 已失败,且
|
||||
任务仍可重调 /pr 的语义会被混淆)。为什么不直接把
|
||||
pr_jobs 行写成 needs_local_worker 状态:pr_jobs 的认
|
||||
领只认 queued(claim_pr_job 在 pr_exec.py,本路不改
|
||||
该文件),写成新状态后 local worker 也认领不到,任务
|
||||
会被永久搁置;真要落库状态,需 pr_exec.py 的认领同
|
||||
步改成含 needs_local_worker 或 local 重排队——该改动
|
||||
留给协调员(见汇报残留),本路不伪造一个“写了状态
|
||||
却没人能接”的通道。签名无效时同样不碰任务(返回 [],
|
||||
只记日志),fail-closed。
|
||||
peek 本主机 queued 的 pr 任务,逐条把行状态持久化
|
||||
为 needs_local_worker(CAS,只改仍是 queued 的行,
|
||||
已被 local worker 认领的不覆盖),并记审计 + 日志
|
||||
返回 needs_local_worker 条目。任务本身保持 merged,
|
||||
pr 任务保持可被 local worker 认领(claim_pr_job
|
||||
同时认 queued 与 needs_local_worker),绝不把它标
|
||||
failed(failed 会让调用方以为 PR 已失败,且任务仍
|
||||
可重调 /pr 的语义会被混淆)。签名无效时同样不碰
|
||||
任务(返回 [],只记日志),fail-closed。
|
||||
"""
|
||||
if not self._code_signature_valid():
|
||||
log_event(self.logger, "worker_pr_refused_code_signature",
|
||||
@@ -3588,8 +3585,23 @@ class Worker:
|
||||
continue
|
||||
reason = ("PR 执行需要 local worker(host-worktrees"
|
||||
" 只在主机上可见),本 worker 为 %s,"
|
||||
"任务保持 queued 等 local worker 认领"
|
||||
"任务保持可认领等 local worker 认领"
|
||||
% self._executor_name())
|
||||
marked = False
|
||||
try:
|
||||
conn = _db_connect(self.db_path)
|
||||
try:
|
||||
marked = mark_pr_job_needs_local_worker(
|
||||
conn, job_id, reason)
|
||||
finally:
|
||||
conn.close()
|
||||
except Exception as exc:
|
||||
log_event(self.logger, "pr_job_mark_failed",
|
||||
message="pr job mark failed: %s" % exc)
|
||||
continue
|
||||
if not marked:
|
||||
# 已被 local worker 认领或已终态:不覆盖、不重复记。
|
||||
continue
|
||||
self._audit(project_id, "pr_job_needs_local_worker",
|
||||
"%s: %s" % (job_id, reason))
|
||||
log_event(self.logger, "pr_job_needs_local_worker",
|
||||
|
||||
Reference in new issue
Block a user