@telora/daemon 0.15.37 → 0.15.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build-info.json +2 -2
- package/dist/assembly-resolvers.d.ts +1 -1
- package/dist/assembly-resolvers.d.ts.map +1 -1
- package/dist/feeds/ghsa.d.ts +97 -0
- package/dist/feeds/ghsa.d.ts.map +1 -0
- package/dist/feeds/ghsa.js +226 -0
- package/dist/feeds/ghsa.js.map +1 -0
- package/dist/feeds/local.d.ts +55 -0
- package/dist/feeds/local.d.ts.map +1 -0
- package/dist/feeds/local.js +196 -0
- package/dist/feeds/local.js.map +1 -0
- package/dist/feeds/osv.d.ts +98 -0
- package/dist/feeds/osv.d.ts.map +1 -0
- package/dist/feeds/osv.js +277 -0
- package/dist/feeds/osv.js.map +1 -0
- package/dist/focus-engine.d.ts.map +1 -1
- package/dist/focus-engine.js +47 -0
- package/dist/focus-engine.js.map +1 -1
- package/dist/focus-executor.d.ts +53 -0
- package/dist/focus-executor.d.ts.map +1 -1
- package/dist/focus-executor.js +41 -26
- package/dist/focus-executor.js.map +1 -1
- package/dist/scanners/deps.d.ts +101 -0
- package/dist/scanners/deps.d.ts.map +1 -0
- package/dist/scanners/deps.js +242 -0
- package/dist/scanners/deps.js.map +1 -0
- package/dist/scanners/signatures.d.ts +44 -0
- package/dist/scanners/signatures.d.ts.map +1 -0
- package/dist/scanners/signatures.js +140 -0
- package/dist/scanners/signatures.js.map +1 -0
- package/dist/scanners/workflow.d.ts +42 -0
- package/dist/scanners/workflow.d.ts.map +1 -0
- package/dist/scanners/workflow.js +325 -0
- package/dist/scanners/workflow.js.map +1 -0
- package/dist/security-auto-inject.d.ts +114 -0
- package/dist/security-auto-inject.d.ts.map +1 -0
- package/dist/security-auto-inject.js +148 -0
- package/dist/security-auto-inject.js.map +1 -0
- package/dist/security-rescan-resolution.d.ts +84 -0
- package/dist/security-rescan-resolution.d.ts.map +1 -0
- package/dist/security-rescan-resolution.js +114 -0
- package/dist/security-rescan-resolution.js.map +1 -0
- package/dist/security-scan-engine.d.ts +102 -0
- package/dist/security-scan-engine.d.ts.map +1 -0
- package/dist/security-scan-engine.js +202 -0
- package/dist/security-scan-engine.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Severity-gated auto-injection for security findings.
|
|
3
|
+
*
|
|
4
|
+
* When the scanner engine writes a finding at or above the configured
|
|
5
|
+
* auto_inject_severity_threshold, this module:
|
|
6
|
+
* 1. Resolves the product's Security focus (focus_kind='security').
|
|
7
|
+
* 2. Creates or reuses an entity node representing the vulnerable surface.
|
|
8
|
+
* 3. Creates an injection node on the focus's reality tree with
|
|
9
|
+
* statement = advisory summary; targets the entity node via a
|
|
10
|
+
* reality_tree_edge of kind 'targets'.
|
|
11
|
+
* 4. Creates a delivery on the Security focus linked to the injection
|
|
12
|
+
* via the delivery's injection_id column.
|
|
13
|
+
* 5. Sets finding.linked_injection_id.
|
|
14
|
+
* 6. Writes a security_finding_audit row with action='auto_injected'.
|
|
15
|
+
*
|
|
16
|
+
* Below-threshold findings are not auto-injected; the FindingsView UI
|
|
17
|
+
* offers click-to-remediate that calls this same function with a
|
|
18
|
+
* `force: true` flag (single code path for both auto and manual).
|
|
19
|
+
*
|
|
20
|
+
* Suppressed findings (suppression jsonb non-null and not expired) are
|
|
21
|
+
* skipped entirely.
|
|
22
|
+
*
|
|
23
|
+
* @module security-auto-inject
|
|
24
|
+
*/
|
|
25
|
+
import { callApi } from './queries/shared.js';
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Severity comparison
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
const SEVERITY_RANK = {
|
|
30
|
+
low: 1,
|
|
31
|
+
medium: 2,
|
|
32
|
+
high: 3,
|
|
33
|
+
critical: 4,
|
|
34
|
+
};
|
|
35
|
+
/** Returns true when `severity` is at or above `threshold`. */
|
|
36
|
+
export function meetsThreshold(severity, threshold) {
|
|
37
|
+
return SEVERITY_RANK[severity] >= SEVERITY_RANK[threshold];
|
|
38
|
+
}
|
|
39
|
+
function isSuppressedAndActive(finding, now = new Date()) {
|
|
40
|
+
if (finding.status !== 'suppressed')
|
|
41
|
+
return false;
|
|
42
|
+
if (!finding.suppression)
|
|
43
|
+
return false;
|
|
44
|
+
const s = finding.suppression;
|
|
45
|
+
if (!s.expires_at)
|
|
46
|
+
return true;
|
|
47
|
+
return new Date(s.expires_at).getTime() > now.getTime();
|
|
48
|
+
}
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// Statement + label builders
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
function buildAdvisorySummary(finding) {
|
|
53
|
+
const payload = finding.payload;
|
|
54
|
+
const candidates = [
|
|
55
|
+
typeof payload.title === 'string' ? payload.title : null,
|
|
56
|
+
typeof payload.summary === 'string' ? payload.summary : null,
|
|
57
|
+
typeof payload.advisory_text === 'string' ? payload.advisory_text : null,
|
|
58
|
+
].filter((s) => Boolean(s));
|
|
59
|
+
const head = candidates[0] ?? `Security finding ${finding.identifier}`;
|
|
60
|
+
return `${head} (${finding.iocClass}, severity=${finding.severity})`;
|
|
61
|
+
}
|
|
62
|
+
function buildEntityLabel(finding) {
|
|
63
|
+
return `${finding.iocClass}:${finding.identifier}`;
|
|
64
|
+
}
|
|
65
|
+
export async function processNewFinding(finding, options, deps) {
|
|
66
|
+
if (finding.linkedInjectionId)
|
|
67
|
+
return { status: 'skipped_already_linked' };
|
|
68
|
+
if (isSuppressedAndActive(finding))
|
|
69
|
+
return { status: 'skipped_suppressed' };
|
|
70
|
+
if (!options.force && !meetsThreshold(finding.severity, options.autoInjectThreshold)) {
|
|
71
|
+
return { status: 'skipped_below_threshold' };
|
|
72
|
+
}
|
|
73
|
+
const focus = await deps.resolveSecurityFocus(finding.productId);
|
|
74
|
+
if (!focus)
|
|
75
|
+
return { status: 'skipped_no_security_focus' };
|
|
76
|
+
const entity = await deps.upsertEntityNode({
|
|
77
|
+
treeId: focus.treeId,
|
|
78
|
+
organizationId: finding.organizationId,
|
|
79
|
+
label: buildEntityLabel(finding),
|
|
80
|
+
payload: { ioc_class: finding.iocClass, identifier: finding.identifier },
|
|
81
|
+
});
|
|
82
|
+
const injection = await deps.createInjection({
|
|
83
|
+
treeId: focus.treeId,
|
|
84
|
+
organizationId: finding.organizationId,
|
|
85
|
+
statement: buildAdvisorySummary(finding),
|
|
86
|
+
targetNodeId: entity.nodeId,
|
|
87
|
+
sourcePayload: {
|
|
88
|
+
finding_id: finding.id,
|
|
89
|
+
ioc_class: finding.iocClass,
|
|
90
|
+
severity: finding.severity,
|
|
91
|
+
identifier: finding.identifier,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
const delivery = await deps.createDelivery({
|
|
95
|
+
focusId: focus.focusId,
|
|
96
|
+
productId: finding.productId,
|
|
97
|
+
organizationId: finding.organizationId,
|
|
98
|
+
name: `Remediate ${buildEntityLabel(finding)}`,
|
|
99
|
+
description: buildAdvisorySummary(finding),
|
|
100
|
+
injectionNodeId: injection.nodeId,
|
|
101
|
+
});
|
|
102
|
+
await deps.linkFinding(finding.id, injection.nodeId);
|
|
103
|
+
await deps.writeAudit({
|
|
104
|
+
findingId: finding.id,
|
|
105
|
+
organizationId: finding.organizationId,
|
|
106
|
+
action: options.force ? 'manually_remediated' : 'auto_injected',
|
|
107
|
+
actorUserId: options.actorUserId,
|
|
108
|
+
reason: options.force ? 'click_to_remediate' : 'severity_threshold_met',
|
|
109
|
+
payload: {
|
|
110
|
+
severity: finding.severity,
|
|
111
|
+
threshold: options.autoInjectThreshold,
|
|
112
|
+
delivery_id: delivery.deliveryId,
|
|
113
|
+
injection_node_id: injection.nodeId,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
return {
|
|
117
|
+
status: 'injected',
|
|
118
|
+
injectionNodeId: injection.nodeId,
|
|
119
|
+
deliveryId: delivery.deliveryId,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
// Default Deps -- daemon-side wiring via callApi.
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
export function buildDefaultAutoInjectDeps() {
|
|
126
|
+
return {
|
|
127
|
+
resolveSecurityFocus: async (productId) => {
|
|
128
|
+
const res = await callApi('daemon_resolve_security_focus', { productId });
|
|
129
|
+
return res?.focus ?? null;
|
|
130
|
+
},
|
|
131
|
+
upsertEntityNode: async (input) => {
|
|
132
|
+
return callApi('daemon_upsert_security_entity_node', input);
|
|
133
|
+
},
|
|
134
|
+
createInjection: async (input) => {
|
|
135
|
+
return callApi('daemon_create_security_injection', input);
|
|
136
|
+
},
|
|
137
|
+
createDelivery: async (input) => {
|
|
138
|
+
return callApi('daemon_create_security_delivery', input);
|
|
139
|
+
},
|
|
140
|
+
linkFinding: async (findingId, injectionNodeId) => {
|
|
141
|
+
await callApi('daemon_link_finding_to_injection', { findingId, injectionNodeId });
|
|
142
|
+
},
|
|
143
|
+
writeAudit: async (input) => {
|
|
144
|
+
await callApi('daemon_write_security_finding_audit', input);
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=security-auto-inject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-auto-inject.js","sourceRoot":"","sources":["../src/security-auto-inject.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-scan resolution: when a scan run completes that covered a finding's
|
|
3
|
+
* IOC class but did not re-produce a previously-open finding, flip the
|
|
4
|
+
* finding to 'resolved' and (if the linked injection's delivery is done)
|
|
5
|
+
* auto-verify the injection.
|
|
6
|
+
*
|
|
7
|
+
* Called by the scanner engine immediately after a run finishes writing
|
|
8
|
+
* its findings, before suppression-expiry sweeps and before the next
|
|
9
|
+
* tick begins.
|
|
10
|
+
*
|
|
11
|
+
* @module security-rescan-resolution
|
|
12
|
+
*/
|
|
13
|
+
export interface OpenFindingRow {
|
|
14
|
+
id: string;
|
|
15
|
+
organizationId: string;
|
|
16
|
+
productId: string;
|
|
17
|
+
iocClass: string;
|
|
18
|
+
identifier: string;
|
|
19
|
+
linkedInjectionId: string | null;
|
|
20
|
+
}
|
|
21
|
+
export interface ResolutionDeps {
|
|
22
|
+
/**
|
|
23
|
+
* Find all 'open' findings for the product that match the IOC classes
|
|
24
|
+
* the just-completed scan run covered. The engine knows which classes
|
|
25
|
+
* ran so the caller filters down to those.
|
|
26
|
+
*/
|
|
27
|
+
listOpenFindings: (productId: string, iocClasses: string[]) => Promise<OpenFindingRow[]>;
|
|
28
|
+
/** Set the finding to 'resolved' with resolved_at = now(). */
|
|
29
|
+
markFindingResolved: (findingId: string) => Promise<void>;
|
|
30
|
+
/** Append audit row for the resolution. */
|
|
31
|
+
writeAudit: (input: {
|
|
32
|
+
findingId: string;
|
|
33
|
+
organizationId: string;
|
|
34
|
+
action: 'resolved';
|
|
35
|
+
payload: Record<string, unknown>;
|
|
36
|
+
}) => Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Returns the execution_status of the delivery linked to the injection,
|
|
39
|
+
* or null if there is no such delivery.
|
|
40
|
+
*/
|
|
41
|
+
getInjectionDeliveryStatus: (injectionNodeId: string) => Promise<string | null>;
|
|
42
|
+
/** Compound op: retire the injection + promote FRT overlays to CRT. */
|
|
43
|
+
verifyInjection: (injectionNodeId: string) => Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Map of identifiers that the current run did emit, per IOC class.
|
|
47
|
+
*/
|
|
48
|
+
export interface ScanRunFindingSet {
|
|
49
|
+
iocClass: string;
|
|
50
|
+
identifiers: Set<string>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Resolve previously-open findings that didn't re-appear in this run.
|
|
54
|
+
*
|
|
55
|
+
* @returns the list of finding ids that were flipped to 'resolved'.
|
|
56
|
+
*/
|
|
57
|
+
export declare function resolveStaleFindings(productId: string, observedSets: ScanRunFindingSet[], deps: ResolutionDeps): Promise<string[]>;
|
|
58
|
+
export declare function buildDefaultResolutionDeps(): ResolutionDeps;
|
|
59
|
+
export interface SuppressionExpirySweepDeps {
|
|
60
|
+
/** Returns findings where status='suppressed' and suppression.expires_at < now(). */
|
|
61
|
+
listExpiredSuppressions: () => Promise<Array<{
|
|
62
|
+
id: string;
|
|
63
|
+
organizationId: string;
|
|
64
|
+
}>>;
|
|
65
|
+
/** Set status='open', suppression=null. */
|
|
66
|
+
unsuppressFinding: (findingId: string) => Promise<void>;
|
|
67
|
+
/** Append audit row with action='unsuppressed' and reason='suppression_expired'. */
|
|
68
|
+
writeAudit: (input: {
|
|
69
|
+
findingId: string;
|
|
70
|
+
organizationId: string;
|
|
71
|
+
action: 'unsuppressed';
|
|
72
|
+
payload: Record<string, unknown>;
|
|
73
|
+
}) => Promise<void>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Sweep suppressions whose expires_at has passed and flip them back to
|
|
77
|
+
* 'open'. Idempotent: a suppression already expired is a no-op on the
|
|
78
|
+
* second call because the predicate now matches status='open'.
|
|
79
|
+
*
|
|
80
|
+
* @returns the finding ids whose suppression was lifted.
|
|
81
|
+
*/
|
|
82
|
+
export declare function runSuppressionExpirySweep(deps: SuppressionExpirySweepDeps): Promise<string[]>;
|
|
83
|
+
export declare function buildDefaultSuppressionExpirySweepDeps(): SuppressionExpirySweepDeps;
|
|
84
|
+
//# sourceMappingURL=security-rescan-resolution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-rescan-resolution.d.ts","sourceRoot":"","sources":["../src/security-rescan-resolution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,gBAAgB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IACzF,8DAA8D;IAC9D,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,2CAA2C;IAC3C,UAAU,EAAE,CAAC,KAAK,EAAE;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC;QACvB,MAAM,EAAE,UAAU,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpB;;;OAGG;IACH,0BAA0B,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAChF,uEAAuE;IACvE,eAAe,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,iBAAiB,EAAE,EACjC,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,MAAM,EAAE,CAAC,CAqCnB;AAMD,wBAAgB,0BAA0B,IAAI,cAAc,CA0B3D;AAMD,MAAM,WAAW,0BAA0B;IACzC,qFAAqF;IACrF,uBAAuB,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACtF,2CAA2C;IAC3C,iBAAiB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,oFAAoF;IACpF,UAAU,EAAE,CAAC,KAAK,EAAE;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC;QACvB,MAAM,EAAE,cAAc,CAAC;QACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,0BAA0B,GAC/B,OAAO,CAAC,MAAM,EAAE,CAAC,CAcnB;AAED,wBAAgB,sCAAsC,IAAI,0BAA0B,CAgBnF"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-scan resolution: when a scan run completes that covered a finding's
|
|
3
|
+
* IOC class but did not re-produce a previously-open finding, flip the
|
|
4
|
+
* finding to 'resolved' and (if the linked injection's delivery is done)
|
|
5
|
+
* auto-verify the injection.
|
|
6
|
+
*
|
|
7
|
+
* Called by the scanner engine immediately after a run finishes writing
|
|
8
|
+
* its findings, before suppression-expiry sweeps and before the next
|
|
9
|
+
* tick begins.
|
|
10
|
+
*
|
|
11
|
+
* @module security-rescan-resolution
|
|
12
|
+
*/
|
|
13
|
+
import { callApi } from './queries/shared.js';
|
|
14
|
+
/**
|
|
15
|
+
* Resolve previously-open findings that didn't re-appear in this run.
|
|
16
|
+
*
|
|
17
|
+
* @returns the list of finding ids that were flipped to 'resolved'.
|
|
18
|
+
*/
|
|
19
|
+
export async function resolveStaleFindings(productId, observedSets, deps) {
|
|
20
|
+
const iocClasses = observedSets.map((s) => s.iocClass);
|
|
21
|
+
if (iocClasses.length === 0)
|
|
22
|
+
return [];
|
|
23
|
+
const openFindings = await deps.listOpenFindings(productId, iocClasses);
|
|
24
|
+
const observedByClass = new Map();
|
|
25
|
+
for (const set of observedSets) {
|
|
26
|
+
observedByClass.set(set.iocClass, set.identifiers);
|
|
27
|
+
}
|
|
28
|
+
const resolvedIds = [];
|
|
29
|
+
for (const finding of openFindings) {
|
|
30
|
+
const observedInClass = observedByClass.get(finding.iocClass);
|
|
31
|
+
if (!observedInClass)
|
|
32
|
+
continue;
|
|
33
|
+
if (observedInClass.has(finding.identifier))
|
|
34
|
+
continue;
|
|
35
|
+
// Finding was open, its class was covered, but it didn't re-appear.
|
|
36
|
+
await deps.markFindingResolved(finding.id);
|
|
37
|
+
await deps.writeAudit({
|
|
38
|
+
findingId: finding.id,
|
|
39
|
+
organizationId: finding.organizationId,
|
|
40
|
+
action: 'resolved',
|
|
41
|
+
payload: { reason: 'absent_in_rescan', ioc_class: finding.iocClass },
|
|
42
|
+
});
|
|
43
|
+
resolvedIds.push(finding.id);
|
|
44
|
+
// Auto-verify the linked injection if its delivery has reached 'done'.
|
|
45
|
+
if (finding.linkedInjectionId) {
|
|
46
|
+
const status = await deps.getInjectionDeliveryStatus(finding.linkedInjectionId);
|
|
47
|
+
if (status === 'done') {
|
|
48
|
+
await deps.verifyInjection(finding.linkedInjectionId);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return resolvedIds;
|
|
53
|
+
}
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Default Deps -- daemon-side wiring via callApi.
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
export function buildDefaultResolutionDeps() {
|
|
58
|
+
return {
|
|
59
|
+
listOpenFindings: async (productId, iocClasses) => {
|
|
60
|
+
const res = await callApi('daemon_list_open_security_findings', { productId, iocClasses });
|
|
61
|
+
return res.items ?? [];
|
|
62
|
+
},
|
|
63
|
+
markFindingResolved: async (findingId) => {
|
|
64
|
+
await callApi('daemon_resolve_security_finding', { findingId });
|
|
65
|
+
},
|
|
66
|
+
writeAudit: async (input) => {
|
|
67
|
+
await callApi('daemon_write_security_finding_audit', input);
|
|
68
|
+
},
|
|
69
|
+
getInjectionDeliveryStatus: async (injectionNodeId) => {
|
|
70
|
+
const res = await callApi('daemon_get_injection_delivery_status', { injectionNodeId });
|
|
71
|
+
return res.status;
|
|
72
|
+
},
|
|
73
|
+
verifyInjection: async (injectionNodeId) => {
|
|
74
|
+
await callApi('reality_tree_verify_injection', { injectionNodeId });
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Sweep suppressions whose expires_at has passed and flip them back to
|
|
80
|
+
* 'open'. Idempotent: a suppression already expired is a no-op on the
|
|
81
|
+
* second call because the predicate now matches status='open'.
|
|
82
|
+
*
|
|
83
|
+
* @returns the finding ids whose suppression was lifted.
|
|
84
|
+
*/
|
|
85
|
+
export async function runSuppressionExpirySweep(deps) {
|
|
86
|
+
const expired = await deps.listExpiredSuppressions();
|
|
87
|
+
const lifted = [];
|
|
88
|
+
for (const finding of expired) {
|
|
89
|
+
await deps.unsuppressFinding(finding.id);
|
|
90
|
+
await deps.writeAudit({
|
|
91
|
+
findingId: finding.id,
|
|
92
|
+
organizationId: finding.organizationId,
|
|
93
|
+
action: 'unsuppressed',
|
|
94
|
+
payload: { reason: 'suppression_expired' },
|
|
95
|
+
});
|
|
96
|
+
lifted.push(finding.id);
|
|
97
|
+
}
|
|
98
|
+
return lifted;
|
|
99
|
+
}
|
|
100
|
+
export function buildDefaultSuppressionExpirySweepDeps() {
|
|
101
|
+
return {
|
|
102
|
+
listExpiredSuppressions: async () => {
|
|
103
|
+
const res = await callApi('daemon_list_expired_security_suppressions', {});
|
|
104
|
+
return res.items ?? [];
|
|
105
|
+
},
|
|
106
|
+
unsuppressFinding: async (findingId) => {
|
|
107
|
+
await callApi('daemon_unsuppress_security_finding', { findingId });
|
|
108
|
+
},
|
|
109
|
+
writeAudit: async (input) => {
|
|
110
|
+
await callApi('daemon_write_security_finding_audit', input);
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=security-rescan-resolution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-rescan-resolution.js","sourceRoot":"","sources":["../src/security-rescan-resolution.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security scan engine.
|
|
3
|
+
*
|
|
4
|
+
* Polls security_scan_configs for due scans (cron-due or manual_run_requested_at
|
|
5
|
+
* set), dispatches pluggable Scanner implementations per IOC class, writes
|
|
6
|
+
* one security_scan_runs row plus N security_findings rows per execution,
|
|
7
|
+
* and (downstream) hands findings to security-auto-inject for severity-gated
|
|
8
|
+
* injection materialization.
|
|
9
|
+
*
|
|
10
|
+
* Activation: gated by shouldRunLoop('TELORA_SECURITY_SCAN_LOOP') in
|
|
11
|
+
* unified-shell.ts. Opt-out semantics match the other daemon loop ticks
|
|
12
|
+
* (unset/anything-but-'0' = enabled, '0' = disabled). See
|
|
13
|
+
* docs/runbook-loop-activation.md.
|
|
14
|
+
*
|
|
15
|
+
* Pattern reference: verification-engine.ts (pluggable strategies + Deps).
|
|
16
|
+
*
|
|
17
|
+
* @module security-scan-engine
|
|
18
|
+
*/
|
|
19
|
+
import type { DaemonConfig } from './types.js';
|
|
20
|
+
import { type AutoInjectDeps } from './security-auto-inject.js';
|
|
21
|
+
import { type ResolutionDeps } from './security-rescan-resolution.js';
|
|
22
|
+
export type Severity = 'low' | 'medium' | 'high' | 'critical';
|
|
23
|
+
/** Configuration row driving an individual product's scan cadence. */
|
|
24
|
+
export interface ScanConfig {
|
|
25
|
+
id: string;
|
|
26
|
+
organizationId: string;
|
|
27
|
+
productId: string;
|
|
28
|
+
scheduleCron: string;
|
|
29
|
+
enabledIocClasses: string[];
|
|
30
|
+
autoInjectSeverityThreshold: Severity;
|
|
31
|
+
enabled: boolean;
|
|
32
|
+
manualRunRequestedAt: string | null;
|
|
33
|
+
lastRunAt: string | null;
|
|
34
|
+
}
|
|
35
|
+
/** Per-scan context passed to each Scanner. */
|
|
36
|
+
export interface ScanContext {
|
|
37
|
+
config: ScanConfig;
|
|
38
|
+
repoPath: string;
|
|
39
|
+
}
|
|
40
|
+
/** Single finding draft emitted by a Scanner. Stored in security_findings. */
|
|
41
|
+
export interface FindingDraft {
|
|
42
|
+
iocClass: string;
|
|
43
|
+
severity: Severity;
|
|
44
|
+
identifier: string;
|
|
45
|
+
payload: Record<string, unknown>;
|
|
46
|
+
}
|
|
47
|
+
/** Per-scanner output for a single scan run. */
|
|
48
|
+
export interface ScanResult {
|
|
49
|
+
findings: FindingDraft[];
|
|
50
|
+
/** Coverage breadcrumb (e.g. packages_audited, files_scanned) + any warnings. */
|
|
51
|
+
coverage: Record<string, unknown>;
|
|
52
|
+
}
|
|
53
|
+
/** Pluggable Scanner contract -- one per IOC class. */
|
|
54
|
+
export interface Scanner {
|
|
55
|
+
/** IOC class slug, matched against ScanConfig.enabledIocClasses. */
|
|
56
|
+
iocClass: string;
|
|
57
|
+
scan(ctx: ScanContext): Promise<ScanResult>;
|
|
58
|
+
}
|
|
59
|
+
export declare function registerScanner(scanner: Scanner): void;
|
|
60
|
+
export declare function getRegisteredScanners(): Scanner[];
|
|
61
|
+
export interface SecurityScanDeps {
|
|
62
|
+
getDueScanConfigs: () => Promise<ScanConfig[]>;
|
|
63
|
+
startRun: (configId: string, trigger: 'schedule' | 'manual') => Promise<string>;
|
|
64
|
+
finishRun: (runId: string, update: {
|
|
65
|
+
status: 'succeeded' | 'failed' | 'partial';
|
|
66
|
+
coverageSummary: Record<string, unknown>;
|
|
67
|
+
findingsCountBySeverity: Record<Severity, number>;
|
|
68
|
+
durationMs: number;
|
|
69
|
+
}) => Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Persist a finding and return its DB-assigned id so downstream
|
|
72
|
+
* hooks (auto-injection, resolution) can reference it.
|
|
73
|
+
*/
|
|
74
|
+
writeFinding: (runId: string, productId: string, organizationId: string, finding: FindingDraft) => Promise<{
|
|
75
|
+
findingId: string;
|
|
76
|
+
}>;
|
|
77
|
+
clearManualRunRequest: (configId: string) => Promise<void>;
|
|
78
|
+
resolveCwd: (productId: string) => string;
|
|
79
|
+
/**
|
|
80
|
+
* Flush the OSV + GHSA feed caches. Invoked at the start of every
|
|
81
|
+
* manual-triggered scan so a user-clicked "Refresh feeds" pulls fresh
|
|
82
|
+
* upstream advisory data rather than the cached 15-minute window.
|
|
83
|
+
*/
|
|
84
|
+
clearFeedCaches: () => void;
|
|
85
|
+
scanners: Scanner[];
|
|
86
|
+
/**
|
|
87
|
+
* Optional severity-gated auto-injection hook. When set, each newly
|
|
88
|
+
* written finding is passed to processNewFinding so the daemon can
|
|
89
|
+
* materialize a remediation injection + delivery for it.
|
|
90
|
+
*/
|
|
91
|
+
autoInjectDeps?: AutoInjectDeps;
|
|
92
|
+
/**
|
|
93
|
+
* Optional re-scan resolution hook. When set, after every scan run
|
|
94
|
+
* finishes, the engine asks the resolution module to flip previously
|
|
95
|
+
* open findings whose identifiers did not re-appear to 'resolved'.
|
|
96
|
+
*/
|
|
97
|
+
resolutionDeps?: ResolutionDeps;
|
|
98
|
+
}
|
|
99
|
+
export declare function runScanForConfig(config: ScanConfig, trigger: 'schedule' | 'manual', deps: SecurityScanDeps): Promise<void>;
|
|
100
|
+
export declare function runSecurityScanTick(deps: SecurityScanDeps): Promise<void>;
|
|
101
|
+
export declare function buildDefaultSecurityScanDeps(config: DaemonConfig): SecurityScanDeps;
|
|
102
|
+
//# sourceMappingURL=security-scan-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-scan-engine.d.ts","sourceRoot":"","sources":["../src/security-scan-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAGL,KAAK,cAAc,EAGpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAGL,KAAK,cAAc,EAEpB,MAAM,iCAAiC,CAAC;AAQzC,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;AAE9D,sEAAsE;AACtE,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,2BAA2B,EAAE,QAAQ,CAAC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,+CAA+C;AAC/C,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,gDAAgD;AAChD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,iFAAiF;IACjF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,uDAAuD;AACvD,MAAM,WAAW,OAAO;IACtB,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC7C;AAQD,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEtD;AAED,wBAAgB,qBAAqB,IAAI,OAAO,EAAE,CAEjD;AAMD,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,EAAE,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAC/C,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,QAAQ,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAChF,SAAS,EAAE,CACT,KAAK,EAAE,MAAM,EACb,MAAM,EAAE;QACN,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;QAC3C,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACzC,uBAAuB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAClD,UAAU,EAAE,MAAM,CAAC;KACpB,KACE,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB;;;OAGG;IACH,YAAY,EAAE,CACZ,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE,YAAY,KAClB,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpC,qBAAqB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1C;;;;OAIG;IACH,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB;;;;OAIG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;;;OAIG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,UAAU,GAAG,QAAQ,EAC9B,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,IAAI,CAAC,CAsHf;AAMD,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAa/E;AAMD,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,YAAY,GAAG,gBAAgB,CA8CnF"}
|