@highflame/policy 2.2.40 → 2.2.41
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/_schemas/agent_ops/templates/ported/organization/organization_deny_baseline.cedar +2 -2
- package/_schemas/agent_ops/templates/ported/tool-permissioning/tools_mcp_server_allowlist.cedar +24 -4
- package/_schemas/ai_gateway/detectors.json +928 -0
- package/_schemas/ai_gateway/templates/mcp_server_allowlist.cedar +24 -4
- package/_schemas/guardrails/detectors.json +2193 -0
- package/_schemas/guardrails/templates/mcp_server_allowlist.cedar +24 -4
- package/_schemas/overwatch/detectors.json +1082 -0
- package/_schemas/sentry/detectors.json +857 -0
- package/dist/agent_ops-defaults.gen.js +26 -6
- package/dist/ai_gateway-defaults.gen.js +24 -4
- package/dist/ai_gateway-detectors.gen.d.ts +1 -1
- package/dist/ai_gateway-detectors.gen.js +22 -8
- package/dist/guardrails-defaults.gen.js +24 -4
- package/dist/guardrails-detectors.gen.d.ts +1 -1
- package/dist/guardrails-detectors.gen.js +22 -8
- package/dist/overwatch-defaults.gen.js +25 -5
- package/dist/overwatch-detectors.gen.d.ts +1 -1
- package/dist/overwatch-detectors.gen.js +22 -8
- package/package.json +1 -1
|
@@ -1648,8 +1648,23 @@ const AGENT_OPS_TOOLS_MCP_SERVER_ALLOWLIST_CEDAR = `// =========================
|
|
|
1648
1648
|
// MCP Server Allowlist
|
|
1649
1649
|
// =============================================================================
|
|
1650
1650
|
// Restricts MCP server connections to a pre-approved list. Customize the
|
|
1651
|
-
// \`context.mcp_server\` values
|
|
1652
|
-
//
|
|
1651
|
+
// \`context.mcp_server\` values to match the allowed servers for your
|
|
1652
|
+
// environment — the SAME list appears in both rules and both must be edited.
|
|
1653
|
+
//
|
|
1654
|
+
// Both rules are conditional on the allowlist, and both are needed:
|
|
1655
|
+
//
|
|
1656
|
+
// permit ... when { allowlisted } grants access; Cedar is default-deny,
|
|
1657
|
+
// so without this nothing allows the
|
|
1658
|
+
// allowlisted servers either.
|
|
1659
|
+
// forbid ... unless { allowlisted } claws back everything else, including
|
|
1660
|
+
// when a broad Baseline Permit is loaded.
|
|
1661
|
+
//
|
|
1662
|
+
// The forbid MUST carry the negation. \`forbid\` always beats \`permit\` in Cedar,
|
|
1663
|
+
// so an UNCONDITIONAL forbid denies the allowlisted servers too — which is
|
|
1664
|
+
// what this template used to do (highflame-policy#186).
|
|
1665
|
+
//
|
|
1666
|
+
// The \`context has mcp_server\` guard stays inside both conditions: a request
|
|
1667
|
+
// naming no server cannot be on the allowlist, so it is denied.
|
|
1653
1668
|
//
|
|
1654
1669
|
// Context keys consumed:
|
|
1655
1670
|
// - mcp_server: String
|
|
@@ -1676,7 +1691,7 @@ when {
|
|
|
1676
1691
|
|
|
1677
1692
|
@id("tools.deny-non-allowlisted-mcp")
|
|
1678
1693
|
@name("Block non-allowlisted MCP servers")
|
|
1679
|
-
@description("Blocks connect_server
|
|
1694
|
+
@description("Blocks connect_server unless mcp_server is in the allowlist.")
|
|
1680
1695
|
@severity("medium")
|
|
1681
1696
|
@tags("category:tools,surface:connect-server,scope:org-wide,posture:deny-default")
|
|
1682
1697
|
@reject_message("MCP server connection blocked: server is not on the allowlist.")
|
|
@@ -1684,7 +1699,12 @@ forbid (
|
|
|
1684
1699
|
principal,
|
|
1685
1700
|
action == AgentOps::Action::"connect_server",
|
|
1686
1701
|
resource
|
|
1687
|
-
)
|
|
1702
|
+
)
|
|
1703
|
+
unless {
|
|
1704
|
+
context has mcp_server &&
|
|
1705
|
+
(context.mcp_server == "filesystem" ||
|
|
1706
|
+
context.mcp_server == "playwright")
|
|
1707
|
+
};
|
|
1688
1708
|
`;
|
|
1689
1709
|
const AGENT_OPS_SECURITY_CHAT_ASSISTANT_CEDAR = `// =============================================================================
|
|
1690
1710
|
// Chat Assistant — Security
|
|
@@ -4460,8 +4480,8 @@ const AGENT_OPS_ORGANIZATION_DENY_BASELINE_CEDAR = `// =========================
|
|
|
4460
4480
|
// =============================================================================
|
|
4461
4481
|
|
|
4462
4482
|
@id("organization.deny-baseline")
|
|
4463
|
-
@name("Block all actions (
|
|
4464
|
-
@description("Blocks all actions
|
|
4483
|
+
@name("Block all actions (kill switch)")
|
|
4484
|
+
@description("Blocks all actions unconditionally. A kill switch, not a baseline: forbid beats permit in Cedar, so this also disables every permit in the set.")
|
|
4465
4485
|
@severity("high")
|
|
4466
4486
|
@tags("category:organization,posture:deny-default,scope:org-wide")
|
|
4467
4487
|
@reject_message("Request blocked: this organization uses a deny-by-default baseline — only explicitly permitted actions are allowed.")
|
|
@@ -370,8 +370,23 @@ const AI_GATEWAY_TOOLS_MCP_SERVER_ALLOWLIST_CEDAR = `// ========================
|
|
|
370
370
|
// MCP Server Allowlist
|
|
371
371
|
// =============================================================================
|
|
372
372
|
// Restricts MCP server connections to a pre-approved list. Customize the
|
|
373
|
-
// \`context.mcp_server\` values
|
|
374
|
-
//
|
|
373
|
+
// \`context.mcp_server\` values to match the allowed servers for your
|
|
374
|
+
// environment — the SAME list appears in both rules and both must be edited.
|
|
375
|
+
//
|
|
376
|
+
// Both rules are conditional on the allowlist, and both are needed:
|
|
377
|
+
//
|
|
378
|
+
// permit ... when { allowlisted } grants access; Cedar is default-deny,
|
|
379
|
+
// so without this nothing allows the
|
|
380
|
+
// allowlisted servers either.
|
|
381
|
+
// forbid ... unless { allowlisted } claws back everything else, including
|
|
382
|
+
// when a broad Baseline Permit is loaded.
|
|
383
|
+
//
|
|
384
|
+
// The forbid MUST carry the negation. \`forbid\` always beats \`permit\` in Cedar,
|
|
385
|
+
// so an UNCONDITIONAL forbid denies the allowlisted servers too — which is
|
|
386
|
+
// what this template used to do (highflame-policy#186).
|
|
387
|
+
//
|
|
388
|
+
// The \`context has mcp_server\` guard stays inside both conditions: a request
|
|
389
|
+
// naming no server cannot be on the allowlist, so it is denied.
|
|
375
390
|
//
|
|
376
391
|
// Context keys consumed:
|
|
377
392
|
// - mcp_server: String
|
|
@@ -398,7 +413,7 @@ when {
|
|
|
398
413
|
|
|
399
414
|
@id("tools.deny-non-allowlisted-mcp")
|
|
400
415
|
@name("Block non-allowlisted MCP servers")
|
|
401
|
-
@description("Blocks connect_server
|
|
416
|
+
@description("Blocks connect_server unless mcp_server is in the allowlist.")
|
|
402
417
|
@severity("medium")
|
|
403
418
|
@tags("category:tools,surface:connect-server,scope:org-wide,posture:deny-default")
|
|
404
419
|
@reject_message("MCP server connection blocked: server is not on the allowlist.")
|
|
@@ -406,7 +421,12 @@ forbid (
|
|
|
406
421
|
principal,
|
|
407
422
|
action == AIGateway::Action::"connect_server",
|
|
408
423
|
resource
|
|
409
|
-
)
|
|
424
|
+
)
|
|
425
|
+
unless {
|
|
426
|
+
context has mcp_server &&
|
|
427
|
+
(context.mcp_server == "filesystem" ||
|
|
428
|
+
context.mcp_server == "playwright")
|
|
429
|
+
};
|
|
410
430
|
`;
|
|
411
431
|
const AI_GATEWAY_TOOLS_MCP_TOOL_PERMISSIONS_CEDAR = `// =============================================================================
|
|
412
432
|
// MCP Tool Permissions
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DetectorCard } from './detector-card-types.gen';
|
|
2
|
-
export declare const AI_GATEWAY_DETECTOR_SPEC_VERSION = "1.
|
|
2
|
+
export declare const AI_GATEWAY_DETECTOR_SPEC_VERSION = "1.1.0";
|
|
3
3
|
export declare const AI_GATEWAY_DETECTORS: readonly DetectorCard[];
|
|
4
4
|
export declare const AI_GATEWAY_FIELD_TO_DETECTORS: Readonly<Record<string, readonly string[]>>;
|
|
5
5
|
export declare function aiGatewayDetectorById(id: string): DetectorCard | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const AI_GATEWAY_DETECTOR_SPEC_VERSION = "1.
|
|
1
|
+
export const AI_GATEWAY_DETECTOR_SPEC_VERSION = "1.1.0";
|
|
2
2
|
export const AI_GATEWAY_DETECTORS = [
|
|
3
3
|
{
|
|
4
4
|
id: "injection",
|
|
@@ -177,11 +177,25 @@ export const AI_GATEWAY_DETECTORS = [
|
|
|
177
177
|
inhouse: false,
|
|
178
178
|
model: null,
|
|
179
179
|
latencyP50Ms: 250,
|
|
180
|
-
emits: [{ name: "package_install_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff a package install/download command was recognized in the event." }, { name: "packages_checked", type: "Long", modifiable: false, semantic: "count", description: "Number of unique packages checked against osv.dev." }, { name: "malicious_package_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff any referenced package has a known-malicious (MAL-) OSV advisory." }, { name: "malicious_package_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "100 when a malicious package was detected, 0 otherwise." }, { name: "malicious_packages", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Malicious packages as ecosystem/name[@version] strings." }, { name: "
|
|
180
|
+
emits: [{ name: "package_install_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff a package install/download command was recognized in the event." }, { name: "packages_checked", type: "Long", modifiable: false, semantic: "count", description: "Number of unique packages checked against osv.dev." }, { name: "malicious_package_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff any referenced package has a known-malicious (MAL-) OSV advisory." }, { name: "malicious_package_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "100 when a malicious package was detected, 0 otherwise." }, { name: "malicious_packages", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Malicious packages as ecosystem/name[@version] strings." }, { name: "package_check_status", type: "String", modifiable: false, semantic: "category_label", description: "Set to 'degraded' when the osv.dev lookup failed (fail-open); empty otherwise." }],
|
|
181
181
|
supportedModes: ["enforce", "monitor", "alert"],
|
|
182
182
|
defendsAgainst: ["supply_chain"],
|
|
183
183
|
exampleAttacks: [{ title: "Typosquatted PyPI install via MCP bash tool", vulnerabilityId: "supply_chain", snippet: "pip install reqeusts", expectedSignal: {} }],
|
|
184
184
|
},
|
|
185
|
+
{
|
|
186
|
+
id: "package_reputation",
|
|
187
|
+
displayName: "Package Reputation (OSV)",
|
|
188
|
+
category: "tool_safety",
|
|
189
|
+
stability: "preview",
|
|
190
|
+
tier: "slow",
|
|
191
|
+
inhouse: false,
|
|
192
|
+
model: null,
|
|
193
|
+
latencyP50Ms: 250,
|
|
194
|
+
emits: [{ name: "malicious_package_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff any referenced package has a known-malicious (MAL-) OSV advisory." }, { name: "malicious_packages", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Malicious packages as ecosystem/name[@version] strings." }, { name: "package_names", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Names of all packages parsed from install commands (without ecosystem prefix), e.g. 'requests', 'left-pad'. Available even when the osv.dev lookup fails." }, { name: "package_ecosystems", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Unique package ecosystems seen in this event, e.g. 'PyPI', 'npm'. Useful for policies that restrict which ecosystems are permitted." }, { name: "package_advisory_count", type: "Long", modifiable: false, semantic: "count", description: "Total non-malicious OSV advisories (GHSA- / CVE- IDs) found across all checked packages. Excludes MAL- entries counted in malicious_package_detected." }, { name: "package_risk_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "Graduated supply-chain risk score (0-100). 100 when any malicious package is found; proportional to advisory_count for advisory-only packages; 0 when all packages are clean." }],
|
|
195
|
+
supportedModes: ["enforce", "monitor", "alert"],
|
|
196
|
+
defendsAgainst: ["supply_chain"],
|
|
197
|
+
exampleAttacks: [{ title: "Install of a package carrying a malicious advisory", vulnerabilityId: "supply_chain", snippet: "pip install evil-pkg", expectedSignal: { "malicious_package_detected": true } }],
|
|
198
|
+
},
|
|
185
199
|
];
|
|
186
200
|
// Semantic field → contributing detector ids (producesAttrs + normalizationAliases,
|
|
187
201
|
// resolved at codegen). Used by the client field→detector resolver — no Shield round-trip.
|
|
@@ -196,20 +210,20 @@ export const AI_GATEWAY_FIELD_TO_DETECTORS = {
|
|
|
196
210
|
"jailbreak_score": ["injection"],
|
|
197
211
|
"loop_count": ["loop_detector"],
|
|
198
212
|
"loop_detected": ["loop_detector"],
|
|
199
|
-
"malicious_package_detected": ["malicious_package"],
|
|
213
|
+
"malicious_package_detected": ["malicious_package", "package_reputation"],
|
|
200
214
|
"malicious_package_score": ["malicious_package"],
|
|
201
|
-
"malicious_packages": ["malicious_package"],
|
|
215
|
+
"malicious_packages": ["malicious_package", "package_reputation"],
|
|
202
216
|
"mcp_config_risk": ["mcp_risk"],
|
|
203
217
|
"mcp_risk_score": ["mcp_risk"],
|
|
204
218
|
"mcp_server": ["mcp_risk"],
|
|
205
219
|
"mcp_server_verified": ["mcp_risk"],
|
|
206
220
|
"mcp_tool": ["mcp_risk"],
|
|
207
|
-
"package_advisory_count": ["
|
|
221
|
+
"package_advisory_count": ["package_reputation"],
|
|
208
222
|
"package_check_status": ["malicious_package"],
|
|
209
|
-
"package_ecosystems": ["
|
|
223
|
+
"package_ecosystems": ["package_reputation"],
|
|
210
224
|
"package_install_detected": ["malicious_package"],
|
|
211
|
-
"package_names": ["
|
|
212
|
-
"package_risk_score": ["
|
|
225
|
+
"package_names": ["package_reputation"],
|
|
226
|
+
"package_risk_score": ["package_reputation"],
|
|
213
227
|
"packages_checked": ["malicious_package"],
|
|
214
228
|
"pattern_type": ["action_pattern"],
|
|
215
229
|
"pii_count": ["pii"],
|
|
@@ -1193,8 +1193,23 @@ const GUARDRAILS_TOOLS_MCP_SERVER_ALLOWLIST_CEDAR = `// ========================
|
|
|
1193
1193
|
// MCP Server Allowlist
|
|
1194
1194
|
// =============================================================================
|
|
1195
1195
|
// Restricts MCP server connections to a pre-approved list. Customize the
|
|
1196
|
-
// \`context.mcp_server\` values
|
|
1197
|
-
//
|
|
1196
|
+
// \`context.mcp_server\` values to match the allowed servers for your
|
|
1197
|
+
// environment — the SAME list appears in both rules and both must be edited.
|
|
1198
|
+
//
|
|
1199
|
+
// Both rules are conditional on the allowlist, and both are needed:
|
|
1200
|
+
//
|
|
1201
|
+
// permit ... when { allowlisted } grants access; Cedar is default-deny,
|
|
1202
|
+
// so without this nothing allows the
|
|
1203
|
+
// allowlisted servers either.
|
|
1204
|
+
// forbid ... unless { allowlisted } claws back everything else, including
|
|
1205
|
+
// when a broad Baseline Permit is loaded.
|
|
1206
|
+
//
|
|
1207
|
+
// The forbid MUST carry the negation. \`forbid\` always beats \`permit\` in Cedar,
|
|
1208
|
+
// so an UNCONDITIONAL forbid denies the allowlisted servers too — which is
|
|
1209
|
+
// what this template used to do (highflame-policy#186).
|
|
1210
|
+
//
|
|
1211
|
+
// The \`context has mcp_server\` guard stays inside both conditions: a request
|
|
1212
|
+
// naming no server cannot be on the allowlist, so it is denied.
|
|
1198
1213
|
//
|
|
1199
1214
|
// Context keys consumed:
|
|
1200
1215
|
// - mcp_server: String
|
|
@@ -1221,7 +1236,7 @@ when {
|
|
|
1221
1236
|
|
|
1222
1237
|
@id("tools.deny-non-allowlisted-mcp")
|
|
1223
1238
|
@name("Block non-allowlisted MCP servers")
|
|
1224
|
-
@description("Blocks connect_server
|
|
1239
|
+
@description("Blocks connect_server unless mcp_server is in the allowlist.")
|
|
1225
1240
|
@severity("medium")
|
|
1226
1241
|
@tags("category:tools,surface:connect-server,scope:org-wide,posture:deny-default")
|
|
1227
1242
|
@reject_message("MCP server connection blocked: server is not on the allowlist.")
|
|
@@ -1229,7 +1244,12 @@ forbid (
|
|
|
1229
1244
|
principal,
|
|
1230
1245
|
action == Guardrails::Action::"connect_server",
|
|
1231
1246
|
resource
|
|
1232
|
-
)
|
|
1247
|
+
)
|
|
1248
|
+
unless {
|
|
1249
|
+
context has mcp_server &&
|
|
1250
|
+
(context.mcp_server == "filesystem" ||
|
|
1251
|
+
context.mcp_server == "playwright")
|
|
1252
|
+
};
|
|
1233
1253
|
`;
|
|
1234
1254
|
const GUARDRAILS_SECURITY_CHAT_ASSISTANT_CEDAR = `// =============================================================================
|
|
1235
1255
|
// Chat Assistant — Security
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DetectorCard } from './detector-card-types.gen';
|
|
2
|
-
export declare const GUARDRAILS_DETECTOR_SPEC_VERSION = "1.
|
|
2
|
+
export declare const GUARDRAILS_DETECTOR_SPEC_VERSION = "1.4.0";
|
|
3
3
|
export declare const GUARDRAILS_DETECTORS: readonly DetectorCard[];
|
|
4
4
|
export declare const GUARDRAILS_FIELD_TO_DETECTORS: Readonly<Record<string, readonly string[]>>;
|
|
5
5
|
export declare function guardrailsDetectorById(id: string): DetectorCard | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const GUARDRAILS_DETECTOR_SPEC_VERSION = "1.
|
|
1
|
+
export const GUARDRAILS_DETECTOR_SPEC_VERSION = "1.4.0";
|
|
2
2
|
export const GUARDRAILS_DETECTORS = [
|
|
3
3
|
{
|
|
4
4
|
id: "pii",
|
|
@@ -401,11 +401,25 @@ export const GUARDRAILS_DETECTORS = [
|
|
|
401
401
|
inhouse: false,
|
|
402
402
|
model: null,
|
|
403
403
|
latencyP50Ms: 250,
|
|
404
|
-
emits: [{ name: "package_install_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff a package install/download command was recognized in the event." }, { name: "packages_checked", type: "Long", modifiable: false, semantic: "count", description: "Number of unique packages checked against osv.dev." }, { name: "malicious_package_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff any referenced package has a known-malicious (MAL-) OSV advisory." }, { name: "malicious_package_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "100 when a malicious package was detected, 0 otherwise." }, { name: "malicious_packages", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Malicious packages as ecosystem/name[@version] strings." }, { name: "
|
|
404
|
+
emits: [{ name: "package_install_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff a package install/download command was recognized in the event." }, { name: "packages_checked", type: "Long", modifiable: false, semantic: "count", description: "Number of unique packages checked against osv.dev." }, { name: "malicious_package_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff any referenced package has a known-malicious (MAL-) OSV advisory." }, { name: "malicious_package_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "100 when a malicious package was detected, 0 otherwise." }, { name: "malicious_packages", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Malicious packages as ecosystem/name[@version] strings." }, { name: "package_check_status", type: "String", modifiable: false, semantic: "category_label", description: "Set to 'degraded' when the osv.dev lookup failed (fail-open); empty otherwise." }],
|
|
405
405
|
supportedModes: ["enforce", "monitor", "alert"],
|
|
406
406
|
defendsAgainst: ["supply_chain"],
|
|
407
407
|
exampleAttacks: [{ title: "Typosquatted PyPI package install", vulnerabilityId: "supply_chain", snippet: "pip install reqeusts", expectedSignal: {} }],
|
|
408
408
|
},
|
|
409
|
+
{
|
|
410
|
+
id: "package_reputation",
|
|
411
|
+
displayName: "Package Reputation (OSV)",
|
|
412
|
+
category: "tool_safety",
|
|
413
|
+
stability: "preview",
|
|
414
|
+
tier: "slow",
|
|
415
|
+
inhouse: false,
|
|
416
|
+
model: null,
|
|
417
|
+
latencyP50Ms: 250,
|
|
418
|
+
emits: [{ name: "malicious_package_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff any referenced package has a known-malicious (MAL-) OSV advisory." }, { name: "malicious_packages", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Malicious packages as ecosystem/name[@version] strings." }, { name: "package_names", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Names of all packages parsed from install commands (without ecosystem prefix), e.g. 'requests', 'left-pad'. Available even when the osv.dev lookup fails." }, { name: "package_ecosystems", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Unique package ecosystems seen in this event, e.g. 'PyPI', 'npm'. Useful for policies that restrict which ecosystems are permitted." }, { name: "package_advisory_count", type: "Long", modifiable: false, semantic: "count", description: "Total non-malicious OSV advisories (GHSA- / CVE- IDs) found across all checked packages. Excludes MAL- entries counted in malicious_package_detected." }, { name: "package_risk_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "Graduated supply-chain risk score (0-100). 100 when any malicious package is found; proportional to advisory_count for advisory-only packages; 0 when all packages are clean." }],
|
|
419
|
+
supportedModes: ["enforce", "monitor", "alert"],
|
|
420
|
+
defendsAgainst: ["supply_chain"],
|
|
421
|
+
exampleAttacks: [{ title: "Install of a package carrying a malicious advisory", vulnerabilityId: "supply_chain", snippet: "pip install evil-pkg", expectedSignal: { "malicious_package_detected": true } }],
|
|
422
|
+
},
|
|
409
423
|
{
|
|
410
424
|
id: "sentiment",
|
|
411
425
|
displayName: "Sentiment Analysis",
|
|
@@ -510,9 +524,9 @@ export const GUARDRAILS_FIELD_TO_DETECTORS = {
|
|
|
510
524
|
"loop_count": ["loop_detector"],
|
|
511
525
|
"loop_detected": ["loop_detector"],
|
|
512
526
|
"loop_tool": ["loop_detector"],
|
|
513
|
-
"malicious_package_detected": ["malicious_package"],
|
|
527
|
+
"malicious_package_detected": ["malicious_package", "package_reputation"],
|
|
514
528
|
"malicious_package_score": ["malicious_package"],
|
|
515
|
-
"malicious_packages": ["malicious_package"],
|
|
529
|
+
"malicious_packages": ["malicious_package", "package_reputation"],
|
|
516
530
|
"mcp_config_risk": ["mcp_risk"],
|
|
517
531
|
"mcp_input_request_detected": ["mcp_input_request"],
|
|
518
532
|
"mcp_input_request_methods": ["mcp_input_request"],
|
|
@@ -527,12 +541,12 @@ export const GUARDRAILS_FIELD_TO_DETECTORS = {
|
|
|
527
541
|
"mip_label_name": ["file_metadata"],
|
|
528
542
|
"multi_turn_detection": ["deepcontext"],
|
|
529
543
|
"non_ascii_score": ["security"],
|
|
530
|
-
"package_advisory_count": ["
|
|
544
|
+
"package_advisory_count": ["package_reputation"],
|
|
531
545
|
"package_check_status": ["malicious_package"],
|
|
532
|
-
"package_ecosystems": ["
|
|
546
|
+
"package_ecosystems": ["package_reputation"],
|
|
533
547
|
"package_install_detected": ["malicious_package"],
|
|
534
|
-
"package_names": ["
|
|
535
|
-
"package_risk_score": ["
|
|
548
|
+
"package_names": ["package_reputation"],
|
|
549
|
+
"package_risk_score": ["package_reputation"],
|
|
536
550
|
"packages_checked": ["malicious_package"],
|
|
537
551
|
"path_traversal_detected": ["path_traversal"],
|
|
538
552
|
"path_traversal_severity": ["path_traversal"],
|
|
@@ -1547,7 +1547,23 @@ const OVERWATCH_TOOLS_MCP_SERVER_ALLOWLIST_CEDAR = `// =========================
|
|
|
1547
1547
|
// MCP Server Allowlist
|
|
1548
1548
|
// =============================================================================
|
|
1549
1549
|
// Restricts MCP server connections to a pre-approved list. Customize the
|
|
1550
|
-
// \`context.mcp_server\` values
|
|
1550
|
+
// \`context.mcp_server\` values to match the allowed servers for your
|
|
1551
|
+
// environment — the SAME list appears in both rules and both must be edited.
|
|
1552
|
+
//
|
|
1553
|
+
// Both rules are conditional on the allowlist, and both are needed:
|
|
1554
|
+
//
|
|
1555
|
+
// permit ... when { allowlisted } grants access; Cedar is default-deny,
|
|
1556
|
+
// so without this nothing allows the
|
|
1557
|
+
// allowlisted servers either.
|
|
1558
|
+
// forbid ... unless { allowlisted } claws back everything else, including
|
|
1559
|
+
// when a broad Baseline Permit is loaded.
|
|
1560
|
+
//
|
|
1561
|
+
// The forbid MUST carry the negation. \`forbid\` always beats \`permit\` in Cedar,
|
|
1562
|
+
// so an UNCONDITIONAL forbid denies the allowlisted servers too — which is
|
|
1563
|
+
// what this template used to do (highflame-policy#186).
|
|
1564
|
+
//
|
|
1565
|
+
// The \`context has mcp_server\` guard stays inside both conditions: a request
|
|
1566
|
+
// naming no server cannot be on the allowlist, so it is denied.
|
|
1551
1567
|
//
|
|
1552
1568
|
// Context keys consumed:
|
|
1553
1569
|
// - mcp_server: String
|
|
@@ -1573,7 +1589,7 @@ when {
|
|
|
1573
1589
|
|
|
1574
1590
|
@id("tools.deny-non-allowlisted-mcp")
|
|
1575
1591
|
@name("Block non-allowlisted MCP servers")
|
|
1576
|
-
@description("Blocks connect_server
|
|
1592
|
+
@description("Blocks connect_server unless mcp_server is in the allowlist.")
|
|
1577
1593
|
@severity("medium")
|
|
1578
1594
|
@tags("category:tools,surface:connect-server,scope:org-wide,posture:deny-default")
|
|
1579
1595
|
@reject_message("MCP server connection blocked: server is not on the allowlist.")
|
|
@@ -1581,7 +1597,11 @@ forbid (
|
|
|
1581
1597
|
principal,
|
|
1582
1598
|
action == Overwatch::Action::"connect_server",
|
|
1583
1599
|
resource
|
|
1584
|
-
)
|
|
1600
|
+
)
|
|
1601
|
+
unless {
|
|
1602
|
+
context has mcp_server &&
|
|
1603
|
+
(context.mcp_server == "filesystem" || context.mcp_server == "playwright")
|
|
1604
|
+
};
|
|
1585
1605
|
`;
|
|
1586
1606
|
const OVERWATCH_TOOLS_MCP_TOOL_PERMISSIONS_CEDAR = `// =============================================================================
|
|
1587
1607
|
// MCP Tool Permissions
|
|
@@ -1652,8 +1672,8 @@ const OVERWATCH_ORGANIZATION_DENY_BASELINE_CEDAR = `// =========================
|
|
|
1652
1672
|
// =============================================================================
|
|
1653
1673
|
|
|
1654
1674
|
@id("organization.deny-baseline")
|
|
1655
|
-
@name("Block all actions (
|
|
1656
|
-
@description("Blocks all actions
|
|
1675
|
+
@name("Block all actions (kill switch)")
|
|
1676
|
+
@description("Blocks all actions unconditionally. A kill switch, not a baseline: forbid beats permit in Cedar, so this also disables every permit in the set.")
|
|
1657
1677
|
@severity("high")
|
|
1658
1678
|
@tags("category:organization,posture:deny-default,scope:org-wide")
|
|
1659
1679
|
@reject_message("Request blocked: this organization uses a deny-by-default baseline — only explicitly permitted actions are allowed.")
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DetectorCard } from './detector-card-types.gen';
|
|
2
|
-
export declare const OVERWATCH_DETECTOR_SPEC_VERSION = "1.
|
|
2
|
+
export declare const OVERWATCH_DETECTOR_SPEC_VERSION = "1.1.0";
|
|
3
3
|
export declare const OVERWATCH_DETECTORS: readonly DetectorCard[];
|
|
4
4
|
export declare const OVERWATCH_FIELD_TO_DETECTORS: Readonly<Record<string, readonly string[]>>;
|
|
5
5
|
export declare function overwatchDetectorById(id: string): DetectorCard | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const OVERWATCH_DETECTOR_SPEC_VERSION = "1.
|
|
1
|
+
export const OVERWATCH_DETECTOR_SPEC_VERSION = "1.1.0";
|
|
2
2
|
export const OVERWATCH_DETECTORS = [
|
|
3
3
|
{
|
|
4
4
|
id: "injection",
|
|
@@ -191,11 +191,25 @@ export const OVERWATCH_DETECTORS = [
|
|
|
191
191
|
inhouse: false,
|
|
192
192
|
model: null,
|
|
193
193
|
latencyP50Ms: 250,
|
|
194
|
-
emits: [{ name: "package_install_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff a package install/download command was recognized in the
|
|
194
|
+
emits: [{ name: "package_install_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff a package install/download command was recognized in the event." }, { name: "packages_checked", type: "Long", modifiable: false, semantic: "count", description: "Number of unique packages checked against osv.dev." }, { name: "malicious_package_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff any referenced package has a known-malicious (MAL-) OSV advisory." }, { name: "malicious_package_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "100 when a malicious package was detected, 0 otherwise." }, { name: "malicious_packages", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Malicious packages as ecosystem/name[@version] strings." }, { name: "package_check_status", type: "String", modifiable: false, semantic: "category_label", description: "Set to 'degraded' when the osv.dev lookup failed (fail-open); empty otherwise." }],
|
|
195
195
|
supportedModes: ["enforce", "monitor", "alert"],
|
|
196
196
|
defendsAgainst: ["supply_chain"],
|
|
197
197
|
exampleAttacks: [{ title: "Typosquatted PyPI package install", vulnerabilityId: "supply_chain", snippet: "pip install reqeusts", expectedSignal: {} }, { title: "Malicious npm package install", vulnerabilityId: "supply_chain", snippet: "npm install event-stream@3.3.6", expectedSignal: {} }],
|
|
198
198
|
},
|
|
199
|
+
{
|
|
200
|
+
id: "package_reputation",
|
|
201
|
+
displayName: "Package Reputation (OSV)",
|
|
202
|
+
category: "tool_safety",
|
|
203
|
+
stability: "preview",
|
|
204
|
+
tier: "slow",
|
|
205
|
+
inhouse: false,
|
|
206
|
+
model: null,
|
|
207
|
+
latencyP50Ms: 250,
|
|
208
|
+
emits: [{ name: "malicious_package_detected", type: "Bool", modifiable: false, semantic: "boolean_flag", description: "True iff any referenced package has a known-malicious (MAL-) OSV advisory." }, { name: "malicious_packages", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Malicious packages as ecosystem/name[@version] strings." }, { name: "package_names", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Names of all packages parsed from install commands (without ecosystem prefix), e.g. 'requests', 'left-pad'. Available even when the osv.dev lookup fails." }, { name: "package_ecosystems", type: "Set<String>", modifiable: false, semantic: "category_set", description: "Unique package ecosystems seen in this event, e.g. 'PyPI', 'npm'. Useful for policies that restrict which ecosystems are permitted." }, { name: "package_advisory_count", type: "Long", modifiable: false, semantic: "count", description: "Total non-malicious OSV advisories (GHSA- / CVE- IDs) found across all checked packages. Excludes MAL- entries counted in malicious_package_detected." }, { name: "package_risk_score", type: "Long", modifiable: false, semantic: "severity_0_100", description: "Graduated supply-chain risk score (0-100). 100 when any malicious package is found; proportional to advisory_count for advisory-only packages; 0 when all packages are clean." }],
|
|
209
|
+
supportedModes: ["enforce", "monitor", "alert"],
|
|
210
|
+
defendsAgainst: ["supply_chain"],
|
|
211
|
+
exampleAttacks: [{ title: "Install of a package carrying a malicious advisory", vulnerabilityId: "supply_chain", snippet: "pip install evil-pkg", expectedSignal: { "malicious_package_detected": true } }],
|
|
212
|
+
},
|
|
199
213
|
];
|
|
200
214
|
// Semantic field → contributing detector ids (producesAttrs + normalizationAliases,
|
|
201
215
|
// resolved at codegen). Used by the client field→detector resolver — no Shield round-trip.
|
|
@@ -215,20 +229,20 @@ export const OVERWATCH_FIELD_TO_DETECTORS = {
|
|
|
215
229
|
"loop_count": ["loop_detector"],
|
|
216
230
|
"loop_detected": ["loop_detector"],
|
|
217
231
|
"loop_tool": ["loop_detector"],
|
|
218
|
-
"malicious_package_detected": ["malicious_package"],
|
|
232
|
+
"malicious_package_detected": ["malicious_package", "package_reputation"],
|
|
219
233
|
"malicious_package_score": ["malicious_package"],
|
|
220
|
-
"malicious_packages": ["malicious_package"],
|
|
234
|
+
"malicious_packages": ["malicious_package", "package_reputation"],
|
|
221
235
|
"mcp_config_risk": ["mcp_risk"],
|
|
222
236
|
"mcp_risk_score": ["mcp_risk"],
|
|
223
237
|
"mcp_server": ["mcp_risk"],
|
|
224
238
|
"mcp_server_verified": ["mcp_risk"],
|
|
225
239
|
"mcp_tool": ["mcp_risk"],
|
|
226
|
-
"package_advisory_count": ["
|
|
240
|
+
"package_advisory_count": ["package_reputation"],
|
|
227
241
|
"package_check_status": ["malicious_package"],
|
|
228
|
-
"package_ecosystems": ["
|
|
242
|
+
"package_ecosystems": ["package_reputation"],
|
|
229
243
|
"package_install_detected": ["malicious_package"],
|
|
230
|
-
"package_names": ["
|
|
231
|
-
"package_risk_score": ["
|
|
244
|
+
"package_names": ["package_reputation"],
|
|
245
|
+
"package_risk_score": ["package_reputation"],
|
|
232
246
|
"packages_checked": ["malicious_package"],
|
|
233
247
|
"pattern_type": ["action_pattern"],
|
|
234
248
|
"pii_count": ["pii"],
|