@gendigital/sage-opencode 0.10.0 → 0.12.0

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.
Files changed (48) hide show
  1. package/README.md +6 -6
  2. package/dist/bundled-dirs.d.ts +1 -1
  3. package/dist/bundled-dirs.d.ts.map +1 -1
  4. package/dist/bundled-dirs.js +1 -1
  5. package/dist/bundled-dirs.js.map +1 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +291 -71
  8. package/dist/index.js.map +1 -1
  9. package/dist/mcp-server.cjs +31882 -0
  10. package/dist/mcp-server.cjs.map +7 -0
  11. package/dist/plugin-discovery.d.ts +1 -0
  12. package/dist/plugin-discovery.d.ts.map +1 -1
  13. package/dist/plugin-discovery.js +27 -1
  14. package/dist/plugin-discovery.js.map +1 -1
  15. package/dist/startup-scan.d.ts +11 -3
  16. package/dist/startup-scan.d.ts.map +1 -1
  17. package/dist/startup-scan.js +60 -21
  18. package/dist/startup-scan.js.map +1 -1
  19. package/dist/tool-handler.d.ts +3 -2
  20. package/dist/tool-handler.d.ts.map +1 -1
  21. package/dist/tool-handler.js +22 -5
  22. package/dist/tool-handler.js.map +1 -1
  23. package/package.json +5 -3
  24. package/resources/threats/agent-layer.yaml +186 -0
  25. package/resources/threats/commands.yaml +24 -53
  26. package/resources/threats/credentials.yaml +12 -20
  27. package/resources/threats/dummy.yaml +44 -50
  28. package/resources/threats/files.yaml +34 -53
  29. package/resources/threats/mac-commands.yaml +20 -47
  30. package/resources/threats/mac-credentials.yaml +4 -12
  31. package/resources/threats/mac-files.yaml +5 -15
  32. package/resources/threats/mac-obfuscation.yaml +6 -13
  33. package/resources/threats/mac-persistence.yaml +11 -20
  34. package/resources/threats/mac-supply-chain.yaml +5 -8
  35. package/resources/threats/mitre.yaml +105 -167
  36. package/resources/threats/obfuscation.yaml +7 -15
  37. package/resources/threats/persistence.yaml +10 -17
  38. package/resources/threats/prompt-injection.yaml +92 -43
  39. package/resources/threats/self-defense.yaml +8 -12
  40. package/resources/threats/supply_chain.yaml +1 -2
  41. package/resources/threats/urls.yaml +9 -14
  42. package/resources/threats/win-commands.yaml +46 -106
  43. package/resources/threats/win-credentials.yaml +14 -24
  44. package/resources/threats/win-files.yaml +10 -20
  45. package/resources/threats/win-obfuscation.yaml +21 -37
  46. package/resources/threats/win-persistence.yaml +8 -16
  47. package/resources/threats/win-supply-chain.yaml +2 -3
  48. /package/resources/{allowlists → trusted-domains}/trusted-installer-domains.yaml +0 -0
@@ -7,6 +7,7 @@ import type { Branding, Logger, PluginInfo } from "@gendigital/sage-core";
7
7
  * Discover OpenCode plugins from all sources:
8
8
  * 1. NPM packages from config files
9
9
  * 2. Local plugin files (global + project)
10
+ * 3. Loose skills (global + project) as pseudo-plugins
10
11
  */
11
12
  export declare function discoverOpenCodePlugins(logger: Logger, projectDir?: string, branding?: Branding): Promise<PluginInfo[]>;
12
13
  //# sourceMappingURL=plugin-discovery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-discovery.d.ts","sourceRoot":"","sources":["../src/plugin-discovery.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAc1E;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC5C,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,GAAE,QAA0B,GAClC,OAAO,CAAC,UAAU,EAAE,CAAC,CAuBvB"}
1
+ {"version":3,"file":"plugin-discovery.d.ts","sourceRoot":"","sources":["../src/plugin-discovery.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAa,MAAM,uBAAuB,CAAC;AA4CrF;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC5C,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,GAAE,QAA0B,GAClC,OAAO,CAAC,UAAU,EAAE,CAAC,CA6BvB"}
@@ -5,7 +5,7 @@
5
5
  import { readdir, stat } from "node:fs/promises";
6
6
  import { homedir } from "node:os";
7
7
  import { basename, join } from "node:path";
8
- import { defaultBranding, getFileContent } from "@gendigital/sage-core";
8
+ import { defaultBranding, discoverLooseSkillsAcrossRoots, getFileContent, getHomeDir, } from "@gendigital/sage-core";
9
9
  /** Resolve XDG base directories with fallbacks to homedir defaults */
10
10
  function getConfigHome() {
11
11
  return process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config");
@@ -14,10 +14,31 @@ function getCacheHome() {
14
14
  return process.env.XDG_CACHE_HOME ?? join(homedir(), ".cache");
15
15
  }
16
16
  const PROJECT_CONFIG_NAME = "opencode.json";
17
+ /**
18
+ * Loose-skill roots OpenCode loads, at both scopes. Global (personal) skills
19
+ * live under the user profile; project skills live inside the project dir.
20
+ * OpenCode reads its own `opencode` family plus Claude- and agent-compatible
21
+ * families; each is scanned so a malicious skill in any load path is covered.
22
+ * The global `opencode` root is XDG-based (`~/.config/opencode/skills`), not
23
+ * `~/.opencode/skills`. The `scope` key segment keeps a personal and project
24
+ * skill of the same family from colliding in the scan cache.
25
+ */
26
+ function resolveSkillRoots(projectDir) {
27
+ const roots = [
28
+ { dir: join(getConfigHome(), "opencode", "skills"), tag: "opencode", scope: "personal" },
29
+ { dir: join(getHomeDir(), ".claude", "skills"), tag: "claude", scope: "personal" },
30
+ { dir: join(getHomeDir(), ".agents", "skills"), tag: "agents", scope: "personal" },
31
+ ];
32
+ if (projectDir) {
33
+ roots.push({ dir: join(projectDir, ".opencode", "skills"), tag: "opencode", scope: "project" }, { dir: join(projectDir, ".claude", "skills"), tag: "claude", scope: "project" }, { dir: join(projectDir, ".agents", "skills"), tag: "agents", scope: "project" });
34
+ }
35
+ return roots;
36
+ }
17
37
  /**
18
38
  * Discover OpenCode plugins from all sources:
19
39
  * 1. NPM packages from config files
20
40
  * 2. Local plugin files (global + project)
41
+ * 3. Loose skills (global + project) as pseudo-plugins
21
42
  */
22
43
  export async function discoverOpenCodePlugins(logger, projectDir, branding = defaultBranding) {
23
44
  logger.debug(`${branding.name} plugin discovery: scanning OpenCode plugins`);
@@ -35,6 +56,11 @@ export async function discoverOpenCodePlugins(logger, projectDir, branding = def
35
56
  const projectPlugins = await discoverLocalPlugins(projectPluginsDir, "project", logger);
36
57
  plugins.push(...projectPlugins);
37
58
  }
59
+ // 4. Discover loose skills as pseudo-plugins (deduped by resolved path,
60
+ // fails open per root) so the scan pipeline covers skills installed outside
61
+ // any plugin.
62
+ const skills = await discoverLooseSkillsAcrossRoots(resolveSkillRoots(projectDir));
63
+ plugins.push(...skills);
38
64
  logger.debug(`${branding.name} plugin discovery: found ${plugins.length} plugin(s)`);
39
65
  return plugins;
40
66
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-discovery.js","sourceRoot":"","sources":["../src/plugin-discovery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin-discovery.js","sourceRoot":"","sources":["../src/plugin-discovery.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,15 @@
1
1
  /**
2
2
  * Startup and session scan handlers for OpenCode.
3
- * Thin wrapper over core's createScanHandler.
3
+ * Runs core's session scan and hands back the structured findings so the
4
+ * connector can build its own TUI popup (rather than a formatted string).
4
5
  */
5
- import { type Branding, type Logger } from "@gendigital/sage-core";
6
- export declare function createSessionScanHandler(logger: Logger, projectDir?: string, onResult?: (msg: string) => void, branding?: Branding): () => Promise<void>;
6
+ import { type Branding, type Logger, type PluginScanResult } from "@gendigital/sage-core";
7
+ export declare function resolveSkillUploadWorkerPath(): string | undefined;
8
+ /**
9
+ * Build a session-scan runner. Discovers OpenCode plugins/skills (minus Sage
10
+ * itself), runs the core session scan — which populates the verdict cache and
11
+ * spawns the skill-upload worker — and passes the structured results to
12
+ * `onResults`. Fails open: any error is logged and the handler resolves.
13
+ */
14
+ export declare function createSessionScanHandler(logger: Logger, projectDir?: string, onResults?: (results: PluginScanResult[]) => void, branding?: Branding, onNotices?: (noticeIds: string[]) => void): () => Promise<void>;
7
15
  //# sourceMappingURL=startup-scan.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"startup-scan.d.ts","sourceRoot":"","sources":["../src/startup-scan.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,KAAK,QAAQ,EAGb,KAAK,MAAM,EACX,MAAM,uBAAuB,CAAC;AAmB/B,wBAAgB,wBAAwB,CACvC,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAChC,QAAQ,GAAE,QAA0B,GAClC,MAAM,OAAO,CAAC,IAAI,CAAC,CAiBrB"}
1
+ {"version":3,"file":"startup-scan.d.ts","sourceRoot":"","sources":["../src/startup-scan.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACN,KAAK,QAAQ,EAEb,KAAK,MAAM,EACX,KAAK,gBAAgB,EAErB,MAAM,uBAAuB,CAAC;AAqB/B,wBAAgB,4BAA4B,IAAI,MAAM,GAAG,SAAS,CAOjE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACvC,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,EAAE,KAAK,IAAI,EACjD,QAAQ,GAAE,QAA0B,EACpC,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,IAAI,GACvC,MAAM,OAAO,CAAC,IAAI,CAAC,CAuCrB"}
@@ -1,16 +1,18 @@
1
1
  /**
2
2
  * Startup and session scan handlers for OpenCode.
3
- * Thin wrapper over core's createScanHandler.
3
+ * Runs core's session scan and hands back the structured findings so the
4
+ * connector can build its own TUI popup (rather than a formatted string).
4
5
  */
5
6
  import { createRequire } from "node:module";
6
- import { createScanHandler as coreScanHandler, defaultBranding, } from "@gendigital/sage-core";
7
+ import { defaultBranding, runSessionStart, } from "@gendigital/sage-core";
7
8
  import { getBundledDataDirs, getSageVersion } from "./bundled-dirs.js";
8
9
  import { discoverOpenCodePlugins } from "./plugin-discovery.js";
10
+ const SELF_PREFIX = "@gendigital/sage-opencode@";
9
11
  /**
10
- * OpenCode is published as an unbundled ESM plugin (tsc only). The model
11
- * download worker therefore lives in the `@gendigital/sage-core` package
12
- * as `dist/model-download-worker.js`. Resolve via `require.resolve` so we
13
- * pick it up wherever pnpm/node placed it.
12
+ * OpenCode is published as an unbundled ESM plugin (tsc only). The detached
13
+ * workers therefore live in the `@gendigital/sage-core` package under
14
+ * `dist/`. Resolve via `require.resolve` so we pick them up wherever
15
+ * pnpm/node placed them.
14
16
  */
15
17
  function resolveModelDownloadWorkerPath() {
16
18
  try {
@@ -21,21 +23,58 @@ function resolveModelDownloadWorkerPath() {
21
23
  return undefined;
22
24
  }
23
25
  }
24
- export function createSessionScanHandler(logger, projectDir, onResult, branding = defaultBranding) {
25
- const { threatsDir, allowlistsDir } = getBundledDataDirs();
26
+ export function resolveSkillUploadWorkerPath() {
27
+ try {
28
+ const req = createRequire(import.meta.url);
29
+ return req.resolve("@gendigital/sage-core/dist/skill-upload-worker.js");
30
+ }
31
+ catch {
32
+ return undefined;
33
+ }
34
+ }
35
+ /**
36
+ * Build a session-scan runner. Discovers OpenCode plugins/skills (minus Sage
37
+ * itself), runs the core session scan — which populates the verdict cache and
38
+ * spawns the skill-upload worker — and passes the structured results to
39
+ * `onResults`. Fails open: any error is logged and the handler resolves.
40
+ */
41
+ export function createSessionScanHandler(logger, projectDir, onResults, branding = defaultBranding, onNotices) {
42
+ const { threatsDir, trustedDomainsDir } = getBundledDataDirs();
26
43
  const version = getSageVersion();
27
- return coreScanHandler({
28
- logger,
29
- context: "session",
30
- discoverPlugins: () => discoverOpenCodePlugins(logger, projectDir, branding),
31
- selfPrefix: "@gendigital/sage-opencode@",
32
- threatsDir,
33
- allowlistsDir,
34
- version,
35
- agentRuntime: "opencode",
36
- branding,
37
- onResult,
38
- modelDownloadWorkerPath: resolveModelDownloadWorkerPath(),
39
- });
44
+ return async () => {
45
+ try {
46
+ const discovered = await discoverOpenCodePlugins(logger, projectDir, branding);
47
+ const plugins = discovered.filter((p) => !p.key.startsWith(SELF_PREFIX));
48
+ const { scanResults, notices } = await runSessionStart({
49
+ plugins,
50
+ threatsDir,
51
+ trustedDomainsDir,
52
+ version,
53
+ logger,
54
+ agentRuntime: "opencode",
55
+ // No agentRuntimeVersion: the OpenCode SDK exposes no host version synchronously.
56
+ modelDownloadWorkerPath: resolveModelDownloadWorkerPath(),
57
+ skillUploadWorkerPath: resolveSkillUploadWorkerPath(),
58
+ });
59
+ const findingsCount = scanResults.reduce((n, r) => n + r.findings.length, 0);
60
+ logger.debug(`${branding.name} session scan complete`, {
61
+ agentRuntime: "opencode",
62
+ pluginsCount: plugins.length,
63
+ resultsWithFindings: scanResults.length,
64
+ findingsCount,
65
+ });
66
+ // Surface the one-time notice BEFORE the finding toasts. The toast queue
67
+ // is FIFO, so enqueuing notices first shows the "new feature" info ahead
68
+ // of any malware findings.
69
+ if (notices && notices.length > 0)
70
+ onNotices?.(notices);
71
+ onResults?.(scanResults);
72
+ }
73
+ catch (error) {
74
+ logger.error(`${branding.name} session scan failed (fail-open)`, {
75
+ error: String(error),
76
+ });
77
+ }
78
+ };
40
79
  }
41
80
  //# sourceMappingURL=startup-scan.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"startup-scan.js","sourceRoot":"","sources":["../src/startup-scan.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAEN,iBAAiB,IAAI,eAAe,EACpC,eAAe,GAEf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE;;;;;GAKG;AACH,SAAS,8BAA8B;IACtC,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3C,OAAO,GAAG,CAAC,OAAO,CAAC,qDAAqD,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,wBAAwB,CACvC,MAAc,EACd,UAAmB,EACnB,QAAgC,EAChC,WAAqB,eAAe;IAEpC,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAC3D,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;IAEjC,OAAO,eAAe,CAAC;QACtB,MAAM;QACN,OAAO,EAAE,SAAS;QAClB,eAAe,EAAE,GAAG,EAAE,CAAC,uBAAuB,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC;QAC5E,UAAU,EAAE,4BAA4B;QACxC,UAAU;QACV,aAAa;QACb,OAAO;QACP,YAAY,EAAE,UAAU;QACxB,QAAQ;QACR,QAAQ;QACR,uBAAuB,EAAE,8BAA8B,EAAE;KACzD,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"startup-scan.js","sourceRoot":"","sources":["../src/startup-scan.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAEN,eAAe,EAGf,eAAe,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAEhE,MAAM,WAAW,GAAG,4BAA4B,CAAC;AAEjD;;;;;GAKG;AACH,SAAS,8BAA8B;IACtC,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3C,OAAO,GAAG,CAAC,OAAO,CAAC,qDAAqD,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,4BAA4B;IAC3C,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3C,OAAO,GAAG,CAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC;IACzE,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACvC,MAAc,EACd,UAAmB,EACnB,SAAiD,EACjD,WAAqB,eAAe,EACpC,SAAyC;IAEzC,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAC/D,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;IAEjC,OAAO,KAAK,IAAI,EAAE;QACjB,IAAI,CAAC;YACJ,MAAM,UAAU,GAAG,MAAM,uBAAuB,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC/E,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;YAEzE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,MAAM,eAAe,CAAC;gBACtD,OAAO;gBACP,UAAU;gBACV,iBAAiB;gBACjB,OAAO;gBACP,MAAM;gBACN,YAAY,EAAE,UAAU;gBACxB,kFAAkF;gBAClF,uBAAuB,EAAE,8BAA8B,EAAE;gBACzD,qBAAqB,EAAE,4BAA4B,EAAE;aACrD,CAAC,CAAC;YAEH,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC7E,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,IAAI,wBAAwB,EAAE;gBACtD,YAAY,EAAE,UAAU;gBACxB,YAAY,EAAE,OAAO,CAAC,MAAM;gBAC5B,mBAAmB,EAAE,WAAW,CAAC,MAAM;gBACvC,aAAa;aACb,CAAC,CAAC;YACH,yEAAyE;YACzE,yEAAyE;YACzE,2BAA2B;YAC3B,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;gBAAE,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC;YACxD,SAAS,EAAE,CAAC,WAAW,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,IAAI,kCAAkC,EAAE;gBAChE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC;aACpB,CAAC,CAAC;QACJ,CAAC;IACF,CAAC,CAAC;AACH,CAAC"}
@@ -1,8 +1,9 @@
1
- import { type ApprovalStore, type Branding, type Logger } from "@gendigital/sage-core";
1
+ import { type ApprovalStore, type Branding, type CanonicalToolType, type Logger } from "@gendigital/sage-core";
2
+ export declare const OPENCODE_TOOL_MAP: Record<string, CanonicalToolType>;
2
3
  export interface ToolHandlerOptions {
3
4
  showToast?: (msg: string, variant: "info" | "success" | "warning" | "error") => void;
4
5
  }
5
- export declare function createToolHandlers(logger: Logger, approvalStore: ApprovalStore, threatsDir: string, allowlistsDir: string, options?: ToolHandlerOptions, branding?: Branding): {
6
+ export declare function createToolHandlers(logger: Logger, approvalStore: ApprovalStore, threatsDir: string, trustedDomainsDir: string, options?: ToolHandlerOptions, branding?: Branding): {
6
7
  "tool.execute.before": (input: {
7
8
  tool: string;
8
9
  sessionID: string;
@@ -1 +1 @@
1
- {"version":3,"file":"tool-handler.d.ts","sourceRoot":"","sources":["../src/tool-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,aAAa,EAClB,KAAK,QAAQ,EAMb,KAAK,MAAM,EAEX,MAAM,uBAAuB,CAAC;AA+C/B,MAAM,WAAW,kBAAkB;IAClC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,KAAK,IAAI,CAAC;CACrF;AAED,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,aAAa,EAC5B,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,kBAAkB,EAC5B,QAAQ,GAAE,QAA0B;mCAG5B;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,UAClD;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,KACvC,OAAO,CAAC,IAAI,CAAC;EAiHhB"}
1
+ {"version":3,"file":"tool-handler.d.ts","sourceRoot":"","sources":["../src/tool-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,iBAAiB,EAOtB,KAAK,MAAM,EAEX,MAAM,uBAAuB,CAAC;AAE/B,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAc/D,CAAC;AA+BF,MAAM,WAAW,kBAAkB;IAClC,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,KAAK,IAAI,CAAC;CACrF;AAED,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,aAAa,EAC5B,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,MAAM,EACzB,OAAO,CAAC,EAAE,kBAAkB,EAC5B,QAAQ,GAAE,QAA0B;mCAG5B;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,UAClD;QAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,KACvC,OAAO,CAAC,IAAI,CAAC;EAyIhB"}
@@ -1,5 +1,5 @@
1
- import { canonicalizeToolName, defaultBranding, formatDenyMessage, guardToolCall, summarizeArtifacts, } from "@gendigital/sage-core";
2
- const OPENCODE_TOOL_MAP = {
1
+ import { canonicalizeToolName, captureEnabled, captureHookInput, defaultBranding, formatDenyMessage, guardToolCall, summarizeArtifacts, } from "@gendigital/sage-core";
2
+ export const OPENCODE_TOOL_MAP = {
3
3
  bash: "Bash",
4
4
  webfetch: "WebFetch",
5
5
  write: "Write",
@@ -37,7 +37,7 @@ function normalizeToolInput(toolName, args) {
37
37
  return args;
38
38
  }
39
39
  }
40
- export function createToolHandlers(logger, approvalStore, threatsDir, allowlistsDir, options, branding = defaultBranding) {
40
+ export function createToolHandlers(logger, approvalStore, threatsDir, trustedDomainsDir, options, branding = defaultBranding) {
41
41
  const beforeToolUse = async (input, output) => {
42
42
  const completeHook = (result, data = {}) => {
43
43
  logger.debug("OpenCode tool hook completed", {
@@ -59,6 +59,17 @@ export function createToolHandlers(logger, approvalStore, threatsDir, allowlists
59
59
  });
60
60
  try {
61
61
  const args = output.args ?? {};
62
+ // E2E payload-drift capture (drift loop). OpenCode is an in-process
63
+ // ESM plugin (not MCP, not a CJS hook), so the "raw wire" payload is the
64
+ // in-proc tool-call shape OpenCode hands us. Namespaced opencode-* so it
65
+ // can't collide with other agents sharing SAGE_E2E_CAPTURE_DIR. Inert in
66
+ // production (env unset); fail-open inside captureHookInput.
67
+ if (captureEnabled()) {
68
+ await captureHookInput("PreToolUse", { tool: input.tool, sessionID: input.sessionID, callID: input.callID, args }, {
69
+ toolName: canonicalizeToolName(OPENCODE_TOOL_MAP, input.tool),
70
+ toolInput: normalizeToolInput(input.tool, args),
71
+ }, { filePrefix: "opencode-" });
72
+ }
62
73
  const artifacts = extractFromOpenCodeTool(input.tool, args);
63
74
  if (!artifacts || artifacts.length === 0) {
64
75
  completeHook("skipped", { skippedReason: "no_artifacts" });
@@ -74,7 +85,7 @@ export function createToolHandlers(logger, approvalStore, threatsDir, allowlists
74
85
  artifacts,
75
86
  }, {
76
87
  threatsDir,
77
- allowlistsDir,
88
+ trustedDomainsDir,
78
89
  logger,
79
90
  }, approvalStore);
80
91
  if (verdict.decision === "allow") {
@@ -107,7 +118,13 @@ export function createToolHandlers(logger, approvalStore, threatsDir, allowlists
107
118
  throw new SageVerdictBlockError(formatDenyMessage(verdict, branding));
108
119
  }
109
120
  // ask — actionId is always set for ask verdicts
110
- const reasons = verdict.reasons.length > 0 ? verdict.reasons.slice(0, 3).join("; ") : verdict.category;
121
+ const maxReasons = 3;
122
+ const reasons = verdict.reasons.length > 0
123
+ ? verdict.reasons.slice(0, maxReasons).join("; ") +
124
+ (verdict.reasons.length > maxReasons
125
+ ? `; ... and ${verdict.reasons.length - maxReasons} more`
126
+ : "")
127
+ : verdict.category;
111
128
  completeHook("evaluated", {
112
129
  toolName,
113
130
  decision: verdict.decision,
@@ -1 +1 @@
1
- {"version":3,"file":"tool-handler.js","sourceRoot":"","sources":["../src/tool-handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tool-handler.js","sourceRoot":"","sources":["../src/tool-handler.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.10.0",
7
+ "version": "0.12.0",
8
8
  "type": "module",
9
9
  "description": "Safety for Agents - ADR layer for OpenCode",
10
10
  "homepage": "https://github.com/gendigitalinc/sage",
@@ -32,10 +32,12 @@
32
32
  ],
33
33
  "dependencies": {
34
34
  "@opencode-ai/plugin": "^1.14.48",
35
- "@gendigital/sage-core": "0.10.0"
35
+ "@gendigital/sage-mcp": "0.12.0",
36
+ "@gendigital/sage-core": "0.12.0"
36
37
  },
37
38
  "devDependencies": {
38
39
  "@types/node": "^22.0.0",
40
+ "esbuild": "^0.25.0",
39
41
  "typescript": "^5.9.0",
40
42
  "vitest": "^4.0.0"
41
43
  },
@@ -52,7 +54,7 @@
52
54
  "malware-detection"
53
55
  ],
54
56
  "scripts": {
55
- "build": "pnpm -C ../core build && pnpm run clean && pnpm run sync:assets && tsc",
57
+ "build": "pnpm run clean && pnpm run sync:assets && tsc && node esbuild.config.mjs",
56
58
  "clean": "node ../../scripts/clean.mjs dist resources tsconfig.tsbuildinfo",
57
59
  "sync:assets": "node scripts/sync-assets.mjs",
58
60
  "test": "vitest run"
@@ -0,0 +1,186 @@
1
+ # Agent-layer threat patterns for Sage
2
+ #
3
+ # Author: ATR (Agent Threat Rules) community contributors
4
+ # Upstream: https://github.com/Agent-Threat-Rule/agent-threat-rules
5
+ # Contributed per issue #30 + vaclavbelak's comment
6
+ # (https://github.com/gendigitalinc/sage/issues/30#issuecomment-4266904912)
7
+ #
8
+ # License: MIT
9
+ # Rules in this file are adapted from the ATR project
10
+ # (https://github.com/Agent-Threat-Rule/agent-threat-rules),
11
+ # Copyright (c) 2026 ATR Contributors, and are included in Sage
12
+ # under the ATR MIT license per explicit agreement in issue #30.
13
+ # Sage-specific modifications to each rule are noted in its comment block.
14
+ #
15
+ # What this file covers (gaps vs Sage's existing rules):
16
+ # MCP tool / response attacks CLT-MCP-004 (1 rule -- path traversal)
17
+ # Skill package compromise CLT-SKL-001..008 (6 rules -- IDs 001,002,004,005,006,008; 003/007 dropped for FP risk)
18
+ # Context exfiltration CLT-CTX-003 (1 rule -- PEM key leak)
19
+ # Supply chain CLT-SUPPLY-002 (1 rule)
20
+ #
21
+ # All prompt_injection rules have been moved to prompt-injection.yaml:
22
+ # CLT-PI-052 (IMPORTANT-tag shadowing, ex CLT-MCP-002)
23
+ # CLT-PI-091..093 (HTML-comment delivery, jailbreak persona, CJK pivot)
24
+ # Dropped: CLT-CTX-002 (instruction tampering) -- covered by CLT-PI-001..005
25
+ #
26
+ # Design notes:
27
+ # - All rules use `match_on: content` so they fire on Write/Edit content,
28
+ # plugin/skill file scans, and any agent integration that passes a
29
+ # `content` artifact. They complement (do not duplicate) Sage's existing
30
+ # command/URL/credential-file rules.
31
+ # - Confidence values are calibrated to Sage's policy zones (docs/decision-pipeline.md):
32
+ # 0.95 = attack-only signal, deny under all sensitivities
33
+ # 0.85 = high-precision attack pattern, deny paranoid/balanced, ask relaxed
34
+ # - `case_insensitive: true` replaces ATR's `(?i)` inline flag.
35
+
36
+ # ===========================================================================
37
+ # MCP TOOL & RESPONSE POISONING
38
+ # ===========================================================================
39
+
40
+ - id: "CLT-MCP-004"
41
+ category: mcp_poisoning
42
+ severity: warning
43
+ confidence: 0.85
44
+ pattern: "\\.\\.[\\/\\\\](?:\\.\\.[\\/\\\\])+(?:etc|proc|root|sys|boot|passwd|shadow|shadow\\.bak|master\\.key)(?:[\\/\\\\]|\\s|$)"
45
+ match_on: content
46
+ case_insensitive: false
47
+ title: "Path traversal targeting system directory (/etc, /proc, /root, /sys, ...)"
48
+ expires_at: null
49
+ revoked: false
50
+ # Adapted from ATR-2026-00012: narrowed to require 2+ traversal hops terminating
51
+ # in a sensitive system directory (dropped dev, hosts from ATR's list); reduces
52
+ # FP on benign code examples that use relative paths like ../../src/.
53
+ # Fires in pre-hook (Write/Edit content blocking) and session-start plugin scans
54
+ # only; post-hook scanning is limited to category=prompt_injection rules.
55
+
56
+ # ===========================================================================
57
+ # SKILL PACKAGE COMPROMISE -- malicious content inside SKILL.md, plugin
58
+ # manifests, or skill package files.
59
+ # ===========================================================================
60
+
61
+ - id: "CLT-SKL-001"
62
+ category: skill_compromise
63
+ severity: critical
64
+ confidence: 0.85
65
+ pattern: "you\\s+(must|should|will|shall)\\s+(ignore|disregard|override|forget|bypass|circumvent|supersede|set\\s+aside|discard|abandon)\\s+(all\\s+)?(previous|prior|system|safety|security)\\s+(instructions?|prompts?|rules?|guidelines?|policies|restrictions?)"
66
+ match_on: content
67
+ case_insensitive: true
68
+ title: "SKILL.md prompt injection via mandatory override"
69
+ expires_at: null
70
+ revoked: false
71
+ # Adapted from ATR-2026-00120: simplified to single regex targeting the
72
+ # mandatory-subject ("you must/shall") framing only; omits ATR's broader
73
+ # context-window injection and multi-condition layers.
74
+ # Intentional layering with CLT-PI-001..004: those rules catch the bare
75
+ # imperative verb; this rule adds a distinct signal for the explicit mandatory
76
+ # subject, increasing confidence when both fire on the same payload.
77
+
78
+ # CLT-SKL-003 intentionally omitted — dropped for FP risk during ATR curation.
79
+
80
+ - id: "CLT-SKL-002"
81
+ category: skill_compromise
82
+ severity: critical
83
+ confidence: 0.85
84
+ pattern: "(eval\\s*\\$\\(\\s*echo\\s+[\"'][A-Za-z0-9+/=]{20,}[\"']\\s*\\|\\s*base64\\s+-d|echo\\s+[\"'][A-Za-z0-9+/=]{20,}[\"']\\s*\\|\\s*base64\\s+(-d|--decode)\\s*\\|\\s*(bash|sh|python|node|ruby|perl))"
85
+ match_on: content
86
+ case_insensitive: true
87
+ title: "Base64-encoded payload piped to interpreter inside skill content"
88
+ expires_at: null
89
+ revoked: false
90
+ # Source: ATR-2026-00121 (pattern unchanged from upstream).
91
+
92
+ - id: "CLT-SKL-004"
93
+ category: skill_compromise
94
+ severity: critical
95
+ confidence: 0.85
96
+ pattern: "<!--[\\s\\S]{0,200}?(agent\\s+should|send\\s+all|output\\s+all|exfiltrate|curl\\s|wget\\s|post\\s+.{0,30}(key|credential|token|password|secret)|api[_-]?key.{0,30}https?://)"
97
+ match_on: content
98
+ case_insensitive: true
99
+ title: "Hidden payload in HTML comment within skill content"
100
+ expires_at: null
101
+ revoked: false
102
+ # Adapted from ATR-2026-00128: changed ATR's [^>] lookahead to [\s\S] to avoid
103
+ # false negatives when a hyphen precedes an exfil keyword; maintains same
104
+ # exfil-keyword focus (distinct from CLT-PI-002's instruction-override focus).
105
+
106
+ - id: "CLT-SKL-005"
107
+ category: skill_compromise
108
+ severity: critical
109
+ confidence: 0.95
110
+ pattern: "(?:\\uDB40[\\uDC00-\\uDC7F]){3,}"
111
+ match_on: content
112
+ case_insensitive: false
113
+ title: "Unicode Tag character smuggling (U+E0000..U+E007F) in skill content"
114
+ expires_at: null
115
+ revoked: false
116
+ # Source: ATR-2026-00129 (pattern unchanged from upstream). Tag characters
117
+ # are invisible to humans but visible to LLMs; 3+ in sequence is an
118
+ # injection signature with no legitimate use.
119
+
120
+ - id: "CLT-SKL-006"
121
+ category: skill_compromise
122
+ severity: critical
123
+ confidence: 0.85
124
+ pattern: "(tar|zip|7z)\\s+[^\\n]*~/?\\.ssh|(find|ls|cat|strings)\\s+[^\\n]*(wallet\\.dat|seed\\.txt|mnemonic|keystore)[^\\n]*(\\||>|>>|curl|wget|fetch|POST)|sqlite3\\s+[^\\n]*(Cookies|Login\\s*Data|cookies\\.sqlite|places\\.sqlite)"
125
+ match_on: content
126
+ case_insensitive: true
127
+ title: "Compound skill-content exfiltration (wallet/browser/SSH archival)"
128
+ expires_at: null
129
+ revoked: false
130
+ # Adapted from ATR-2026-00149: condensed ATR's 13 detection conditions into
131
+ # one regex covering SSH archival, crypto wallet exfil, and browser DB dump;
132
+ # omits ATR's DNS-exfil, IMDS metadata, and env-file piping layers.
133
+ # Intentional layering with CLT-CRED-008 (command artifact): that rule catches
134
+ # the same SSH archival at shell execution time; this rule catches it in
135
+ # written skill/plugin content before it executes.
136
+
137
+ # CLT-SKL-007 intentionally omitted — dropped for FP risk during ATR curation.
138
+
139
+ - id: "CLT-SKL-008"
140
+ category: skill_compromise
141
+ severity: warning
142
+ confidence: 0.85
143
+ pattern: "(?:(?:always|must|shall|will|should)\\s+){1,3}(?:approve|accept|allow|grant|permit)\\b[^.\\n]{0,80}(?:without|regardless|even\\s+if|despite)\\s+(?:confirmation|permission|approval|consent|asking|checking|verification|user)"
144
+ match_on: content
145
+ case_insensitive: true
146
+ title: "Hidden override instruction in skill -- auto-approve all"
147
+ expires_at: null
148
+ revoked: false
149
+ # Adapted from ATR-2026-00163: added "will"/"should" modals and "despite" as
150
+ # an additional consent-bypass synonym; bounded modal repetition to {1,3}.
151
+
152
+ # ===========================================================================
153
+ # CONTEXT EXFILTRATION
154
+ # ===========================================================================
155
+
156
+ - id: "CLT-CTX-003"
157
+ category: context_exfiltration
158
+ severity: critical
159
+ confidence: 0.95
160
+ pattern: "-----BEGIN\\s+[A-Z ]+PRIVATE\\s+KEY-----[\\s\\S]{40,}-----END\\s+[A-Z ]+PRIVATE\\s+KEY-----"
161
+ match_on: content
162
+ title: "PEM private key block appearing in agent content"
163
+ expires_at: null
164
+ revoked: false
165
+ # Source: ATR-2026-00021 (pattern unchanged from upstream). Fires on Write/Edit
166
+ # content and session-start plugin scans (category context_exfiltration is
167
+ # pre-hook only; post-hook scanning is limited to prompt_injection rules).
168
+ # Covers RSA, EC, DSA, OPENSSH, ENCRYPTED variants.
169
+
170
+ # ===========================================================================
171
+ # SUPPLY CHAIN
172
+ # ===========================================================================
173
+
174
+ - id: "CLT-SUPPLY-002"
175
+ category: supply_chain
176
+ severity: warning
177
+ confidence: 0.95
178
+ pattern: "(?:filesytem|filsystem|file_sytem|flie_system|filessystem|filesystm|filsystm|filesysem)[-_](?:read|write|list|delete|search)"
179
+ match_on: content
180
+ case_insensitive: true
181
+ title: "Typosquatted filesystem tool name (targets MCP filesystem server)"
182
+ expires_at: null
183
+ revoked: false
184
+ # Adapted from ATR-2026-00060: extracted filesystem-server typo variants only;
185
+ # narrows ATR's broader MCP squatting rule to the
186
+ # @modelcontextprotocol/server-filesystem impersonation family.