fix(agent): list_assets 按任务范围过滤,修复任务间资产互串 (#59)
list_assets 此前把任务 id 写死为 0、裸查整个共享资产库,模型又无从写出 范围过滤条件,于是把别的任务的资产(尤其 IP)当成本任务目标,测试方向 被带偏。 - 新增 QueryDSLInScope / GetByIDsInScope:只返回落在【本任务及直接关联 任务】task_scope 内的资产,按归属匹配而非字面值(根域范围含其全部子域/ 服务/接口,网段范围含段内主机及服务);越权 id 静默丢弃 - 新增 scopeTargetCTE(纯 scope 归属判定,不含 anchor/tested);whereBuilder 加占位符偏移,$1 留给 taskID - 修复 IP 直连主机(http://1.2.3.4/api)无法被网段范围命中的盲区:谓词加 OR ts.net >>= try_inet(a.domain) - 非任务上下文(Auto/pentest, taskID<=0)无范围可依,回退全库 - QueryDSL/CountDSL 原样未动,UI 的「测试资产」视图(按生产者过滤)不受影响
This commit is contained in:
1 parent
16e87b48c2
commit
4ccb8f4ff2
5 files changed
+267
-7
No files matched your search
@@ -52,6 +52,42 @@ tested AS (
|
||||
JOIN context_tasks ctx ON ctx.exploration_id=en.exploration_id
|
||||
)`
|
||||
|
||||
// scopeTargetCTE selects every asset that BELONGS to the current task's (and its
|
||||
// direct source tasks') declared scope — membership, not literal value: a
|
||||
// root_domain scope pulls in every subdomain / service / endpoint whose own
|
||||
// root_domain column equals it; an ip/cidr scope pulls in assets whose ip OR
|
||||
// IP-literal host falls inside the net. $1 is the task id. Unlike contextCoverageCTE
|
||||
// it carries neither the fact-anchor union nor the tested set — it is pure "in
|
||||
// declared scope", independent of what has already been touched. Used by the
|
||||
// agent's list_assets so a query returns the task's relevant assets, not the
|
||||
// whole shared库.
|
||||
const scopeTargetCTE = `
|
||||
context_tasks AS (
|
||||
SELECT t.id AS task_id
|
||||
FROM tasks t
|
||||
WHERE t.id=$1 AND t.deleted_at IS NULL
|
||||
UNION ALL
|
||||
SELECT source.id
|
||||
FROM task_relations relation
|
||||
JOIN tasks source ON source.id=relation.source_task_id AND source.deleted_at IS NULL
|
||||
WHERE relation.task_id=$1
|
||||
),
|
||||
target AS (
|
||||
SELECT DISTINCT a.id
|
||||
FROM assets a
|
||||
JOIN task_scope ts ON (
|
||||
(ts.kind='company' AND a.company_id = ts.company_id)
|
||||
OR (ts.kind='root_domain' AND a.root_domain = ts.domain)
|
||||
OR (ts.kind='subdomain' AND a.domain = ts.domain)
|
||||
OR (ts.kind IN ('ip','cidr') AND (ts.net >>= try_inet(a.ip) OR ts.net >>= try_inet(a.domain)))
|
||||
OR (ts.kind='icp' AND (
|
||||
lower(regexp_replace(COALESCE(a.icp,''), '[[:space:]]+', '', 'g')) = ts.value
|
||||
OR lower(regexp_replace(COALESCE(a.app_icp,''), '[[:space:]]+', '', 'g')) = ts.value
|
||||
))
|
||||
)
|
||||
JOIN context_tasks ctx ON ctx.task_id=ts.task_id
|
||||
)`
|
||||
|
||||
// ListTaskScopeWithSources returns the current task's scope followed by the
|
||||
// scopes of its direct source tasks. TaskScope.TaskID preserves provenance.
|
||||
func (s *AssetStore) ListTaskScopeWithSources(taskID int64) ([]TaskScope, error) {
|
||||
|
||||
Reference in new issue
Block a user