@lmzhen/dsh-evolution-threat 0.3.61 → 0.3.63
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/README.md +9 -0
- package/lib/index.js +11 -7
- package/lib/types/index.d.ts +10 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -27,6 +27,15 @@ Independent of request-prefix construction. This package does not alter the asse
|
|
|
27
27
|
default. The whole text is always scanned in overlapping windows; this value
|
|
28
28
|
is not a total cap.
|
|
29
29
|
|
|
30
|
+
- `threatExemptLabels` (default `[]`): pattern labels the deployment knows to
|
|
31
|
+
be benign. P2-4 (v14) closed the store-vs-guard asymmetry for the STORE
|
|
32
|
+
gates (`SkillLibrary`/`MemoryStore` options) — but the exemption surface is
|
|
33
|
+
per config site: this guard row, the tool-skill-manage row, the
|
|
34
|
+
evolution-commands row (its own SkillLibrary for the command write paths),
|
|
35
|
+
and the memory store options each carry their OWN list and must be set
|
|
36
|
+
separately. A label exempted only on the store side still blocks here.
|
|
37
|
+
(v17 audit: the evolution-commands site was missing from this enumeration.)
|
|
38
|
+
|
|
30
39
|
## Known Limitations and Deferred Work
|
|
31
40
|
|
|
32
41
|
|
package/lib/index.js
CHANGED
|
@@ -9,25 +9,28 @@ const name = "evolution-threat";
|
|
|
9
9
|
const inject = ["tools"];
|
|
10
10
|
const Config = z.object({
|
|
11
11
|
enabled: z.boolean().default(true),
|
|
12
|
-
maxScanChars: z.number().min(PATTERN_OVERLAP + 1).default(65536)
|
|
12
|
+
maxScanChars: z.number().min(PATTERN_OVERLAP + 1).default(65536),
|
|
13
|
+
threatExemptLabels: z.array(z.string()).default([])
|
|
13
14
|
});
|
|
14
15
|
function asRecord(value) {
|
|
15
16
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
16
17
|
}
|
|
17
18
|
/** Scan one tool invocation for threat-shaped payload text. Exported so the
|
|
18
|
-
* guard contract is testable directly (0.3.17).
|
|
19
|
-
|
|
19
|
+
* guard contract is testable directly (0.3.17). `options.excludeLabels` carries
|
|
20
|
+
* the deployment's benign-label allowlist so this channel agrees with the
|
|
21
|
+
* SkillLibrary/MemoryStore write gates (P2-4, v14). */
|
|
22
|
+
function scanToolArgs(toolName, args, maxScanChars, options = {}) {
|
|
20
23
|
if (!EVOLUTION_WRITE_TOOLS.includes(toolName)) return null;
|
|
21
24
|
const record = asRecord(args);
|
|
22
25
|
if (toolName === "memory") {
|
|
23
26
|
for (const text of [record.facts, record.content]) if (typeof text === "string") {
|
|
24
|
-
const hit = scanMemoryThreats(text, maxScanChars);
|
|
27
|
+
const hit = scanMemoryThreats(text, maxScanChars, options);
|
|
25
28
|
if (hit) return hit;
|
|
26
29
|
}
|
|
27
30
|
if (Array.isArray(record.operations)) for (const op of record.operations) {
|
|
28
31
|
const inner = asRecord(op);
|
|
29
32
|
for (const text of [inner.facts, inner.content]) if (typeof text === "string") {
|
|
30
|
-
const hit = scanMemoryThreats(text, maxScanChars);
|
|
33
|
+
const hit = scanMemoryThreats(text, maxScanChars, options);
|
|
31
34
|
if (hit) return hit;
|
|
32
35
|
}
|
|
33
36
|
}
|
|
@@ -38,7 +41,7 @@ function scanToolArgs(toolName, args, maxScanChars) {
|
|
|
38
41
|
record.file_content,
|
|
39
42
|
record.new_string
|
|
40
43
|
]) if (typeof text === "string") {
|
|
41
|
-
const hit = scanContentThreats(text, maxScanChars);
|
|
44
|
+
const hit = scanContentThreats(text, maxScanChars, options);
|
|
42
45
|
if (hit) return hit;
|
|
43
46
|
}
|
|
44
47
|
return null;
|
|
@@ -55,10 +58,11 @@ function apply(ctx, rawConfig = {}) {
|
|
|
55
58
|
if (!(rawConfig.enabled ?? true)) return;
|
|
56
59
|
const maxScanChars = resolveMaxScanChars(rawConfig);
|
|
57
60
|
if (maxScanChars !== (rawConfig.maxScanChars ?? 65536)) ctx.logger.warn(`evolution-threat: maxScanChars=${String(rawConfig.maxScanChars)} is invalid; falling back to the default 65_536`);
|
|
61
|
+
const scanOptions = { excludeLabels: rawConfig.threatExemptLabels ?? [] };
|
|
58
62
|
ctx.inject(["tools"], (toolCtx) => {
|
|
59
63
|
const tools = toolCtx.get("tools");
|
|
60
64
|
toolCtx.effect(() => tools.guard((exec) => {
|
|
61
|
-
return scanToolArgs(exec.name, exec.arguments, maxScanChars) ?? void 0;
|
|
65
|
+
return scanToolArgs(exec.name, exec.arguments, maxScanChars, scanOptions) ?? void 0;
|
|
62
66
|
}), "evolution-threat.tools-guard");
|
|
63
67
|
});
|
|
64
68
|
}
|
package/lib/types/index.d.ts
CHANGED
|
@@ -4,17 +4,25 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { Context } from '@deepseek-ai/cordis';
|
|
6
6
|
import z from '@deepseek-ai/schemastery';
|
|
7
|
+
import type { ScanOptions } from '@lmzhen/dsh-evolution-core';
|
|
7
8
|
export declare const name = "evolution-threat";
|
|
8
9
|
export declare const inject: string[];
|
|
9
10
|
export interface Config {
|
|
10
11
|
enabled?: boolean;
|
|
11
12
|
/** Maximum normalized characters scanned per write field. */
|
|
12
13
|
maxScanChars?: number;
|
|
14
|
+
/** Pattern labels the deployment knows to be benign. P2-4 (v14): without
|
|
15
|
+
* this the guard blocked payloads the SkillLibrary/MemoryStore gates already
|
|
16
|
+
* exempted, while its message advertised an exemption that did not exist on
|
|
17
|
+
* this channel. Same `excludeLabels` contract as the store gates. */
|
|
18
|
+
threatExemptLabels?: string[];
|
|
13
19
|
}
|
|
14
20
|
export declare const Config: z<Config>;
|
|
15
21
|
/** Scan one tool invocation for threat-shaped payload text. Exported so the
|
|
16
|
-
* guard contract is testable directly (0.3.17).
|
|
17
|
-
|
|
22
|
+
* guard contract is testable directly (0.3.17). `options.excludeLabels` carries
|
|
23
|
+
* the deployment's benign-label allowlist so this channel agrees with the
|
|
24
|
+
* SkillLibrary/MemoryStore write gates (P2-4, v14). */
|
|
25
|
+
export declare function scanToolArgs(toolName: string, args: unknown, maxScanChars: number, options?: ScanOptions): string | null;
|
|
18
26
|
/** Resolve the effective `maxScanChars`, clamping invalid values to the
|
|
19
27
|
* default (G3.1: 0/negative/NaN/±Infinity → 65_536; V6-05: a value below
|
|
20
28
|
* PATTERN_OVERLAP + 1 is out of the coverage-guarantee domain → default).
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-threat",
|
|
3
3
|
"description": "Write-time threat guard for evolution tools (community build)",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.63",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"license": "MIT",
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@deepseek-ai/schemastery": "^3.18.1",
|
|
34
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
34
|
+
"@lmzhen/dsh-evolution-core": "^0.3.63"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
@@ -42,6 +42,6 @@
|
|
|
42
42
|
"@deepseek-ai/dsh-agent-loop-testkit": "^0.1.1-rc.2",
|
|
43
43
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
44
44
|
"@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
|
|
45
|
-
"@lmzhen/dsh-evolution-core": "^0.3.
|
|
45
|
+
"@lmzhen/dsh-evolution-core": "^0.3.63"
|
|
46
46
|
}
|
|
47
47
|
}
|