@gendigital/sage-opencode 0.12.0 → 0.13.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 (31) hide show
  1. package/dist/mcp-server.cjs +38 -10
  2. package/dist/mcp-server.cjs.map +2 -2
  3. package/dist/tool-handler.d.ts.map +1 -1
  4. package/dist/tool-handler.js +5 -3
  5. package/dist/tool-handler.js.map +1 -1
  6. package/package.json +3 -3
  7. package/resources/threats/_macros.yaml +193 -0
  8. package/resources/threats/agent-layer.yaml +19 -1
  9. package/resources/threats/commands.yaml +165 -31
  10. package/resources/threats/credentials.yaml +24 -4
  11. package/resources/threats/dummy.yaml +30 -0
  12. package/resources/threats/files.yaml +38 -0
  13. package/resources/threats/mac-commands.yaml +118 -27
  14. package/resources/threats/mac-credentials.yaml +34 -8
  15. package/resources/threats/mac-files.yaml +20 -0
  16. package/resources/threats/mac-obfuscation.yaml +28 -6
  17. package/resources/threats/mac-persistence.yaml +30 -4
  18. package/resources/threats/mac-supply-chain.yaml +12 -3
  19. package/resources/threats/mitre.yaml +325 -62
  20. package/resources/threats/obfuscation.yaml +33 -8
  21. package/resources/threats/persistence.yaml +40 -5
  22. package/resources/threats/prompt-injection.yaml +58 -0
  23. package/resources/threats/self-defense.yaml +15 -2
  24. package/resources/threats/supply_chain.yaml +6 -1
  25. package/resources/threats/urls.yaml +10 -0
  26. package/resources/threats/win-commands.yaml +294 -60
  27. package/resources/threats/win-credentials.yaml +68 -9
  28. package/resources/threats/win-files.yaml +20 -0
  29. package/resources/threats/win-obfuscation.yaml +56 -8
  30. package/resources/threats/win-persistence.yaml +45 -7
  31. package/resources/threats/win-supply-chain.yaml +5 -1
@@ -4230,7 +4230,8 @@ var init_types2 = __esm({
4230
4230
  VerdictSeveritySchema = external_exports.enum(["info", "warning", "critical"]);
4231
4231
  ThreatSchema = external_exports.object({
4232
4232
  id: external_exports.string(),
4233
- version: external_exports.number().int().optional(),
4233
+ version: external_exports.number().int().positive(),
4234
+ detectionName: external_exports.string(),
4234
4235
  category: external_exports.string(),
4235
4236
  severity: VerdictSeveritySchema,
4236
4237
  confidence: external_exports.number(),
@@ -4329,6 +4330,7 @@ var init_types2 = __esm({
4329
4330
  sensitivity: SensitivitySchema.default("balanced"),
4330
4331
  disabled_threats: external_exports.array(external_exports.string()).default([]),
4331
4332
  announce_clean_scans: external_exports.boolean().default(true),
4333
+ manage_status_line: external_exports.boolean().default(true),
4332
4334
  brand_key: external_exports.string().min(1).max(32).regex(/^[a-z0-9_-]+$/u).optional(),
4333
4335
  community_iq: external_exports.boolean().default(true)
4334
4336
  });
@@ -20788,7 +20790,7 @@ init_file_utils();
20788
20790
  var import_meta = {};
20789
20791
  function resolveVersion() {
20790
20792
  if (true)
20791
- return "0.12.0";
20793
+ return "0.13.0";
20792
20794
  try {
20793
20795
  const pkgPath = (0, import_node_path3.join)((0, import_node_path3.dirname)((0, import_node_url.fileURLToPath)(import_meta.url)), "..", "package.json");
20794
20796
  const pkg = JSON.parse(getFileContentSync(pkgPath));
@@ -31437,6 +31439,9 @@ function readContent(entry) {
31437
31439
  return {};
31438
31440
  return raw;
31439
31441
  }
31442
+ function readContentSnippet(entry) {
31443
+ return asString(entry.content_snippet);
31444
+ }
31440
31445
  function isRuntimeVerdictEntry(v) {
31441
31446
  if (!v || typeof v !== "object" || Array.isArray(v))
31442
31447
  return false;
@@ -31482,9 +31487,10 @@ var ReportInputSchema = external_exports.object({
31482
31487
  entry_ids: external_exports.array(external_exports.string()).optional().describe(`REQUIRED in normal use: list of specific audit entry_ids to report as false positives. ALWAYS call sage_list_audit_entries first to inspect the audit log and identify the exact deny/ask verdict the user considers a false positive, then pass its entry_id here. Up to ${MAX_EXPLICIT_ENTRIES} entry_ids may be provided per call. Omitting this parameter is a fallback that submits up to ${MAX_IMPLICIT_ENTRIES} most recent deny/ask entries for the conversation, which may include irrelevant verdicts and should only be used when entry_id discovery is impossible.`),
31483
31488
  dry_run: external_exports.boolean().optional().describe("If true, do not POST; just show the payload.")
31484
31489
  });
31485
- function parseAuditSignals(raw) {
31490
+ function parseAuditSignals(raw, options = {}) {
31486
31491
  if (!raw || typeof raw !== "object" || Array.isArray(raw))
31487
31492
  return {};
31493
+ const includePiContentSnippet = options.includePiContentSnippet ?? true;
31488
31494
  const obj = raw;
31489
31495
  const heuristicsRaw = obj.heuristics;
31490
31496
  const urlChecksRaw = obj.url_checks;
@@ -31496,11 +31502,16 @@ function parseAuditSignals(raw) {
31496
31502
  if (!h || typeof h !== "object" || Array.isArray(h))
31497
31503
  return null;
31498
31504
  const rec = h;
31505
+ const detection_name = asString(rec.detection_name);
31499
31506
  const rule_id = asString(rec.rule_id);
31500
31507
  const rule_version = typeof rec.rule_version === "number" ? Math.trunc(rec.rule_version) : void 0;
31501
31508
  if (!rule_id)
31502
31509
  return null;
31503
- return { rule_id, rule_version };
31510
+ return {
31511
+ ...detection_name ? { detection_name } : {},
31512
+ rule_id,
31513
+ rule_version
31514
+ };
31504
31515
  }).filter(Boolean) : void 0;
31505
31516
  const url_checks = Array.isArray(urlChecksRaw) ? urlChecksRaw.map((u) => {
31506
31517
  if (!u || typeof u !== "object" || Array.isArray(u))
@@ -31538,12 +31549,20 @@ function parseAuditSignals(raw) {
31538
31549
  if (!m || typeof m !== "object" || Array.isArray(m))
31539
31550
  return null;
31540
31551
  const rec = m;
31552
+ const detection_name = asString(rec.detection_name);
31541
31553
  const risk = typeof rec.risk === "number" ? rec.risk : void 0;
31542
31554
  const model_id = asString(rec.model_id);
31543
31555
  const content_name = asString(rec.content_name);
31556
+ const content_snippet = asString(rec.content_snippet);
31544
31557
  if (risk === void 0 || !model_id || !content_name)
31545
31558
  return null;
31546
- return { risk, model_id, content_name };
31559
+ return {
31560
+ ...detection_name ? { detection_name } : {},
31561
+ risk,
31562
+ model_id,
31563
+ content_name,
31564
+ ...content_snippet && includePiContentSnippet ? { content_snippet } : {}
31565
+ };
31547
31566
  }).filter(Boolean) : void 0;
31548
31567
  const amsi_checks = Array.isArray(amsiChecksRaw) ? amsiChecksRaw.map((a) => {
31549
31568
  if (!a || typeof a !== "object" || Array.isArray(a))
@@ -31615,7 +31634,11 @@ function registerFalsePositiveTools(server, opts) {
31615
31634
  severity: asString(e.severity),
31616
31635
  source: asString(e.source),
31617
31636
  user_override: e.user_override,
31618
- signals: parseAuditSignals(e.signals),
31637
+ // PI snippets are untrusted fetched content. Exclude their raw
31638
+ // text—including the generic top-level content_snippet - from this
31639
+ // model-visible response. Retain it only for the backend-only
31640
+ // false-positive report below.
31641
+ signals: parseAuditSignals(e.signals, { includePiContentSnippet: false }),
31619
31642
  content: readContent(e)
31620
31643
  }));
31621
31644
  complete("completed", {
@@ -31732,10 +31755,14 @@ ${reasoning}`;
31732
31755
  const agent_runtime = asString(e.agent_runtime) ?? "unknown";
31733
31756
  const tool_type = asString(e.tool_name) ?? "Unknown";
31734
31757
  const verdict = asString(e.verdict) ?? "deny";
31735
- const user_action = e.user_override === true ? "allowed" : "blocked";
31758
+ const wasAllowed = verdict === "allow" || e.user_override === true;
31759
+ const user_action = wasAllowed ? "allowed" : "blocked";
31736
31760
  const hook_type = asHookType(e.hook_type) ?? "PreToolUse";
31737
- const signals = parseAuditSignals(e.signals);
31761
+ const signals = parseAuditSignals(e.signals, {
31762
+ includePiContentSnippet: !dry_run
31763
+ });
31738
31764
  const content = readContent(e);
31765
+ const contentSnippet = readContentSnippet(e);
31739
31766
  const bestEffortSignals = {};
31740
31767
  if (signals.heuristics)
31741
31768
  bestEffortSignals.heuristics = signals.heuristics;
@@ -31764,7 +31791,8 @@ ${reasoning}`;
31764
31791
  user_action,
31765
31792
  timestamp,
31766
31793
  ...Object.keys(bestEffortSignals).length > 0 ? { signals: bestEffortSignals } : {},
31767
- content
31794
+ content,
31795
+ ...contentSnippet && !dry_run ? { content_snippet: contentSnippet } : {}
31768
31796
  },
31769
31797
  comment,
31770
31798
  event_id: entry_id ?? (0, import_node_crypto2.randomUUID)()
@@ -31869,7 +31897,7 @@ async function main() {
31869
31897
  );
31870
31898
  const branding = resolveBranding(config2.brand_key, logger);
31871
31899
  await runSageMcpServerStdio({
31872
- version: "0.12.0",
31900
+ version: "0.13.0",
31873
31901
  logger,
31874
31902
  branding
31875
31903
  });