# OpenGrep super-config: precise # # Auto-generated by security/opengrep/compile-rules.mjs. # DO NOT EDIT BY HAND. Re-run the compile script after editing source rules. # # Source rules dir: security/opengrep/rules/openclaw-policy # Generated at : 2026-04-30T09:09:41.198Z # Rule count : 148 rules: - id: ghsa-25gx-x37c-7pph.openclaw-novnc-x11vnc-missing-auth message: x11vnc starts without VNC authentication; avoid -nopw and require password auth when exposing noVNC observer access. severity: ERROR languages: - regex pattern-regex: x11vnc[^\n]*-nopw metadata: ghsa: GHSA-25GX-X37C-7PPH cwe: CWE-306 category: security technology: - x11vnc - novnc - vnc confidence: high likelihood: medium impact: medium references: - https://github.com/openclaw/openclaw/security/advisories/GHSA-25gx-x37c-7pph advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-25GX-X37C-7PPH detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-novnc-x11vnc-missing-auth - id: ghsa-25pw-4h6w-qwvm.openclaw.imessage-group-allowlist-merged-with-pairing-store languages: - typescript severity: ERROR message: DM pairing-store identities are merged into a group allowlist. Group authorization must stay explicit and should not inherit DM pairing-store entries. patterns: - pattern: | const $STORE = await readChannelAllowFromStore(...).catch(() => []); ... const $GROUP = Array.from(new Set([...$GROUPALLOW, ...$STORE])) .map((v) => String(v).trim()) .filter(Boolean); metadata: category: security cwe: CWE-863 ghsa: GHSA-25PW-4H6W-QWVM confidence: high note: Captures the original iMessage vulnerable merge shape exactly and generalizes to same-family explicit merge sites. advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-25PW-4H6W-QWVM detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.imessage-group-allowlist-merged-with-pairing-store - id: ghsa-2prf-9cw7-fq62.whatsapp-reaction-requires-allowfrom-guard message: WhatsApp reaction actions should validate chatJid with resolveWhatsAppOutboundTarget before sendReactionWhatsApp. severity: ERROR languages: - typescript patterns: - pattern-inside: | if ($ACTION === "react") { ... await sendReactionWhatsApp($TARGET, $MSG, $EMOJI, ...) ... } - pattern: | await sendReactionWhatsApp($TARGET, $MSG, $EMOJI, ...) - metavariable-pattern: metavariable: $TARGET language: generic patterns: - pattern-not: $RES.to - pattern-not-inside: | $RES = resolveWhatsAppOutboundTarget({ ..., to: $TARGET, ... }); ... if (!$RES.ok) { ... } ... await sendReactionWhatsApp($RES.to, $MSG, $EMOJI, ...) metadata: category: security cwe: - CWE-862 - CWE-20 ghsa: GHSA-2PRF-9CW7-FQ62 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-2PRF-9CW7-FQ62 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: whatsapp-reaction-requires-allowfrom-guard - id: ghsa-2qj5-gwg2-xwc4.openclaw.prompt-unsanitized-literal-interpolation languages: - typescript - javascript severity: ERROR message: | Untrusted runtime path/URL value flows into a string literal inside a prompt-builder function, without going through sanitizeForPromptLiteral or wrapUntrustedPromptDataBlock. Workspace paths can contain Unicode control / format characters that break LLM prompt structure (CVE-2026-27001 / GHSA-2qj5-gwg2-xwc4). mode: taint pattern-sources: - patterns: - pattern-either: - pattern: $X.workspaceDir - pattern: $X.containerWorkspaceDir - pattern: $X.agentWorkspaceMount - pattern: $X.browserNoVncUrl - pattern: $X.displayWorkspaceDir - pattern: $X.mountPath - pattern: $X.canvasRootDir - pattern: $X.cwd pattern-sanitizers: - patterns: - pattern-either: - pattern: sanitizeForPromptLiteral(...) - pattern: sanitizeForPromptLiterals(...) - pattern: wrapUntrustedPromptDataBlock(...) - patterns: - pattern: $F(...) - metavariable-regex: metavariable: $F regex: ^(sanitize|escape|validate)[A-Z]\w*Prompt\w*$ pattern-sinks: - patterns: - pattern-either: - pattern: | `...${$VALUE}...` - pattern: | "..." + $VALUE + "..." - pattern: | '...' + $VALUE + '...' - pattern-either: - pattern-inside: | function $FN(...) { ... } - pattern-inside: | const $FN = (...) => { ... } - pattern-inside: | export function $FN(...) { ... } - pattern-inside: | export const $FN = (...) => { ... } - metavariable-regex: metavariable: $FN regex: ^(build|render|compose|construct|format)[A-Z]\w*Prompt\w*$ metadata: ghsa: GHSA-2QJ5-GWG2-XWC4 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-2QJ5-GWG2-XWC4 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.prompt-unsanitized-literal-interpolation - id: ghsa-2qrv-rc5x-2g2h.openclaw-untrusted-workspace-channel-shadow-setup languages: - typescript - javascript severity: ERROR mode: taint message: Workspace-aware channel-plugin catalog lookup at channel-setup time reaches a use site without going through resolveTrustedCatalogEntry() or excludeWorkspace:true. Workspace-defined channel shadows could execute during built-in channel setup. See GHSA-2QRV-RC5X-2G2H. metadata: category: security ghsas: - GHSA-2QRV-RC5X-2G2H ghsa: GHSA-2QRV-RC5X-2G2H advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-2QRV-RC5X-2G2H detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-untrusted-workspace-channel-shadow-setup paths: include: - src/commands/channel-setup/*.ts - src/flows/channel-setup.ts - src/commands/channels/add.ts exclude: - "**/*.test.*" - "**/*.spec.*" - src/commands/channel-setup/trusted-catalog.ts pattern-sources: - patterns: - pattern-either: - pattern: getChannelPluginCatalogEntry(...) - pattern: listChannelPluginCatalogEntries(...) - pattern-not-regex: \bexcludeWorkspace\s*:\s*true\b pattern-sanitizers: - patterns: - pattern-either: - pattern: resolveTrustedCatalogEntry(...) - pattern: listTrustedChannelPluginCatalogEntries(...) - pattern: listSetupDiscoveryChannelPluginCatalogEntries(...) pattern-sinks: - patterns: - pattern-either: - pattern: $X.filter(...) - pattern: $X.map(...) - pattern: $X.flatMap(...) - pattern: $X.find(...) - pattern: $X.forEach(...) - pattern: $X.some(...) - pattern: $X.every(...) - pattern: $X.id - pattern: $X.meta - pattern: $X.plugin - pattern: $X[$I] - pattern: return $X; - pattern: new Map($X) - pattern: new Set($X) - id: ghsa-2rgf-hm63-5qph.xff-last-hop-without-trusted-proxy-context languages: - typescript - javascript severity: WARNING message: Review X-Forwarded-For parsers that pick the last header hop directly instead of walking past trusted proxies. metadata: category: security cwe: - CWE-345 - CWE-807 ghsa: GHSA-2RGF-HM63-5QPH advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-2RGF-HM63-5QPH detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: xff-last-hop-without-trusted-proxy-context pattern-either: - patterns: - pattern: | const $ENTRIES = $FORWARDED ?.split(",") .map(($ENTRY) => $MAP) .filter(($FILTER) => $PRED); const $RAW = $ENTRIES?.at(-1); ... return $NORMALIZE($STRIP($RAW)); - patterns: - pattern: | const $HOPS = $FORWARDED ?.split(",") .map(($ENTRY) => $MAP) .filter(($FILTER) => $PRED); ... return $SANITIZE($HOPS[$HOPS.length - 1]); - id: ghsa-2x4x-cc5g-qmmg.node-pair-approve-missing-callerscopes-object languages: - typescript - javascript severity: ERROR message: approveNodePairing on node approval paths should receive an options object that carries callerScopes. patterns: - pattern-either: - pattern: approveNodePairing($REQ) - pattern: approveNodePairing($REQ, undefined, ...) metadata: ghsa: GHSA-2X4X-CC5G-QMMG advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-2X4X-CC5G-QMMG detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: node-pair-approve-missing-callerscopes-object - id: ghsa-3298-56p6-rpw2.openclaw-killprocesstree-from-shell-utils languages: - typescript severity: ERROR message: killProcessTree from agents/shell-utils performs an immediate ungraceful SIGKILL on the entire process tree. Use the killProcessTree from src/process/kill-tree.ts (which sends SIGTERM, waits graceMs, then SIGKILL only if needed). See GHSA-3298-56P6-RPW2. metadata: category: security cwe: - CWE-697 ghsas: - GHSA-3298-56P6-RPW2 ghsa: GHSA-3298-56P6-RPW2 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-3298-56P6-RPW2 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-killprocesstree-from-shell-utils paths: exclude: - "**/*.test.*" - "**/*.spec.*" - src/process/kill-tree.ts pattern-either: - pattern: import { ..., killProcessTree, ... } from "../shell-utils" - pattern: import { ..., killProcessTree, ... } from "./shell-utils" - pattern: import { ..., killProcessTree, ... } from "../agents/shell-utils" - pattern: import { ..., killProcessTree, ... } from "src/agents/shell-utils" - pattern: import { ..., killProcessTree, ... } from "../../agents/shell-utils" - pattern: | export function killProcessTree($PID: number): void { ... process.kill($X, "SIGKILL"); ... } - id: ghsa-33hm-cq8r-wc49.openclaw-sandbox-tmp-accepts-os-tmpdir languages: - typescript - javascript message: Sandbox tmp-path validation trusts any os.tmpdir() path instead of constraining paths to the active sandbox root or OpenClaw-managed temp roots. severity: ERROR patterns: - pattern-either: - pattern: | const $TMP = path.resolve(os.tmpdir()) ... if (!isPathInside($TMP, $RESOLVED)) { return undefined; } ... return $RESOLVED; - pattern: | const $TMP = path.resolve(os.tmpdir()) ... if (!isPathInside($TMP, $ABS)) { return undefined; } ... return $ABS; metadata: category: security cwe: - CWE-22 - CWE-284 ghsa: GHSA-33HM-CQ8R-WC49 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-33HM-CQ8R-WC49 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-sandbox-tmp-accepts-os-tmpdir - id: ghsa-354r-7mfh-7rh2.review-reaction-enqueue-without-dm-access-check languages: - typescript - javascript severity: WARNING message: Reaction handlers that enqueue system events without calling resolveDmGroupAccessWithLists need review for DM authorization parity. paths: include: - src/discord/monitor/listeners.ts - src/slack/monitor/events/reactions.ts patterns: - pattern-either: - pattern: | async function $F(...){ ... enqueueSystemEvent($TEXT, $OPTS) ... } - pattern: | const $F = async (...) => { ... enqueueSystemEvent($TEXT, $OPTS) ... } - pattern-regex: reaction|Reaction|messageReaction|reaction_added|reaction_removed - pattern-not-regex: resolveDmGroupAccessWithLists metadata: ghsa: GHSA-354R-7MFH-7RH2 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-354R-7MFH-7RH2 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: review-reaction-enqueue-without-dm-access-check - id: ghsa-36h3-7c54-j27r.browser-route-tempdir-write-missing-symlink-guard message: Browser route handler writes to a path under the managed temp root without going through resolveWritablePathWithinRoot. The gate is needed to refuse symlink-root and symlink-parent escapes from the temp dir (otherwise an attacker can place a symlink at any directory component and escape the boundary). See GHSA-36H3-7C54-J27R. severity: ERROR languages: - typescript metadata: ghsa: GHSA-36H3-7C54-J27R category: security cwe: - CWE-22 - CWE-59 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-36H3-7C54-J27R detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: browser-route-tempdir-write-missing-symlink-guard paths: include: - extensions/browser/src/browser/routes/output-paths.ts - extensions/browser/src/browser/routes/agent.act*.ts - extensions/browser/src/browser/routes/agent.debug*.ts patterns: - pattern-either: - pattern: fs.mkdir(...) - pattern: fs.mkdirSync(...) - pattern: fsp.mkdir(...) - pattern: fs.createWriteStream(...) - pattern: fs.writeFile(...) - pattern: fsp.writeFile(...) - pattern-not-inside: | import { ..., resolveWritablePathWithinRoot, ... } from "$X"; ... - pattern-not-inside: | import { resolveWritablePathWithinRoot } from "$X"; ... - pattern-not-inside: | import { resolveWritablePathWithinRoot, ... } from "$X"; ... - id: ghsa-39mp-545q-w789.openclaw-owner-only-send-policy-mutation message: Owner-only /send handlers must reject non-owner senders before mutating sessionEntry.sendPolicy. severity: ERROR languages: - typescript - javascript patterns: - pattern-inside: | const $PARSED = parseSendPolicyCommand($CMD); ... - pattern: | if (!$PARAMS.command.isAuthorizedSender) { ... return ...; } ... if ($PARAMS.sessionEntry && $PARAMS.sessionStore && $PARAMS.sessionKey) { ... $MUTATION ... } - metavariable-pattern: metavariable: $MUTATION patterns: - pattern-either: - pattern: $PARAMS.sessionEntry.sendPolicy = $MODE; - pattern: delete $PARAMS.sessionEntry.sendPolicy; - pattern-not-inside: | const $NONOWNER = rejectNonOwnerCommand($PARAMS, "/send"); if ($NONOWNER) { return $NONOWNER; } - pattern-not-inside: | if (!$PARAMS.command.senderIsOwner) { ... return ...; } metadata: ghsa: GHSA-39MP-545Q-W789 category: authorization detector: A coverage_requirement: vulnerable_fix_diff_files review_surface: owner_only_send_policy rationale: catches /send policy mutations guarded only by general authorization advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-39MP-545Q-W789 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-owner-only-send-policy-mutation - id: ghsa-3cw3-5vxw-g2h3.discovery-txt-hint-routing languages: - swift severity: ERROR message: Discovery helpers should not fall back to TXT-derived lanHost or tailnetDns values when building SSH targets or direct gateway URLs. Use resolved service endpoints only. patterns: - pattern-either: - pattern: let host = self.sanitizedTailnetHost($GW.tailnetDns) ?? $GW.lanHost - pattern: let host = sanitizeTailnet($GW.tailnetDns) ?? $GW.lanHost - pattern: guard let lanHost = self.trimmed(lanHost), !lanHost.isEmpty else { return nil } - pattern: let port = gatewayPort ?? 18789 metadata: ghsa: GHSA-3CW3-5VXW-G2H3 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-3CW3-5VXW-G2H3 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: discovery-txt-hint-routing - id: ghsa-3hcm-ggvf-rch5.exec-allowlist-double-quoted-command-substitution languages: - typescript - javascript severity: ERROR message: Shell allowlist parsers that stay in double-quote mode without rejecting command substitution or backticks can approve commands that execute hidden substitutions. patterns: - pattern-either: - patterns: - pattern-inside: | if ($IN_DOUBLE) { ... } - pattern: | if ($CH === "\"") { $IN_DOUBLE = false; } ... $BUF += $CH; - pattern-not: | if ($CH === "$" && $NEXT === "(") { ... } - pattern-not: | if ($CH === "`") { ... } - patterns: - pattern-inside: | if ($IN_DOUBLE) { ... } - pattern: | if ($CH === "\"") { $IN_DOUBLE = false; } else { $BUF += $CH; } - pattern-not: | if ($CH === "$" && $NEXT === "(") { ... } - pattern-not: | if ($CH === "`") { ... } metadata: ghsa: GHSA-3HCM-GGVF-RCH5 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-3HCM-GGVF-RCH5 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: exec-allowlist-double-quoted-command-substitution - id: ghsa-3q42-xmxv-9vfr.openclaw-talk-voice-set-without-admin-scope-check message: Command handlers that persist talk voice config via writeConfigFile should reject gateway-scoped callers lacking operator.admin before writing the config. severity: ERROR languages: - typescript metadata: ghsa: GHSA-3Q42-XMXV-9VFR cwe: CWE-269 detector: A confidence: low category: security advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-3Q42-XMXV-9VFR detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-talk-voice-set-without-admin-scope-check patterns: - pattern: | if ($ACTION === "set") { ... await $RUNTIME.config.writeConfigFile($NEXT) ... } - pattern-not: | if ($ACTION === "set") { ... if (requiresAdminToSetVoice($CTX.channel, $CTX.gatewayClientScopes)) { return ...; } ... await $RUNTIME.config.writeConfigFile($NEXT) ... } - pattern-not: | if ($ACTION === "set") { ... if (! $CTX.gatewayClientScopes?.includes("operator.admin")) { return ...; } ... await $RUNTIME.config.writeConfigFile($NEXT) ... } - id: ghsa-4685-c5cp-vp95.safe-bin-missing-blocked-option-policy languages: - typescript - javascript message: Safe-bin usage validators should reject dangerous sort/grep flags with hasBlockedSafeBinOption before accepting option tokens. severity: ERROR patterns: - pattern-inside: | function isSafeBinUsage(...) { ... } - pattern: | if ($TOKEN.startsWith("-")) { ... } - pattern-not-inside: | if ($TOKEN.startsWith("-")) { if (hasBlockedSafeBinOption($EXEC, $TOKEN)) { ... } ... } metadata: ghsa: GHSA-4685-C5CP-VP95 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-4685-C5CP-VP95 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: safe-bin-missing-blocked-option-policy - id: ghsa-49cg-279w-m73x.approval-auth-empty-approver-authorized languages: - typescript severity: ERROR message: Empty approver lists should stay implicit same-chat fallback; do not return explicit authorized approval auth when approvers.length === 0. patterns: - pattern-inside: | if ($APPROVERS.length === 0) { ... } - pattern-either: - pattern: | return { authorized: true } as const; - pattern: | return { authorized: true }; metadata: category: security confidence: medium technology: - typescript ghsa: GHSA-49CG-279W-M73X advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-49CG-279W-M73X detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: approval-auth-empty-approver-authorized - id: ghsa-4cqv-h74h-93j4.discord-allowlist-name-matching-without-dangerous-opt-in message: Discord allowlist matching uses mutable names/tags without an explicit dangerous opt-in. languages: - typescript - javascript severity: ERROR patterns: - pattern-either: - pattern: | allowListMatches($LIST, $CANDIDATE) - pattern: | resolveDiscordAllowListMatch({ allowList: $LIST, candidate: $CANDIDATE, ..., }) - pattern: | resolveDiscordAllowListMatch({ ..., allowList: $LIST, candidate: $CANDIDATE, }) - pattern-not: | allowListMatches($LIST, $CANDIDATE, { allowNameMatching: ... }) - pattern-not: | resolveDiscordAllowListMatch({ allowList: $LIST, candidate: $CANDIDATE, allowNameMatching: ..., ..., }) - pattern-not: | resolveDiscordAllowListMatch({ ..., allowList: $LIST, candidate: $CANDIDATE, allowNameMatching: ..., }) metadata: family: discord-allowlist-name-matching review: reusable structural rule for missing dangerous opt-in ghsa: GHSA-4CQV-H74H-93J4 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-4CQV-H74H-93J4 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: discord-allowlist-name-matching-without-dangerous-opt-in - id: ghsa-4g5x-2jfc-xm98.raw-fetch-to-disk-bypasses-media-runtime message: Remote media downloads should use the shared bounded media-runtime helpers instead of fetchWithSsrFGuard plus direct response-body-to-disk writes, which bypass core size, cleanup, and inbound-store limits. severity: ERROR languages: - typescript - javascript patterns: - pattern-inside: | async function $F(...){ ... } - pattern: | const { response, release } = await fetchWithSsrFGuard({ ... }); ... await pipeline(Readable.fromWeb($BODY), $WRITESTREAM); ... - pattern-not-inside: | const $FETCHED = await fetchRemoteMedia({ ... }); ... - pattern-not-inside: | await saveMediaBuffer(...) metadata: category: security confidence: medium ghsa: GHSA-4G5X-2JFC-XM98 detector: A advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-4G5X-2JFC-XM98 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: raw-fetch-to-disk-bypasses-media-runtime - id: ghsa-4rj2-gpmh-qq5x.inbound-allowlist-bidirectional-endswith languages: - typescript - javascript severity: ERROR message: Bidirectional endsWith on normalized caller and allowlist values can bypass inbound allowlists. Reject empty caller IDs and compare canonicalized identifiers with strict equality. patterns: - pattern-either: - pattern: | $FROM.endsWith($ALLOW) || $ALLOW.endsWith($FROM) - pattern: | $ALLOW.endsWith($FROM) || $FROM.endsWith($ALLOW) metavariable-comparison: metavariable: $FROM comparison: str($FROM) != str($ALLOW) metadata: category: security confidence: high cwe: CWE-287 ghsa: GHSA-4RJ2-GPMH-QQ5X advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-4RJ2-GPMH-QQ5X detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: inbound-allowlist-bidirectional-endswith - id: ghsa-527m-976r-jf79.browser-existing-session-interaction-missing-navigation-guard message: Existing-session browser interaction routes must call assertExistingSessionPostInteractionNavigationAllowed (or use withBrowserNavigationPolicy) to apply the SSRF navigation guard. Without this gate, click/keyboard/script interactions can navigate to internal IPs / cloud metadata endpoints that the operator hasn't allowed. See GHSA-527M-976R-JF79. severity: ERROR languages: - typescript metadata: ghsa: GHSA-527M-976R-JF79 category: security cwe: - CWE-918 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-527M-976R-JF79 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: browser-existing-session-interaction-missing-navigation-guard paths: include: - extensions/browser/src/browser/routes/agent.act*.ts exclude: - extensions/browser/src/browser/routes/agent.act.hooks.ts patterns: - pattern-either: - pattern: evaluateChromeMcpScript(...) - pattern: clickChromeMcpElement(...) - pattern: typeChromeMcpKeys(...) - pattern-not-inside: | import { ..., assertExistingSessionPostInteractionNavigationAllowed, ... } from "$X"; ... - pattern-not-inside: | import { ..., assertBrowserNavigationResultAllowed, ... } from "$X"; ... - pattern-not-inside: | import { assertBrowserNavigationResultAllowed } from "$X"; ... - id: ghsa-536q-mj95-h29h.openclaw-browser-interaction-navigation-guard languages: - typescript severity: ERROR message: Browser interaction helpers that expose opts.ssrfPolicy and perform press-based actions should route the action through assertInteractionNavigationCompletedSafely so delayed post-action navigations still receive SSRF enforcement. patterns: - pattern-either: - pattern: | export async function $FN(opts: $OPTS) { ... await $PAGE.keyboard.press(...); ... } - pattern: | export async function $FN(opts: $OPTS) { ... await $LOCATOR.press(...); ... } - pattern: opts.ssrfPolicy - pattern-not-inside: | export async function $FN(opts: $OPTS) { ... await assertInteractionNavigationCompletedSafely({ ... }); ... } - pattern-not-inside: | export async function $FN(opts: $OPTS) { ... return await assertInteractionNavigationCompletedSafely({ ... }); ... } metadata: category: security confidence: medium technology: - playwright - browser ghsa: GHSA-536Q-MJ95-H29H advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-536Q-MJ95-H29H detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-browser-interaction-navigation-guard - id: ghsa-56f2-hvwg-5743.openclaw-unguarded-remote-media-fetch message: Remote media fetch should go through the SSRF guard instead of calling fetch directly. severity: ERROR languages: - typescript patterns: - pattern-either: - pattern: | export async function fetchRemoteMedia(...) { ... $RES = await $FETCHER($URL, ...); ... } - pattern: | async function fetchRemoteMedia(...) { ... $RES = await $FETCHER($URL, ...); ... } - metavariable-regex: metavariable: $URL regex: (^url$|^requestUrl$|^mediaUrl$) metadata: cwe: CWE-918 ghsa: GHSA-56F2-HVWG-5743 detector: A advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-56F2-HVWG-5743 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-unguarded-remote-media-fetch - id: ghsa-5mx2-2mgw-x8rm.openclaw-webhook-loopback-passwordless-fallback languages: - typescript severity: ERROR message: Webhook auth falls back to passwordless targets on loopback instead of requiring configured secret matching. pattern: | const $MATCHING = $STRICT.length > 0 ? $STRICT : isDirectLocalLoopbackRequest($REQ) ? $PASSWORDLESS : []; metadata: ghsa: GHSA-5MX2-2MGW-X8RM advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-5MX2-2MGW-X8RM detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-webhook-loopback-passwordless-fallback - id: ghsa-5v6x-rfc3-7qfr.openclaw-system-run-approval-legacy-command-only-binding message: system.run approval matching should bind to exact argv/canonical command data, not legacy command-only text. languages: - typescript - javascript severity: ERROR patterns: - pattern-inside: | function $F(...){ ... } - pattern: | if (!$REQ.systemRunBinding) { return $MISMATCH(...); } - pattern: | return $MATCH({ expected: $REQ.systemRunBinding, actual: $ACTUAL.binding, actualEnvKeys: $ACTUAL.envKeys, }); metadata: confidence: medium ghsa: GHSA-5V6X-RFC3-7QFR detector: A rationale: Requires v1 structured approval binding before matching. advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-5V6X-RFC3-7QFR detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-system-run-approval-legacy-command-only-binding - id: ghsa-5wcw-8jjv-m286.trusted-proxy-accept-without-origin-guard languages: - typescript - javascript message: Trusted-proxy authorization returns success without first applying authorizeTrustedProxyBrowserOrigin. severity: ERROR patterns: - pattern: | if ("user" in $RESULT) { ... return { ok: true, method: "trusted-proxy", user: $RESULT.user }; } - pattern-not: | if ("user" in $RESULT) { ... const $ORIGIN_RESULT = authorizeTrustedProxyBrowserOrigin(...); ... if ($ORIGIN_RESULT) { ... } ... return { ok: true, method: "trusted-proxy", user: $RESULT.user }; } metadata: category: security confidence: medium ghsa: GHSA-5WCW-8JJV-M286 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-5WCW-8JJV-M286 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: trusted-proxy-accept-without-origin-guard - id: ghsa-5xfq-5mr7-426q.openclaw-session-transcript-path-traversal message: Transcript path helper uses unvalidated sessionId or returns raw sessionFile without containment enforcement. severity: WARNING languages: - typescript pattern-either: - pattern: "return candidate ? candidate : resolveSessionTranscriptPath(sessionId, opts?.agentId)" - pattern: return path.join(resolveAgentSessionsDir(agentId), fileName) metadata: category: security cwe: - CWE-22 ghsa: GHSA-5XFQ-5MR7-426Q confidence: low justification: Coverage-first detector for the vulnerable family in pre-fix session transcript path helpers. advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-5XFQ-5MR7-426Q detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-session-transcript-path-traversal - id: ghsa-62f6-mrcj-v8h5.runtime-overrides-unsanitized-override-store languages: - typescript - javascript severity: WARNING message: Runtime override stores should sanitize object values before set-at-path writes to block prototype-reserved keys. patterns: - pattern-inside: | function $F(..., $VALUE, ...) { ... } - pattern: setConfigValueAtPath($TREE, $PATH, $VALUE) - pattern-not: setConfigValueAtPath($TREE, $PATH, sanitizeOverrideValue($VALUE)) - pattern-not: setConfigValueAtPath($TREE, $PATH, sanitizeInput($VALUE)) - metavariable-regex: metavariable: $F regex: ^set.*Override$ metadata: ghsa: GHSA-62F6-MRCJ-V8H5 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-62F6-MRCJ-V8H5 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: runtime-overrides-unsanitized-override-store - id: ghsa-65rx-fvh6-r4h2.openclaw-unquoted-heredoc-body-missing-expansion-token-guard languages: - typescript severity: ERROR message: Heredoc body parsing resets heredocLine after delimiter matching without checking hasUnquotedHeredocExpansionToken() for unquoted heredocs. Shell command substitution in heredoc bodies can bypass exec allowlist analysis. See GHSA-65RX-FVH6-R4H2. metadata: ghsa: GHSA-65RX-FVH6-R4H2 category: security cwe: - CWE-78 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-65RX-FVH6-R4H2 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-unquoted-heredoc-body-missing-expansion-token-guard paths: include: - src/infra/exec-approvals-analysis.ts patterns: - pattern: | if (current) { const line = current.stripTabs ? heredocLine.replace(/^\t+/, "") : heredocLine; if (line === current.delimiter) { pendingHeredocs.shift(); } } heredocLine = ""; - pattern-not: | if (current) { const line = current.stripTabs ? heredocLine.replace(/^\t+/, "") : heredocLine; if (line === current.delimiter) { pendingHeredocs.shift(); } else if (!current.quoted && hasUnquotedHeredocExpansionToken(heredocLine)) { return { ok: false, reason: "command substitution in unquoted heredoc", segments: [] }; } } heredocLine = ""; - id: ghsa-66r7-m7xm-v49h.qqbot-outbound-media-unvalidated-local-path languages: - typescript - javascript severity: ERROR message: QQBot outbound helper resolves local media paths without media-root boundary validation. patterns: - pattern-either: - pattern: | const $MEDIA = resolveQQBotLocalMediaPath(normalizePath(...)); - pattern: | const $MEDIA = resolveQQBotLocalMediaPath($PATH); - pattern-inside: | export async function $FN(...){ ... } - metavariable-regex: metavariable: $FN regex: ^(sendPhoto|sendVoice|sendVideoMsg|sendDocument|sendMedia|sendVoiceMessage)$ - pattern-not-inside: | const $RESOLVED = resolveOutboundMediaPath(...); ... metadata: ghsa: GHSA-66R7-M7XM-V49H advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-66R7-M7XM-V49H detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: qqbot-outbound-media-unvalidated-local-path - id: ghsa-6g25-pc82-vfwp.oauth-state-reuses-pkce-verifier languages: - typescript - javascript message: OAuth state should be generated independently, not reused from the PKCE verifier/codeVerifier. severity: WARNING patterns: - pattern-either: - pattern: | function $F(..., $VERIFIER, ...) { ... new URLSearchParams({ ..., state: $VERIFIER, ... }) ... } - pattern: | function $F(..., $VERIFIER, ...) { ... const $P = new URLSearchParams(...); ... $P.set('state', $VERIFIER) ... } - metavariable-regex: metavariable: $VERIFIER regex: (?i).*(verifier|codeVerifier).* metadata: ghsa: GHSA-6G25-PC82-VFWP advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-6G25-PC82-VFWP detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: oauth-state-reuses-pkce-verifier - id: ghsa-6mqc-jqh6-x8fc.openclaw-canvas-auth-local-direct-bypass message: Canvas/A2UI auth helper allows local-direct requests before bearer-or-capability auth. severity: ERROR languages: - typescript - javascript patterns: - pattern-inside: | async function $F(...){ ... } - pattern-either: - pattern: | if (isLocalDirectRequest($REQ, ...)) { return { ok: true }; } - pattern: | const $LOCAL = isLocalDirectRequest($REQ, ...); ... if ($LOCAL) { return { ok: true }; } metavariable-regex: metavariable: $F regex: authorize.* metadata: ghsa: GHSA-6MQC-JQH6-X8FC advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-6MQC-JQH6-X8FC detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-canvas-auth-local-direct-bypass - id: ghsa-767m-xrhc-fxm7.telegram-target-writeback-admin-scope-required message: Calls to maybePersistResolvedTelegramTarget should propagate gatewayClientScopes so the helper can enforce operator.admin before persisting Telegram target rewrites. severity: ERROR languages: - typescript patterns: - pattern: | maybePersistResolvedTelegramTarget({ ..., rawTarget: $RAW, ..., resolvedChatId: $CHAT, ..., }) - pattern-not: | maybePersistResolvedTelegramTarget({ ..., gatewayClientScopes: $SCOPES, ..., }) metadata: ghsa: GHSA-767M-XRHC-FXM7 detector: A rationale: Structural callsite check for helper invocations that omit gatewayClientScopes, which disables the operator.admin gate inside Telegram target writeback persistence. advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-767M-XRHC-FXM7 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: telegram-target-writeback-admin-scope-required - id: ghsa-77w2-crqv-cmv3.feishu-structured-card-action-envelope-required languages: - typescript - javascript severity: ERROR message: Feishu interactive card buttons that trigger commands or text should use a structured interaction envelope instead of raw text/command callback values. patterns: - pattern-either: - pattern: | { ..., tag: "button", ..., value: { command: $CMD, ... }, ..., } - pattern: | { ..., tag: "button", ..., value: { text: $TXT, ... }, ..., } paths: include: - "**/*.ts" - "**/*.js" metadata: ghsa: GHSA-77W2-CRQV-CMV3 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-77W2-CRQV-CMV3 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: feishu-structured-card-action-envelope-required - id: ghsa-782p-5fr5-7fj8.channel-metadata-into-trusted-system-prompt languages: - typescript severity: WARNING message: Untrusted channel metadata is being interpolated into trusted GroupSystemPrompt parts. Route it through UntrustedContext instead. pattern-either: - pattern: | const $SYSTEM_PROMPT_PARTS = [ ..., $CHANNEL_DESC ? `Channel description: ${$CHANNEL_DESC}` : null, ..., ].filter(($ENTRY) => Boolean($ENTRY)); - pattern: | const $SYSTEM_PROMPT_PARTS = [ ..., $CHANNEL_DESC ? `Channel topic: ${$CHANNEL_DESC}` : null, ..., ].filter(($ENTRY) => Boolean($ENTRY)); - pattern: | const $SYSTEM_PROMPT_PARTS = [ ..., $CHANNEL_DESC ? `Forum topic: ${$CHANNEL_DESC}` : null, ..., ].filter(($ENTRY) => Boolean($ENTRY)); metadata: ghsa: GHSA-782P-5FR5-7FJ8 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-782P-5FR5-7FJ8 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: channel-metadata-into-trusted-system-prompt - id: ghsa-796m-2973-wc5q.env-wrapper-transparent-unwrap languages: - typescript - javascript severity: WARNING message: env dispatch-wrapper handling unwraps env invocations without a semantic-modifier guard. Review whether env assignments or env -S/--split-string can change runtime behavior and bypass policy expectations. patterns: - pattern-either: - pattern: | case "env": return unwrapDispatchWrapper($WRAPPER, unwrapEnvInvocation($ARGV)); - pattern: | if ($WRAP == "env") { return unwrapEnvInvocation($ARGV); } metadata: ghsa: GHSA-796M-2973-WC5Q advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-796M-2973-WC5Q detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: env-wrapper-transparent-unwrap - id: ghsa-7fcc-cw49-xm78.windows-shell-fallback-after-spawn-error message: Windows spawn retry logic that reruns the same operation with shell=true after ENOENT/EINVAL wrapper failures can turn argv into shell-interpreted command text. severity: ERROR languages: - typescript - javascript patterns: - pattern-either: - pattern: | if (process.platform === "win32" && ($ERR.code === "EINVAL" || $ERR.code === "ENOENT")) { ... return await $RUN(..., true); } - pattern: | if (process.platform === "win32" && ($ERR.code === "ENOENT" || $ERR.code === "EINVAL")) { ... return await $RUN(..., true); } - pattern: | if (process.platform === "win32" && $CHECK($ERR)) { ... return await $RUN(..., true); } - pattern: | if (process.platform === "win32" && $RETRYABLE) { ... return await $RUN(..., true); } - pattern: | if (process.platform === "win32") { ... if ($CHECK($ERR)) { ... return await $RUN(..., true); } } - pattern-either: - pattern-inside: | function $CHECK($ERR) { ... return $CODE === "EINVAL" || $CODE === "ENOENT"; } ... - pattern-inside: | function $CHECK($ERR) { ... return $CODE === "ENOENT" || $CODE === "EINVAL"; } ... - pattern-inside: | const $RETRYABLE = $ERR && ($ERR.code === "ENOENT" || $ERR.code === "EINVAL"); ... - pattern-inside: | const $RETRYABLE = $ERR && ($ERR.code === "EINVAL" || $ERR.code === "ENOENT"); ... metadata: ghsa: GHSA-7FCC-CW49-XM78 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-7FCC-CW49-XM78 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: windows-shell-fallback-after-spawn-error - id: ghsa-7ggg-pvrf-458v.openclaw-host-exec-python-index-override message: Request-scoped host exec env overrides include Python package index redirect variables (PIP_*_INDEX, UV_*_INDEX) that can reroute package downloads. languages: - typescript - javascript severity: ERROR patterns: - pattern-either: - pattern: | sanitizeHostExecEnv({ ..., overrides: { ..., PIP_INDEX_URL: $VALUE, ... }, ... }) - pattern: | sanitizeHostExecEnv({ ..., overrides: { ..., PIP_PYPI_URL: $VALUE, ... }, ... }) - pattern: | sanitizeHostExecEnv({ ..., overrides: { ..., PIP_EXTRA_INDEX_URL: $VALUE, ... }, ... }) - pattern: | sanitizeHostExecEnv({ ..., overrides: { ..., UV_INDEX: $VALUE, ... }, ... }) - pattern: | sanitizeHostExecEnv({ ..., overrides: { ..., UV_INDEX_URL: $VALUE, ... }, ... }) - pattern: | sanitizeHostExecEnv({ ..., overrides: { ..., UV_DEFAULT_INDEX: $VALUE, ... }, ... }) - pattern: | sanitizeHostExecEnv({ ..., overrides: { ..., UV_EXTRA_INDEX_URL: $VALUE, ... }, ... }) - pattern: | sanitizeHostExecEnvWithDiagnostics({ ..., overrides: { ..., PIP_INDEX_URL: $VALUE, ... }, ... }) - pattern: | sanitizeHostExecEnvWithDiagnostics({ ..., overrides: { ..., PIP_PYPI_URL: $VALUE, ... }, ... }) - pattern: | sanitizeHostExecEnvWithDiagnostics({ ..., overrides: { ..., PIP_EXTRA_INDEX_URL: $VALUE, ... }, ... }) - pattern: | sanitizeHostExecEnvWithDiagnostics({ ..., overrides: { ..., UV_INDEX: $VALUE, ... }, ... }) - pattern: | sanitizeHostExecEnvWithDiagnostics({ ..., overrides: { ..., UV_INDEX_URL: $VALUE, ... }, ... }) - pattern: | sanitizeHostExecEnvWithDiagnostics({ ..., overrides: { ..., UV_DEFAULT_INDEX: $VALUE, ... }, ... }) - pattern: | sanitizeHostExecEnvWithDiagnostics({ ..., overrides: { ..., UV_EXTRA_INDEX_URL: $VALUE, ... }, ... }) metadata: ghsa: GHSA-7GGG-PVRF-458V advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-7GGG-PVRF-458V detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-host-exec-python-index-override - id: ghsa-7h7g-x2px-94hj.openclaw-setup-bootstrap-issued-with-profile-argument message: Pairing setup code should issue bootstrap tokens with a dedicated profile object, not ad hoc role/scopes arguments. severity: WARNING languages: - typescript patterns: - pattern-either: - pattern: | return { ..., payload: { ..., bootstrapToken: (await issueDeviceBootstrapToken({ baseDir: $DIR, role: $ROLE, scopes: $SCOPES, })).token, ... }, ... } - pattern: | $ISSUED = await issueDeviceBootstrapToken({ baseDir: $DIR, role: $ROLE, scopes: $SCOPES, }) ... return { ..., payload: { ..., bootstrapToken: $ISSUED.token, ... }, ... } metadata: ghsa: GHSA-7H7G-X2PX-94HJ advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-7H7G-X2PX-94HJ detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-setup-bootstrap-issued-with-profile-argument - id: ghsa-7jp6-r74r-995q.openclaw-matrix-set-profile-missing-owner-guard languages: - typescript severity: WARNING message: Matrix set-profile action dispatches without checking senderIsOwner. See GHSA-7JP6-R74R-995Q. metadata: ghsa: GHSA-7JP6-R74R-995Q category: security cwe: - CWE-862 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-7JP6-R74R-995Q detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-matrix-set-profile-missing-owner-guard paths: include: - extensions/matrix/src/actions.ts - src/agents/tools/matrix-actions.ts patterns: - pattern: | dispatch({ action: "setProfile", ... }) - pattern-not-inside: | if (ctx.senderIsOwner !== true) { ... } ... - id: ghsa-7qf6-h84j-8fq4.msteams-safe-fetch-missing-resolvefn languages: - typescript severity: ERROR message: MS Teams attachment callers that rely on safeFetch/safeFetchWithPolicy should pass resolveFn so each hostname/redirect hop gets DNS/IP validation instead of only hostname allowlist checks. patterns: - pattern-either: - pattern: | safeFetch({ ... }) - pattern: | safeFetchWithPolicy({ ... }) - pattern-not: | safeFetch({ ..., resolveFn: $RESOLVER, ..., }) - pattern-not: | safeFetchWithPolicy({ ..., resolveFn: $RESOLVER, ..., }) - pattern-not-inside: | describe(...) - pattern-not-inside: | it(...) - pattern-not-inside: | test(...) - pattern-not-inside: | expect(...) metadata: ghsa: GHSA-7QF6-H84J-8FQ4 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-7QF6-H84J-8FQ4 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: msteams-safe-fetch-missing-resolvefn - id: ghsa-7rcp-mxpq-72pj.oauth-manual-callback-code-only-acceptance message: Manual OAuth callback parsing should not accept bare authorization codes because that bypasses CSRF state validation. severity: ERROR languages: - typescript - javascript patterns: - pattern: | catch { ... return { code: $CODE, state: $EXPECTED }; } metadata: category: security cwe: CWE-352 ghsa: GHSA-7RCP-MXPQ-72PJ rationale: Detects catch blocks in OAuth callback parsers that fabricate a matching state while accepting non-URL code-only input. advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-7RCP-MXPQ-72PJ detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: oauth-manual-callback-code-only-acceptance - id: ghsa-7wv4-cc7p-jhxc.openclaw.workspace-dotenv-runtime-guard-incomplete languages: - typescript - javascript severity: WARNING message: Workspace .env runtime-control blocklist looks incomplete. Guard helpers should block OPENCLAW_GATEWAY_URL/PORT, OPENCLAW_UPDATE_*, OPENCLAW_SKIP_*, and ClawHub/browser-control variables, not just auth keys and _BASE_URL redirects. patterns: - pattern-either: - pattern: | const BLOCKED_WORKSPACE_DOTENV_KEYS = new Set([...]); - pattern: | const BLOCKED_WORKSPACE_DOTENV_KEYS = new Set([...,]); - pattern-not-regex: OPENCLAW_GATEWAY_URL - pattern-not-regex: OPENCLAW_GATEWAY_PORT - pattern-not-regex: OPENCLAW_BROWSER_EXECUTABLE_PATH - pattern-not-regex: OPENCLAW_SKIP_ - pattern-not-regex: OPENCLAW_UPDATE_ - pattern-not-regex: OPENCLAW_CLAWHUB_ - pattern-not-regex: CLAWHUB_ metadata: ghsa: GHSA-7WV4-CC7P-JHXC advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-7WV4-CC7P-JHXC detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.workspace-dotenv-runtime-guard-incomplete - id: ghsa-7xmq-g46g-f8pv.openclaw-sandbox-media-deferred-path-read message: Sandbox media flows should use root-scoped read helpers at use time instead of deferring to raw bridge/fs pathname reads. severity: WARNING languages: - typescript - javascript metadata: category: security ghsa: GHSA-7XMQ-G46G-F8PV detector: A advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-7XMQ-G46G-F8PV detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-sandbox-media-deferred-path-read pattern-either: - patterns: - pattern: | $RES = await resolveSandboxedBridgeMediaPath(...); ... await loadWebMedia($RES.resolved, { ..., sandboxValidated: true, readFile: (filePath) => $BRIDGE.readFile({ filePath, cwd: $ROOT }), ..., }); - pattern-not: | $RES = await resolveSandboxedBridgeMediaPath(...); ... await loadWebMedia($RES.resolved, { ..., sandboxValidated: true, readFile: createSandboxBridgeReadFile(...), ..., }); - patterns: - pattern: | return { ..., sandboxValidated: true, readFile: (filePath: string) => fs.readFile(filePath), ..., }; - pattern-not: | return { ..., sandboxValidated: true, readFile: createRootScopedReadFile(...), ..., }; - id: ghsa-82g8-464f-2mv7.openclaw-skill-env-host-injection languages: - typescript - javascript message: Skill env overrides are copied into process.env without host-env safety sanitization. severity: ERROR patterns: - pattern-either: - pattern: | for (const [$KEY, $VALUE] of Object.entries($ENV)) { ... process.env[$KEY] = $VALUE; ... } - pattern: | for (const [$KEY, $VALUE] of Object.entries($ENV)) { ... $UPDATES.push({ key: $KEY, ... }); ... process.env[$KEY] = $VALUE; ... } - pattern-not-inside: | const $SANITIZED = sanitizeSkillEnvOverrides(...); ... - pattern-not-inside: | const $SANITIZED = sanitizeEnvVars(...); ... metadata: ghsa: GHSA-82G8-464F-2MV7 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-82G8-464F-2MV7 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-skill-env-host-injection - id: ghsa-846p-hgpv-vphc.qqbot-outbound-local-read-without-boundary-check message: QQ Bot outbound local media handling reads a user-influenced path after resolveQQBotLocalMediaPath() without resolveOutboundMediaPath()/resolveQQBotPayloadLocalFilePath() boundary enforcement. severity: ERROR languages: - typescript - javascript patterns: - pattern-either: - pattern: | $MP = resolveQQBotLocalMediaPath(normalizePath($RAW)); ... readFileAsync($MP) - pattern: | $MP = resolveQQBotLocalMediaPath(normalizePath($RAW)); ... audioFileToSilkBase64($MP, ...) - pattern: | $MP = resolveQQBotLocalMediaPath(normalizePath($RAW)); ... checkFileSize($MP) - pattern-not: | $RES = resolveOutboundMediaPath($RAW, ..., ...) ... - pattern-not: | $SAFE = resolveQQBotPayloadLocalFilePath($MP) ... - pattern-not: | if (!resolveQQBotPayloadLocalFilePath($MP)) { ... } metadata: category: security technology: - qqbot confidence: medium ghsa: GHSA-846P-HGPV-VPHC advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-846P-HGPV-VPHC detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: qqbot-outbound-local-read-without-boundary-check - id: ghsa-8689-gm9g-jgr6.plivo-v3-replay-key-uses-unsorted-url languages: - typescript - javascript severity: ERROR message: Plivo V3 replay keys should be derived from the same canonicalized URL+params base used for signature verification, not from the raw verification URL string. patterns: - pattern-inside: | if ($SIG && $NONCE) { ... } - pattern-either: - pattern: | $REPLAY = `plivo:v3:${sha256Hex(`${$URL}\n${$NONCE}`)}` - pattern: | $REPLAY = "plivo:v3:" + sha256Hex($URL + "\n" + $NONCE) - pattern: | $REPLAY = "plivo:v3:" + sha256Hex(`${$URL}\n${$NONCE}`) - metavariable-regex: metavariable: $URL regex: .*(url|verificationUrl|requestUrl|webhookUrl).* metadata: category: security confidence: medium ghsa: GHSA-8689-GM9G-JGR6 detector: A advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-8689-GM9G-JGR6 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: plivo-v3-replay-key-uses-unsorted-url - id: ghsa-8cp7-rp8r-mg77.ipv6-transition-special-use-ssrf-guard-bypass message: Security-sensitive hostname/IP guard composes isBlockedHostname with isPrivateIpAddress instead of routing through the shared isBlockedHostnameOrIp classifier. Review for missed IPv6 transition encodings such as ISATAP, NAT64, 6to4, or Teredo. severity: ERROR languages: - typescript - javascript patterns: - pattern: isBlockedHostname($HOST) - pattern-not: isBlockedHostnameOrIp($HOST) - pattern-not-inside: | function canFetch(...) { ... } metadata: cwe: CWE-918 ghsa: GHSA-8CP7-RP8R-MG77 detector_kind: reusable-opengrep advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-8CP7-RP8R-MG77 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: ipv6-transition-special-use-ssrf-guard-bypass - id: ghsa-8fmp-37rc-p5g7.openclaw-service-env-merges-unfiltered-dotenv-or-config-env languages: - typescript - javascript severity: WARNING message: Untrusted config/.env environment variables are merged directly into a managed service environment. Filter startup-control keys (for example NODE_OPTIONS, LD_*, DYLD_*) before embedding them in LaunchAgent/systemd/Scheduled Task environments. metadata: category: security ghsa: GHSA-8FMP-37RC-P5G7 cwe: CWE-15 detector: A advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-8FMP-37RC-P5G7 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-service-env-merges-unfiltered-dotenv-or-config-env patterns: - pattern-either: - pattern: | const $ENV = { ...$SOURCE, ...$REST }; - pattern: | const $ENV = { ...$PREFIX, ...$SOURCE, ...$REST }; - metavariable-pattern: metavariable: $SOURCE patterns: - pattern-either: - pattern: readStateDirDotEnvVars(...) - pattern: collectConfigEnvVars(...) - pattern: collectConfigServiceEnvVars(...) - pattern: collectConfigRuntimeEnvVars(...) - pattern-not-inside: | const $SANITIZED = sanitizeHostExecEnvWithDiagnostics(...); ... - pattern-not-inside: | const $SAFE = sanitizeServiceEnvVars(...); ... - id: ghsa-8jpq-5h99-ff5r.ghsa-8jpq-local-path-media-send languages: - typescript - javascript severity: ERROR message: Media-send code should not use a local-path classifier to read attacker-controlled paths directly from disk while fetching the same input in the remote branch. patterns: - pattern-either: - pattern: | if ($ISLOCAL($INPUT)) { ... return $FS.readFileSync($PATH); } else { ... $RESPONSE = await fetch($INPUT, ...); ... } - pattern: | if ($ISLOCAL($INPUT)) { ... $DATA = $FS.readFileSync($PATH); ... } else { ... $RESPONSE = await fetch($INPUT, ...); ... } - pattern: | if ($ISLOCAL($INPUT)) { ... return await $FS.readFile($PATH); } ... $RESPONSE = await fetch($INPUT, ...); ... - pattern: | if ($ISLOCAL($INPUT)) { ... $DATA = await $FS.readFile($PATH); ... } ... $RESPONSE = await fetch($INPUT, ...); ... metadata: ghsa: GHSA-8JPQ-5H99-FF5R advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-8JPQ-5H99-FF5R detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: ghsa-8jpq-local-path-media-send - id: ghsa-8mf7-vv8w-hjr2.openclaw.safebin-profile-lookup-permissive-fallback languages: - typescript - javascript severity: ERROR message: | A safe-bin profile lookup is using a `??` or `||` permissive fallback. The lookup must fail closed: if the binary is missing a profile, deny the call (require user approval) — not allow it with a generic profile. See GHSA-8MF7-VV8W-HJR2. metadata: category: security cwe: - CWE-276 - CWE-77 ghsas: - GHSA-8MF7-VV8W-HJR2 ghsa: GHSA-8MF7-VV8W-HJR2 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-8MF7-VV8W-HJR2 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.safebin-profile-lookup-permissive-fallback paths: include: - src/infra/exec-safe-bin-policy*.ts - src/infra/exec-approvals*.ts - src/infra/exec-allowlist*.ts - src/agents/bash-tools.exec*.ts pattern-either: - patterns: - pattern-either: - pattern: $PROFILES[$NAME] ?? $FALLBACK - pattern: $PROFILES[$NAME] || $FALLBACK - metavariable-regex: metavariable: $PROFILES regex: ^(safeBinProfiles|SAFE_BIN_PROFILES|profiles)$ - patterns: - pattern: $X.$PROFILES[$NAME] ?? $FALLBACK - metavariable-regex: metavariable: $PROFILES regex: ^(safeBinProfiles|SAFE_BIN_PROFILES|profiles)$ - id: ghsa-92jp-89mq-4374.openclaw-browser-bridge-preauth-helper-route message: Privileged browser bridge helper route is registered before auth middleware, so helper access can bypass bridge auth. severity: ERROR languages: - typescript - javascript patterns: - pattern-inside: | export async function $F(...){ ... } - pattern: | app.get($ROUTE, ...) - metavariable-regex: metavariable: $ROUTE regex: ^["'`](?:/sandbox/novnc|/[^"'`]*(?:helper|observer|novnc)[^"'`]*)["'`]$ - pattern-not-inside: | export async function $F(...){ ... installBrowserAuthMiddleware(app, ...) ... app.get($ROUTE, ...) ... } - pattern-not: | app.get($ROUTE, ($REQ, $RES) => { if (!hasVerifiedBrowserAuth($REQ)) { ... } ... }) metadata: category: security technology: - express confidence: medium ghsa: GHSA-92JP-89MQ-4374 rationale: Helper routes like noVNC observer/token redemption should not be reachable before bridge auth is established. advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-92JP-89MQ-4374 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-browser-bridge-preauth-helper-route - id: ghsa-94pw-c6m8-p9p9.openclaw-gateway-config-mutation-guard-missing-dangerous-flag-diff languages: - typescript severity: ERROR message: assertGatewayConfigMutationAllowed() does not compare dangerous config flags using collectEnabledInsecureOrDangerousFlags(). Gateway config.apply/config.patch can otherwise enable dangerous settings through a write-scoped gateway tool. See GHSA-94PW-C6M8-P9P9. metadata: ghsa: GHSA-94PW-C6M8-P9P9 category: security cwe: - CWE-266 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-94PW-C6M8-P9P9 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-gateway-config-mutation-guard-missing-dangerous-flag-diff paths: include: - src/agents/tools/gateway-tool.ts patterns: - pattern: | function assertGatewayConfigMutationAllowed($PARAMS: $TYPE) { ... } - pattern-not: | function assertGatewayConfigMutationAllowed($PARAMS: $TYPE) { ... collectEnabledInsecureOrDangerousFlags(...) ... } - id: ghsa-9528-x887-j2fp.openclaw-webhook-signature-missing-auth-rate-limit languages: - typescript severity: WARNING message: Shared-secret webhook verification does not record auth-rate-limit failure on invalid signature. See GHSA-9528-X887-J2FP. metadata: ghsa: GHSA-9528-X887-J2FP category: security cwe: - CWE-307 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-9528-X887-J2FP detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-webhook-signature-missing-auth-rate-limit paths: include: - extensions/nextcloud-talk/src/monitor.ts - extensions/**/src/**/monitor*.ts patterns: - pattern: verifyNextcloudTalkSignature(...) - pattern-not-inside: | ... verifyNextcloudTalkSignature(...) ... $LIM.recordFailure(...) ... - id: ghsa-98ch-45wp-ch47.openclaw.system-run-approval-binding-portable-normalization-regression languages: - typescript severity: ERROR message: normalizeEnvVarKey with portable:true in system-run-approval-binding.ts instead of normalizeHostOverrideEnvVarKey causes approval-integrity gap. See GHSA-98CH-45WP-CH47. metadata: category: security cwe: - CWE-178 ghsas: - GHSA-98CH-45WP-CH47 ghsa: GHSA-98CH-45WP-CH47 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-98CH-45WP-CH47 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.system-run-approval-binding-portable-normalization-regression paths: include: - src/infra/system-run-approval-binding.ts pattern: "normalizeEnvVarKey($KEY, { portable: true })" - id: ghsa-98hh-7ghg-x6rq.approval-resolve-call-review languages: - typescript - javascript message: Review approval resolution call sites for missing channel-specific approver authorization. severity: WARNING pattern-either: - pattern: | await callApprovalMethod("exec.approval.resolve"); - pattern: | await callApprovalMethod("plugin.approval.resolve"); metadata: category: security ghsa: GHSA-98HH-7GHG-X6RQ detector: A note: Reusable review surface for approval-resolution entrypoints; authorization must be verified manually. advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-98HH-7GHG-X6RQ detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: approval-resolve-call-review - id: ghsa-9jpj-g8vv-j5mf.oauth-state-reuses-pkce-verifier languages: - typescript - javascript severity: ERROR message: OAuth state should be generated independently and must not reuse PKCE verifier material. patterns: - pattern-either: - pattern: | new URLSearchParams({ ..., state: $PKCE.verifier, ..., }) - pattern: | new URLSearchParams({ ..., state: verifier, ..., }) - pattern: | buildAuthUrl(..., $PKCE.verifier, ...) - pattern: | buildAuthUrl(..., verifier, ...) metadata: category: security confidence: medium rationale: Detects OAuth flows that directly reuse PKCE verifier material as the OAuth state token. ghsa: GHSA-9JPJ-G8VV-J5MF advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-9JPJ-G8VV-J5MF detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: oauth-state-reuses-pkce-verifier - id: ghsa-9q7v-8mr7-g23p.openclaw.marketplace-plugin-download-unguarded-fetch languages: - typescript severity: WARNING message: | In src/plugins/marketplace.ts, a raw fetch() is used for a marketplace archive URL without going through fetchWithSsrFGuard. A compromised marketplace server could return a URL pointing to internal network services (RFC1918, cloud metadata). Use fetchWithSsrFGuard({ url: archiveUrl, auditContext: "marketplace-plugin-download" }). See GHSA-9Q7V-8MR7-G23P. metadata: category: security cwe: - CWE-918 ghsas: - GHSA-9Q7V-8MR7-G23P ghsa: GHSA-9Q7V-8MR7-G23P advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-9Q7V-8MR7-G23P detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.marketplace-plugin-download-unguarded-fetch paths: include: - src/plugins/marketplace.ts - src/plugins/marketplace-*.ts - src/plugins/plugin-download*.ts patterns: - pattern: fetch($URL, ...) - pattern-not: fetchWithSsrFGuard(...) - pattern-not-inside: | fetchWithSsrFGuard(...) - id: ghsa-9wqx-g2cw-vc7r.matrix-verification-notice-missing-dm-access-gate message: sendVerificationNotice is called from a Matrix verification file that does not import resolveMatrixMonitorAccessState — the DM access policy check needed to gate verification notices is missing. Verification notices must be gated on DM access policy or they leak the bot's verification state to non-allowed peers. See GHSA-9WQX-G2CW-VC7R. severity: ERROR languages: - typescript metadata: ghsa: GHSA-9WQX-G2CW-VC7R category: authorization cwe: - CWE-863 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-9WQX-G2CW-VC7R detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: matrix-verification-notice-missing-dm-access-gate paths: include: - extensions/matrix/src/matrix/monitor/verification-*.ts patterns: - pattern: sendVerificationNotice(...) - pattern-not-inside: | import { ..., resolveMatrixMonitorAccessState, ... } from "$X"; ... - pattern-not-inside: | import { resolveMatrixMonitorAccessState } from "$X"; ... - pattern-not-inside: | import { resolveMatrixMonitorAccessState, ... } from "$X"; ... - id: ghsa-cg6c-q2hx-69h7.plivo-v2-replay-key-uses-full-verification-url message: Plivo V2 replay keys should be derived from the signed base URL without the query string; hashing the full verification URL lets query-only variants mint fresh verifiedRequestKey values. severity: ERROR languages: - typescript - javascript patterns: - pattern-either: - pattern: | const $KEY = `plivo:v2:${sha256Hex(`${$URL}\n${$NONCE}`)}` - pattern: | const $KEY = "plivo:v2:" + $HASH(`${$URL}\n${$NONCE}`) - metavariable-regex: metavariable: $URL regex: ^(verificationUrl|url)$ metadata: ghsa: GHSA-CG6C-Q2HX-69H7 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-CG6C-Q2HX-69H7 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: plivo-v2-replay-key-uses-full-verification-url - id: ghsa-chm2-m3w2-wcxm.googlechat-users-email-allowlist-mutable-principal languages: - typescript - javascript severity: WARNING message: Google Chat allowlists should not treat users/ entries as email matches; that mixes a mutable email principal into a users/ identity slot. patterns: - pattern-either: - pattern: | $EMAIL && $ENTRY.replace(/^users\//i, "") === $EMAIL - pattern: | $ENTRY.startsWith("users/") && $EMAIL && $ENTRY.slice("users/".length) === $EMAIL - metavariable-regex: metavariable: $EMAIL regex: .*[Ee]mail.* metadata: ghsa: GHSA-CHM2-M3W2-WCXM advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-CHM2-M3W2-WCXM detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: googlechat-users-email-allowlist-mutable-principal - id: ghsa-cv7m-c9jx-vg7q.openclaw-browser-upload-raw-paths-forwarded message: Browser upload/file-chooser code forwards caller-controlled `paths` directly. Upload paths must first be resolved under DEFAULT_UPLOAD_DIR and then forwarded as validated/resolved paths. Raw paths can read arbitrary local files from the Gateway host. See GHSA-CV7M-C9JX-VG7Q. languages: - typescript severity: ERROR metadata: ghsa: GHSA-CV7M-C9JX-VG7Q category: security cwe: - CWE-22 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-CV7M-C9JX-VG7Q detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-browser-upload-raw-paths-forwarded paths: include: - src/agents/tools/browser-tool.ts - src/browser/routes/agent.act.ts - extensions/browser/src/browser/routes/**/*.ts - extensions/browser/src/browser/pw-tools-core.interactions.ts pattern-regex: ^\s*paths\s*,\s*$ - id: ghsa-cwf8-44x6-32c2.openclaw-openshell-uploadpath-direct-localpath-upload languages: - typescript severity: ERROR message: uploadPathToRemote() passes localPath directly to `openshell sandbox upload`. Uploads must use a symlink-free staged snapshot (tmpDir from stageDirectoryContents) before syncing into the remote sandbox. See GHSA-CWF8-44X6-32C2. metadata: ghsa: GHSA-CWF8-44X6-32C2 category: security cwe: - CWE-22 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-CWF8-44X6-32C2 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-openshell-uploadpath-direct-localpath-upload paths: include: - extensions/openshell/src/backend.ts pattern-regex: private async uploadPathToRemote[\s\S]*?"sandbox",[\s\S]*?"upload",[\s\S]*?localPath,[\s\S]*?remotePath, - id: ghsa-cwq8-6f96-g3q4.openclaw-install-scan-fail-open languages: - typescript - javascript severity: ERROR message: Install flow catches install-source scan failures and continues into an install/write path instead of blocking. metadata: category: security cwe: - CWE-636 - CWE-754 ghsa: GHSA-CWQ8-6F96-G3Q4 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-CWQ8-6F96-G3Q4 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-install-scan-fail-open patterns: - pattern-either: - pattern: | try { ... const $SCAN_RESULT = await $SCAN(...); ... } catch ($ERR) { ... $LOGGER.warn(...); ... } ... return await $INSTALL(...); - pattern: | try { ... await $SCAN(...); ... } catch ($ERR) { ... $LOGGER.warn(...); ... } ... return await $INSTALL(...); - pattern: | try { ... const $SCAN_RESULT = await $SCAN(...); ... } catch ($ERR) { ... $LOGGER.warn(...); ... } ... return $INSTALL(...); - pattern: | try { ... await $SCAN(...); ... } catch ($ERR) { ... $LOGGER.warn(...); ... } ... return $INSTALL(...); - metavariable-regex: metavariable: $SCAN regex: ^(runtime\.)?scan[A-Za-z0-9_]*InstallSource(Runtime)?$ - metavariable-regex: metavariable: $INSTALL regex: ^(install|write|copy|proceed)[A-Za-z0-9_]* - id: ghsa-cxpw-2g23-2vgw.acp-extract-text-from-prompt-without-size-limit languages: - typescript message: ACP prompt handlers should pass an explicit byte limit into extractTextFromPrompt before forwarding the assembled message to chat.send. severity: ERROR pattern-regex: (?s)async\s+prompt\s*\([^)]*\)\s*[:{][\s\S]*?extractTextFromPrompt\s*\([^,)]*\)(?!\s*,) metadata: ghsa: GHSA-CXPW-2G23-2VGW cwe: - CWE-20 - CWE-400 category: security technology: - openclaw - acp advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-CXPW-2G23-2VGW detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: acp-extract-text-from-prompt-without-size-limit - id: ghsa-f5mf-3r52-r83w.zalouser-dangerous-group-name-auth-match message: Group authorization candidates include mutable group name or slug values without an explicit opt-in, which can let authorization depend on attacker-controlled naming instead of stable ids. severity: ERROR languages: - typescript - javascript patterns: - pattern-either: - pattern: | buildZalouserGroupCandidates({ ..., groupName: $GROUP_NAME, ..., }) - pattern: | buildZalouserGroupCandidates({ ..., groupChannel: $GROUP_CHANNEL, ..., }) - pattern-not: | buildZalouserGroupCandidates({ ..., allowNameMatching: $ALLOW, ..., }) - pattern-not-inside: | if (isZalouserDangerousNameMatchingEnabled(...)) { ... } - pattern-not-inside: | const $FLAG = isZalouserDangerousNameMatchingEnabled(...); ... buildZalouserGroupCandidates({ ..., allowNameMatching: $FLAG, ..., }) metadata: ghsa: GHSA-F5MF-3R52-R83W advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-F5MF-3R52-R83W detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: zalouser-dangerous-group-name-auth-match - id: ghsa-f7fh-qg34-x2xh.openclaw-direct-cdp-websocket-top-level-branch-missing-validation languages: - typescript - javascript severity: ERROR message: createTargetViaCdp() has a top-level direct WebSocket branch that assigns opts.cdpUrl to wsUrl without validating it first. Direct CDP ws:// targets must be checked with assertCdpEndpointAllowed() to prevent second-hop SSRF. See GHSA-F7FH-QG34-X2XH. metadata: ghsa: GHSA-F7FH-QG34-X2XH category: security cwe: - CWE-918 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-F7FH-QG34-X2XH detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-direct-cdp-websocket-top-level-branch-missing-validation paths: include: - extensions/browser/src/browser/cdp.ts pattern-regex: (?m)^\s*if\s*\(isWebSocketUrl\(opts\.cdpUrl\)\)\s*\{(?:\n\s*//[^\n]*)?\n\s*wsUrl\s*=\s*opts\.cdpUrl\s*; - id: ghsa-fg3m-vhrr-8gj6.windows-shell-fallback-retry languages: - typescript - javascript severity: ERROR message: Windows retry logic that converts wrapper-launch errors into shell execution can reinterpret argv via cmd.exe. Prefer fail-closed wrapper resolution. patterns: - pattern-either: - pattern: | if (process.platform === "win32" && $CHECK($ERR)) { ... return await $RUN(..., true); } - pattern: | if (process.platform === "win32" && $CODE && $SET.has($CODE)) { ... return await $RUN(..., true); } metadata: ghsa: GHSA-FG3M-VHRR-8GJ6 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-FG3M-VHRR-8GJ6 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: windows-shell-fallback-retry - id: ghsa-fh3f-q9qw-93j9.sandbox-config-sha1-hash message: Security-sensitive sandbox/config hash helper uses deprecated SHA-1. severity: WARNING languages: - typescript - javascript patterns: - pattern: $CRYPTO.createHash("sha1") - pattern-either: - pattern-inside: | function $F(...){ ... $PAYLOAD = JSON.stringify(...); ... return ...; } - pattern-inside: | const $F = (...) => { ... $PAYLOAD = JSON.stringify(...); ... return ...; } metadata: category: security confidence: medium technology: - nodejs ghsa: GHSA-FH3F-Q9QW-93J9 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-FH3F-Q9QW-93J9 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: sandbox-config-sha1-hash - id: ghsa-fqcm-97m6-w7rm.openclaw-unconditional-sandboxvalidated-loadwebmedia languages: - typescript severity: WARNING message: "loadWebMedia is running with sandboxValidated: true and a direct readFile override without an adjacent sandboxRoot-based fallback to localRoots. This can bypass local media root checks when sandboxRoot is unset." patterns: - pattern-inside: | async function $F(...){ ... } - pattern: | loadWebMedia($SOURCE, { ..., sandboxValidated: true, ..., readFile: ($FILE) => $READ, ..., }) - pattern-not-inside: | const $MEDIA = $COND ? await loadWebMedia($SOURCE, { ..., sandboxValidated: true, ..., }) : await loadWebMedia($SOURCE, { ..., localRoots: $ROOTS, ..., }); - pattern-not-inside: | if ($COND) { ... await loadWebMedia($SOURCE, { ..., sandboxValidated: true, ..., }); ... } else { ... await loadWebMedia($SOURCE, { ..., localRoots: $ROOTS, ..., }); ... } metadata: ghsa: GHSA-FQCM-97M6-W7RM advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-FQCM-97M6-W7RM detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-unconditional-sandboxvalidated-loadwebmedia - id: ghsa-fqrj-m88p-qf3v.openclaw-zalo-replay-dedupe-key-missing-target-scope languages: - typescript - javascript severity: INFO message: Zalo replay dedupe key is built only from event_name and messageId. Replay caches for multi-account webhook targets must include account/path target scope. See GHSA-FQRJ-M88P-QF3V. metadata: ghsa: GHSA-FQRJ-M88P-QF3V category: security cwe: - CWE-667 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-FQRJ-M88P-QF3V detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-zalo-replay-dedupe-key-missing-target-scope paths: include: - extensions/zalo/src/**/*.ts pattern-either: - pattern: const $KEY = `${$UPDATE.event_name}:${messageId}` - pattern: const $KEY = `${$UPDATE.event_name}:${$MESSAGE_ID}` - id: ghsa-fv94-qvg8-xqpw.ssh-sandbox-upload-missing-symlink-boundary-check languages: - typescript - javascript severity: WARNING message: SSH sandbox upload creates a tar stream from a local directory without a preceding symlink boundary validation helper, so tar may follow escaping symlinks before upload. patterns: - pattern-inside: | async function $FUNC(...){ ... } - pattern: | $TAR = spawn("tar", ["-C", $LOCAL, "-cf", "-", "."], ...) - pattern: | $SSH = spawn($CMD, $ARGS, ...) - pattern-not-inside: | async function $FUNC(...){ ... await $CHECK($LOCAL); ... $TAR = spawn("tar", ["-C", $LOCAL, "-cf", "-", "."], ...) ... } metadata: category: security confidence: medium ghsa: GHSA-FV94-QVG8-XQPW advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-FV94-QVG8-XQPW detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: ssh-sandbox-upload-missing-symlink-boundary-check - id: ghsa-g353-mgv3-8pcj.feishu-webhook-mode-missing-encrypt-key message: Feishu/Lark webhook-mode configuration sets verificationToken without also configuring encryptKey. severity: ERROR languages: - typescript - javascript metadata: category: security technology: - feishu - lark confidence: low note: Review aid only; misses inherited/defaulted config and may not prove runtime exploitability. ghsa: GHSA-G353-MGV3-8PCJ advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-G353-MGV3-8PCJ detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: feishu-webhook-mode-missing-encrypt-key patterns: - pattern-either: - pattern: | { ..., connectionMode: "webhook", ..., verificationToken: $TOKEN, ... } - pattern: | $CFG = { ..., connectionMode: "webhook", ..., verificationToken: $TOKEN, ... } - pattern-not: | { ..., encryptKey: $KEY, ... } - pattern-not: | $CFG = { ..., encryptKey: $KEY, ... } - id: ghsa-g86v-f9qv-rh6m.openclaw-missing-discard-ipv6-special-use-range languages: - typescript - javascript severity: WARNING message: IPv6 special-use blocking set is typed from ipaddr IPv6Range without the runtime "discard" range, so isBlockedSpecialUseIpv6Address can miss 100::/64 discard addresses. patterns: - pattern-either: - patterns: - pattern: | const BLOCKED_IPV6_SPECIAL_USE_RANGES = new Set([ ... ]); - pattern-not: | const BLOCKED_IPV6_SPECIAL_USE_RANGES = new Set([ ..., "discard", ... ]); - pattern-not-inside: | type $T = $R | "discard"; ... - pattern-not-inside: | type $T = "discard" | $R; ... - patterns: - pattern: | const BLOCKED_IPV6_SPECIAL_USE_RANGES = new Set>([ ... ]); - pattern-not: | const BLOCKED_IPV6_SPECIAL_USE_RANGES = new Set>([ ..., "discard", ... ]); - patterns: - pattern: | const BLOCKED_IPV6_SPECIAL_USE_RANGES = new Set>([ ... ]); - pattern-not: | const BLOCKED_IPV6_SPECIAL_USE_RANGES = new Set>([ ..., "discard", ... ]); metadata: ghsa: GHSA-G86V-F9QV-RH6M advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-G86V-F9QV-RH6M detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-missing-discard-ipv6-special-use-range - id: ghsa-g8p2-7wf7-98mq.query-gatewayurl-applied-without-confirmation languages: - typescript - javascript severity: ERROR message: Untrusted gatewayUrl from URL params/hash is written directly into live gateway settings. Route the value through a pending confirmation flow before reconnecting or applying tokens. patterns: - pattern-either: - patterns: - pattern: | $RAW = $PARAMS.get("gatewayUrl"); ... if ($RAW != null) { ... applySettings($HOST, { ...$HOST.settings, gatewayUrl: $URL, ... }); ... } - pattern-not: | $HOST.pendingGatewayUrl = ... - patterns: - pattern-either: - pattern: $URL = $PARAMS.get("gatewayUrl") - pattern: $URL = ($PARAMS.get("gatewayUrl") ?? "").trim() - pattern-inside: | if ($COND) { ... $HOST.settings = { ...$HOST.settings, gatewayUrl: $NEXT, ... }; ... } - pattern-not-inside: | $HOST.pendingGatewayUrl = ... metadata: ghsa: GHSA-G8P2-7WF7-98MQ advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-G8P2-7WF7-98MQ detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: query-gatewayurl-applied-without-confirmation - id: ghsa-g99v-8hwm-g76g.openclaw-web-search-citation-redirect-private-network-policy languages: - typescript - javascript message: Citation redirect resolution should not use a private-network-allowing SSRF policy for HEAD redirect expansion. severity: ERROR patterns: - pattern-either: - pattern: | withWebToolsNetworkGuard({ ..., init: { method: "HEAD", ... }, ..., policy: { dangerouslyAllowPrivateNetwork: true, ... }, ... }, ...) - pattern: | fetchWithWebToolsNetworkGuard({ ..., init: { method: "HEAD", ... }, ..., policy: { dangerouslyAllowPrivateNetwork: true, ... }, ... }) - pattern: | withWebToolsNetworkGuard({ ..., init: { method: "HEAD", ... }, ..., policy: $POLICY, ... }, ...) - pattern: | fetchWithWebToolsNetworkGuard({ ..., init: { method: "HEAD", ... }, ..., policy: $POLICY, ... }) - metavariable-pattern: metavariable: $POLICY patterns: - pattern-either: - pattern: WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY - pattern: TRUSTED_POLICY metadata: category: security cwe: CWE-918 ghsa: GHSA-G99V-8HWM-G76G rationale: HEAD-based citation redirect resolution must not opt into private-network SSRF policy. advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-G99V-8HWM-G76G detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-web-search-citation-redirect-private-network-policy - id: ghsa-gcj7-r3hg-m7w6.replay-key-derived-from-idempotency-header message: Replay or dedupe key derived from an idempotency/replay header can let unsigned metadata control request identity. severity: WARNING languages: - typescript - javascript patterns: - pattern-either: - pattern: | const $TOKEN = $GET(..., $HEADER, ...); ... if ($TOKEN) { ... return `...${$TOKEN}...`; } - pattern: | const $TOKEN = $GET(..., $HEADER); ... if ($TOKEN) { ... return `...${$TOKEN}...`; } - pattern: | const $TOKEN = $HEADERS[$HEADER]; ... if ($TOKEN) { ... return `...${$TOKEN}...`; } - metavariable-regex: metavariable: $HEADER regex: (?i).*(idempotency|replay|dedupe).* metadata: category: security cwe: - CWE-294 - CWE-345 ghsa: GHSA-GCJ7-R3HG-M7W6 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-GCJ7-R3HG-M7W6 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: replay-key-derived-from-idempotency-header - id: ghsa-gfmx-pph7-g46x.openclaw.system-event-missing-explicit-trust languages: - typescript - javascript severity: ERROR message: | enqueueSystemEvent() is called with interpolated or variable text without `trusted: false`. The default is `trusted: true`, which injects the text as a privileged `System:` prefix in the agent's context window. External content — channel messages, user IDs, event payloads, exec output — MUST be explicitly downgraded with `trusted: false` to prevent prompt injection. See GHSA-GFMX-PPH7-G46X. TRIAGE NOTE: If ALL interpolated values in the template literal are boolean flags or enum/const expressions (e.g. `${x ? "on" : "off"}`), or if the variable text is formatted from fully-internal state (not external channel content), the finding may be low-risk. Add `trusted: true` explicitly to self-document that the text is intentionally trusted. metadata: category: security cwe: - CWE-74 - CWE-77 ghsas: - GHSA-GFMX-PPH7-G46X ghsa: GHSA-GFMX-PPH7-G46X advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-GFMX-PPH7-G46X detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.system-event-missing-explicit-trust paths: exclude: - "**/*.test.*" - "**/*.spec.*" - src/auto-reply/reply/directive-handling.impl.ts - src/auto-reply/reply/directive-handling.persist.ts - src/auto-reply/reply/get-reply-directives-apply.ts - src/gateway/config-recovery-notice.ts - src/gateway/server-restart-sentinel.ts - src/infra/session-maintenance-warning.ts pattern-either: - patterns: - pattern: | enqueueSystemEvent(`...${$X}...`, $OPTS) - pattern-not: | enqueueSystemEvent(`...${$X}...`, { ..., trusted: $V, ... }) - pattern-not-inside: | enqueueSystemEvent(`...${$X}...`, { ..., trusted: $V, ... }) - patterns: - pattern: | enqueueSystemEvent($TEXT, $OPTS) - pattern-not: | enqueueSystemEvent($TEXT, { ..., trusted: $V, ... }) - pattern-not-inside: | enqueueSystemEvent($TEXT, { ..., trusted: $V, ... }) - metavariable-regex: metavariable: $TEXT regex: ^[a-zA-Z_$][a-zA-Z0-9_$]*$ - id: ghsa-gg9v-mgcp-v6m7.openclaw-bootstrap-token-legacy-acceptance-without-profile-record languages: - typescript severity: ERROR message: verifyDeviceBootstrapToken() consumes a bootstrap token record without resolving the persisted bootstrap profile. Legacy acceptance does not bind setup codes to issued role/scopes and can allow first-use privilege escalation. See GHSA-GG9V-MGCP-V6M7. metadata: ghsa: GHSA-GG9V-MGCP-V6M7 category: security cwe: - CWE-269 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-GG9V-MGCP-V6M7 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-bootstrap-token-legacy-acceptance-without-profile-record paths: include: - src/infra/device-bootstrap.ts pattern-regex: const \[tokenKey\] = found; - id: ghsa-gq9c-wg68-gwj2.browser-writable-output-path-bypasses-resolvewritablepathwithinroot languages: - typescript severity: ERROR message: Browser route is using resolvePathWithinRoot for a writable output path. For writable destinations (downloads, traces) use resolveWritablePathWithinRoot which performs symlink-aware canonical parent checks. The lexical-only resolvePathWithinRoot can be defeated by a symlink at the parent dir. See GHSA-GQ9C-WG68-GWJ2. metadata: ghsa: GHSA-GQ9C-WG68-GWJ2 category: security cwe: - CWE-22 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-GQ9C-WG68-GWJ2 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: browser-writable-output-path-bypasses-resolveWritablePathWithinRoot paths: include: - extensions/browser/src/browser/routes/**.ts - src/browser/routes/**.ts exclude: - "**/paths.ts" - "**/path-output.ts" pattern: resolvePathWithinRoot(...) - id: ghsa-h7f7-89mm-pqh6.openclaw-skill-download-targetdir-outside-tools-root languages: - typescript - javascript message: Untrusted skill download targetDir resolves outside the per-skill tools root. severity: ERROR patterns: - pattern-either: - pattern: | function $F(..., $SPEC, ...) { ... if ($SPEC.targetDir?.trim()) { return resolveUserPath($SPEC.targetDir); } ... } - pattern: | const $TARGET = $SPEC.targetDir?.trim() ? resolveUserPath($SPEC.targetDir) : $FALLBACK; - pattern-not-inside: | if (!isWithinDir(...)) { ... } - pattern-not-inside: | await assertCanonicalPathWithinBase({ ... }) metadata: ghsa: GHSA-H7F7-89MM-PQH6 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-H7F7-89MM-PQH6 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-skill-download-targetdir-outside-tools-root - id: ghsa-h9xm-j4qg-fvpg.apply-patch-sandbox-hostpath-without-workspace-guard languages: - typescript severity: ERROR message: Sandbox apply_patch path resolution should not return sandbox bridge host paths without re-applying assertSandboxPath when workspaceOnly remains enabled. patterns: - pattern-inside: | async function resolvePatchPath(...) { ... } - pattern: | if (options.sandbox) { const resolved = options.sandbox.bridge.resolvePath({ ... }); ... return { resolved: resolved.hostPath, ... }; } - pattern-not: | if (options.sandbox) { const resolved = options.sandbox.bridge.resolvePath({ ... }); await assertSandboxPath({ filePath: resolved.hostPath, cwd: options.cwd, root: options.cwd, ... }); return { resolved: resolved.hostPath, ... }; } metadata: ghsa: GHSA-H9XM-J4QG-FVPG advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-H9XM-J4QG-FVPG detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: apply-patch-sandbox-hostpath-without-workspace-guard - id: ghsa-j26j-7qc4-3mrf.teams-file-consent-missing-conversation-binding languages: - typescript - javascript severity: WARNING message: fileConsent/invoke handlers should bind pending uploads to the invoking conversation before consuming upload state; uploadId-only pending-upload lookup can allow cross-conversation use. patterns: - pattern-inside: | if ($ACTIVITY.type !== "invoke" || $ACTIVITY.name !== "fileConsent/invoke") { ... } ... - pattern: | const $PENDING = getPendingUpload($UPLOAD_ID); ... if ($ACTION === "accept" && $UPLOAD_INFO) { if ($PENDING) { ... uploadToConsentUrl({ ... }); ... } } else { ... removePendingUpload($UPLOAD_ID); } - pattern-not-inside: | if ($PENDING) { ... if (!$INVOKE_CONV || $PENDING_CONV !== $INVOKE_CONV) { ... } } metadata: confidence: medium detector_review: family_candidate rationale: Matches Teams fileConsent invoke handlers that both upload and remove pending uploads based on uploadId-controlled lookup without a same-handler conversation-binding guard. ghsa: GHSA-J26J-7QC4-3MRF advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-J26J-7QC4-3MRF detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: teams-file-consent-missing-conversation-binding - id: ghsa-j425-whc4-4jgc.openclaw-dangerous-host-env-override-pivots message: Dangerous host env override pivot reaches host env sanitization boundary or policy. severity: ERROR languages: - json - typescript - javascript pattern-either: - patterns: - pattern-inside: | { ... } - pattern-regex: '"(GIT_SSH_COMMAND|GIT_EXEC_PATH|GIT_TEMPLATE_DIR|YARN_RC_FILENAME|CC|CXX|CMAKE_C_COMPILER|CMAKE_CXX_COMPILER|RUSTC_WRAPPER|CARGO_BUILD_RUSTC|CARGO_BUILD_RUSTC_WRAPPER|MAKEFLAGS|MFLAGS)"' - patterns: - pattern-inside: | { ... } - pattern-regex: '"(GIT_CONFIG_[A-Z0-9_]+|NPM_CONFIG_[A-Z0-9_]+|CARGO_REGISTRIES_[A-Z0-9_]+|TF_VAR_[A-Z0-9_]+)"' - patterns: - pattern-either: - pattern: | sanitizeHostExecEnv({ ..., overrides: { ..., $KEY: $VALUE, ... }, ... }) - pattern: | sanitizeSystemRunEnvOverrides({ ..., overrides: { ..., $KEY: $VALUE, ... }, ... }) - metavariable-regex: metavariable: $KEY regex: ^(GIT_SSH_COMMAND|GIT_EXEC_PATH|GIT_TEMPLATE_DIR|YARN_RC_FILENAME|CC|CXX|CMAKE_C_COMPILER|CMAKE_CXX_COMPILER|RUSTC_WRAPPER|CARGO_BUILD_RUSTC|CARGO_BUILD_RUSTC_WRAPPER|MAKEFLAGS|MFLAGS|GIT_CONFIG_[A-Z0-9_]+|NPM_CONFIG_[A-Z0-9_]+|CARGO_REGISTRIES_[A-Z0-9_]+|TF_VAR_[A-Z0-9_]+)$ metadata: ghsa: GHSA-J425-WHC4-4JGC advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-J425-WHC4-4JGC detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-dangerous-host-env-override-pivots - id: ghsa-jf25-7968-h2h5.openclaw-nodes-screen-record-outpath-guard-missing message: The nodes tool (which contains screen_record) must be wrapped via applyNodesToolWorkspaceGuard, which adds outPath to the pathParamKeys. Without this, screen_record outPath bypasses the workspace boundary. See GHSA-JF25-7968-H2H5. severity: ERROR languages: - typescript metadata: ghsa: GHSA-JF25-7968-H2H5 category: security cwe: - CWE-22 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-JF25-7968-H2H5 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-nodes-screen-record-outpath-guard-missing paths: include: - src/agents/openclaw-tools.ts patterns: - pattern: createNodesTool(...) - pattern-not-inside: | import { ..., applyNodesToolWorkspaceGuard, ... } from "$X"; ... - pattern-not-inside: | import { applyNodesToolWorkspaceGuard } from "$X"; ... - pattern-not-inside: | import { applyNodesToolWorkspaceGuard, ... } from "$X"; ... - id: ghsa-jfv4-h8mc-jcp8.immediate-process-tree-sigkill message: Immediate process-tree SIGKILL inside a termination helper deserves review for missing graceful shutdown and ownership checks. severity: WARNING languages: - typescript - javascript patterns: - pattern-either: - pattern: process.kill(-$PID, "SIGKILL") - pattern: process.kill(-$PID, 9) - pattern-inside: | function $F(...) { ... } - metavariable-regex: metavariable: $F regex: (?i).*(kill|terminate|stop|destroy).* - pattern-not-inside: | function $F(...) { ... process.kill(-$PID, "SIGTERM") ... process.kill(-$PID, "SIGKILL") ... } - pattern-not-inside: | function $F(...) { ... process.kill(-$PID, 0) ... process.kill(-$PID, "SIGKILL") ... } metadata: ghsa: GHSA-JFV4-H8MC-JCP8 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-JFV4-H8MC-JCP8 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: immediate-process-tree-sigkill - id: ghsa-jj6q-rrrf-h66h.timing-safe-equal-length-short-circuit message: Secret comparison short-circuits on length before timingSafeEqual; hash to a fixed length first or use a fixed-length helper. severity: ERROR languages: - typescript - javascript patterns: - pattern-either: - pattern: | if ($A.length !== $B.length) { ... return false; } ... return $CRYPTO.timingSafeEqual($A, $B); - pattern: | if ($A.length !== $B.length) return false; ... return $CRYPTO.timingSafeEqual($A, $B); - pattern-not: | return $CRYPTO.timingSafeEqual($HASH(...), $HASH2(...)); metadata: category: security confidence: medium ghsa: GHSA-JJ6Q-RRRF-H66H advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-JJ6Q-RRRF-H66H detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: timing-safe-equal-length-short-circuit - id: ghsa-jjw7-3vjf-fg5j.openclaw-config-private-key-string-field languages: - typescript - javascript message: Config schemas that model a privateKey field as a plain string can bypass secret redaction. Prefer buildSecretInputSchema()/SecretInputSchema and sensitive registration. severity: ERROR patterns: - pattern-either: - pattern: | privateKey: z.string().optional() - pattern: | privateKey: z.string() - pattern-inside: | z.object({ ... }) metadata: ghsa: GHSA-JJW7-3VJF-FG5J advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-JJW7-3VJF-FG5J detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-config-private-key-string-field - id: ghsa-jmm5-fvh5-gf4p.ts-early-length-check-before-timingsafeequal message: Early length mismatch return before timingSafeEqual can leak secret length; hash or pad to fixed-length before comparing. severity: ERROR languages: - typescript - javascript patterns: - pattern-inside: | function $F(...){ ... } - pattern-either: - pattern: | const $A = Buffer.from($LEFT, ...); const $B = Buffer.from($RIGHT, ...); if ($A.length !== $B.length) { return false; } ... return timingSafeEqual($A, $B); - pattern: | const $A = Buffer.from($LEFT, ...); const $B = Buffer.from($RIGHT, ...); if ($A.length !== $B.length) return false; ... return timingSafeEqual($A, $B); metadata: category: security cwe: - CWE-208 ghsa: GHSA-JMM5-FVH5-GF4P advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-JMM5-FVH5-GF4P detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: ts-early-length-check-before-timingsafeequal - id: ghsa-jp4j-q5fc-58gv.discord-component-missing-group-policy languages: - typescript message: Discord component ingress calls ensureGuildComponentMemberAllowed without groupPolicy, which skips guild/channel group policy enforcement. severity: ERROR patterns: - pattern: | await ensureGuildComponentMemberAllowed({ ... }) - pattern-not: | await ensureGuildComponentMemberAllowed({ ..., groupPolicy: $POLICY, ... }) metadata: ghsa: GHSA-JP4J-Q5FC-58GV advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-JP4J-Q5FC-58GV detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: discord-component-missing-group-policy - id: ghsa-jq3f-vjww-8rq7.webhook-body-read-before-secret-validation languages: - typescript - javascript severity: ERROR message: Webhook handlers that read a request body before extracting the Telegram secret header should be reviewed for pre-auth resource exhaustion. patterns: - pattern-inside: | createServer(($REQ, $RES) => { ... }) - pattern: | const $BODY = await readJsonBodyWithLimit($REQ, ...); ... const $RAW = $REQ.headers["x-telegram-bot-api-secret-token"]; - pattern-not: | const $RAW = $REQ.headers["x-telegram-bot-api-secret-token"]; ... if (!hasValidTelegramWebhookSecret(...)) { ... return; } ... const $BODY = await readJsonBodyWithLimit($REQ, ...); metadata: ghsa: GHSA-JQ3F-VJWW-8RQ7 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-JQ3F-VJWW-8RQ7 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: webhook-body-read-before-secret-validation - id: ghsa-jqpq-mgvm-f9r6.openclaw-project-local-node-modules-bin-prepended-to-path languages: - typescript severity: ERROR message: Project-local node_modules/.bin is included in the PATH prepend candidate list. This can allow a malicious workspace to hijack allowlisted command resolution. Project-local bin must be opt-in and append-only. See GHSA-JQPQ-MGVM-F9R6. metadata: ghsa: GHSA-JQPQ-MGVM-F9R6 category: security cwe: - CWE-426 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-JQPQ-MGVM-F9R6 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-project-local-node-modules-bin-prepended-to-path paths: include: - src/infra/path-env.ts pattern-either: - pattern: candidates.push(localBinDir) - pattern: prepend.push(localBinDir) - id: ghsa-m34q-h93w-vg5x.openshell-unsafe-remote-path-normalization languages: - typescript severity: ERROR message: OpenShell remote path configs normalized without managed-root enforcement can escape /sandbox or /agent. patterns: - pattern-either: - pattern: | remoteWorkspaceDir: $FN(...), - pattern: | remoteAgentWorkspaceDir: $FN(...), - metavariable-regex: metavariable: $FN regex: ^(?:normalizeRemotePath|cleanRemotePath|path\.posix\.normalize)$ metadata: category: security ghsa: GHSA-M34Q-H93W-VG5X detector: A advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-M34Q-H93W-VG5X detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openshell-unsafe-remote-path-normalization - id: ghsa-m3mh-3mpg-37hw.openclaw-staged-package-install-without-hidden-project-npmrc languages: - typescript message: Running npm install in a copied package directory without first hiding the staged project .npmrc can let attacker-controlled npm config influence install-time tool execution. severity: WARNING patterns: - pattern: | $RES = await runCommandWithTimeout( ["npm", "install", "--omit=dev", "--silent", "--ignore-scripts"], {..., cwd: $STAGE, ...}, ) - pattern-not-inside: | $HIDDEN = await hideProjectNpmConfigForInstall($STAGE); ... try { ... $RES = await runCommandWithTimeout( ["npm", "install", "--omit=dev", "--silent", "--ignore-scripts"], {..., cwd: $STAGE, ...}, ) ... } finally { await restoreProjectNpmConfigAfterInstall($HIDDEN); } - pattern-not-inside: | $HIDDEN = await hideProjectNpmConfigForInstall($STAGE); ... try { ... await runCommandWithTimeout( ["npm", "install", "--omit=dev", "--silent", "--ignore-scripts"], {..., cwd: $STAGE, ...}, ) ... } finally { await restoreProjectNpmConfigAfterInstall($HIDDEN); } metadata: ghsa: GHSA-M3MH-3MPG-37HW advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-M3MH-3MPG-37HW detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-staged-package-install-without-hidden-project-npmrc - id: ghsa-m69h-jm2f-2pv8.feishu-reaction-chat-type-defaults-to-p2p languages: - typescript severity: WARNING message: Synthetic Feishu reaction events must preserve verified chat type instead of defaulting non-group reactions to p2p. patterns: - pattern-either: - pattern: | const $TYPE: $CHAT = $EVENT.chat_type === "group" ? "group" : "p2p"; - pattern: | const $TYPE = $EVENT.chat_type === "group" ? "group" : "p2p"; metadata: ghsa: GHSA-M69H-JM2F-2PV8 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-M69H-JM2F-2PV8 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: feishu-reaction-chat-type-defaults-to-p2p - id: ghsa-m7x8-2w3w-pr42.ghsa-m7x8-shell-interpolated-gh-api-login message: Unvalidated login-like input interpolated into an execSync shell command that invokes gh api users/... severity: ERROR languages: - typescript - javascript patterns: - pattern-either: - pattern: | execSync(`gh api users/${$LOGIN}`, ...) - pattern: | execSync(`gh api users/${$LOGIN}...`, ...) - pattern: | execSync("gh api users/" + $LOGIN, ...) - pattern: | execSync("gh api users/" + $LOGIN + ..., ...) - pattern: | execSync('gh api users/' + $LOGIN, ...) - pattern: | execSync('gh api users/' + $LOGIN + ..., ...) metadata: ghsa: GHSA-M7X8-2W3W-PR42 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-M7X8-2W3W-PR42 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: ghsa-m7x8-shell-interpolated-gh-api-login - id: ghsa-mc68-q9jw-2h3v.openclaw-docker-path-env-shell-interpolation languages: - typescript - javascript severity: ERROR message: Caller-controlled params.env.PATH is interpolated directly into an `export PATH=...` shell snippet. Pass it via an environment variable and reference the variable from constant shell text instead. See GHSA-MC68-Q9JW-2H3V. metadata: ghsa: GHSA-MC68-Q9JW-2H3V category: security cwe: - CWE-78 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-MC68-Q9JW-2H3V detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-docker-path-env-shell-interpolation paths: include: - src/agents/bash-tools.shared.ts pattern-regex: "`[^`]*export\\s+PATH=[^`]*\\$\\{params\\.env\\.PATH\\}[^`]*`" - id: ghsa-mf5g-6r6f-ghhm.webhook-invalid-token-without-preauth-lockout message: Webhook invalid-token branches should enforce a pre-auth lockout or failure budget before returning 401. severity: WARNING languages: - typescript patterns: - pattern-inside: | function $FUNC(...){ ... } - pattern: | if (!validateToken($TOKEN, $EXPECTED)) { ... return { ok: false, statusCode: 401, error: "Invalid token" }; } - pattern-not-inside: | if ($RATE_LIMITER.isLocked(...)) { ... return { ok: false, statusCode: 429, error: "Rate limit exceeded" }; } - pattern-not-inside: | if (!validateToken($TOKEN, $EXPECTED)) { ... if ($RATE_LIMITER.recordFailure(...)) { ... return { ok: false, statusCode: 429, error: "Rate limit exceeded" }; } ... return { ok: false, statusCode: 401, error: "Invalid token" }; } metadata: category: security ghsa: GHSA-MF5G-6R6F-GHHM detector: A advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-MF5G-6R6F-GHHM detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: webhook-invalid-token-without-preauth-lockout - id: ghsa-mmpf-jwf4-h3qv.shell-git-add-paths-must-use-double-dash languages: - bash severity: ERROR message: Passing filenames into git add without a `--` separator can let option-like paths be interpreted as flags. Use `git add -- ...` and avoid piping path text through xargs. pattern-either: - patterns: - pattern: echo "$FILES" | xargs git add - patterns: - pattern: printf ... | xargs git add - patterns: - pattern: ... | xargs git add - metavariable-regex: metavariable: $... regex: .* - patterns: - pattern: git add $FILES - patterns: - pattern: git add "$FILES" - patterns: - pattern: git add ${FILES[@]} - patterns: - pattern: git add "${FILES[@]}" - patterns: - pattern: git add ${files[@]} - patterns: - pattern: git add "${files[@]}" pattern-not-either: - pattern: git add -- $FILES - pattern: git add -- "$FILES" - pattern: git add -- ${FILES[@]} - pattern: git add -- "${FILES[@]}" - pattern: git add -- ${files[@]} - pattern: git add -- "${files[@]}" metadata: ghsa: GHSA-MMPF-JWF4-H3QV advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-MMPF-JWF4-H3QV detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: shell-git-add-paths-must-use-double-dash - id: ghsa-mp66-rf4f-mhh8.googlechat-app-url-addon-principal-missing-binding message: Google Chat app-url webhook auth accepts add-on principals without comparing the token principal to a configured binding. severity: ERROR languages: - typescript - javascript metadata: ghsa: GHSA-MP66-RF4F-MHH8 detector: A category: security advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-MP66-RF4F-MHH8 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: googlechat-app-url-addon-principal-missing-binding patterns: - pattern: | const $OK = $PAYLOAD?.email_verified && ($EMAIL === $CHAT_ISSUER || $ADDON_ISSUER_PATTERN.test($EMAIL)); - pattern-not: | const $EXPECTED = $PARAMS.expectedAddOnPrincipal?.trim().toLowerCase(); - pattern-not: | const $EXPECTED = $INPUT.expectedAddOnPrincipal?.trim().toLowerCase(); - pattern-not: | const $EXPECTED = $CFG.expectedAddOnPrincipal?.trim().toLowerCase(); paths: include: - "**/*.ts" - "**/*.js" - id: ghsa-mwxv-35wr-4vvj.openclaw.gateway.api-channels-prefix-auth-gap languages: - typescript message: Gateway plugin routes that protect only /api/channels/* but not the exact /api/channels root can leave the channel namespace auth-bypassable. severity: ERROR patterns: - pattern-inside: | if (handlePluginRequest) { ... } - pattern: | if ($REQ_PATH.startsWith("/api/channels/")) { ... } - pattern-not: | if ($REQ_PATH === "/api/channels" || $REQ_PATH.startsWith("/api/channels/")) { ... } metadata: ghsa: GHSA-MWXV-35WR-4VVJ advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-MWXV-35WR-4VVJ detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.gateway.api-channels-prefix-auth-gap - id: ghsa-p4x4-2r7f-wjxg.openclaw-wrapper-carrier-allow-always message: Positional shell carrier persists a carried executable without first rejecting shell or dispatch wrappers. severity: ERROR languages: - typescript - javascript patterns: - pattern-either: - pattern: | const $RESOLUTION = resolveCommandResolutionFromArgv([$CARRIED], $CWD, $ENV); ... return resolveExecutionTargetCandidatePath($RESOLUTION, $CWD); - pattern: | const $RESOLUTION = resolveCommandResolutionFromArgv([$CARRIED], $DIR, $ENVIRONMENT); ... return resolveExecutionTargetCandidatePath($RESOLUTION, $DIR); - pattern-not-inside: | const $NAME = normalizeExecutableToken($CARRIED); ... if (isDispatchWrapperExecutable($NAME) || isShellWrapperExecutable($NAME)) { return undefined; } ... metadata: ghsa: GHSA-P4X4-2R7F-WJXG advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-P4X4-2R7F-WJXG detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-wrapper-carrier-allow-always - id: ghsa-p536-vvpp-9mc8.openclaw.web-fetch-or-media-unbounded-response-read languages: - typescript - javascript severity: WARNING message: | Inside the openclaw web-fetch / media / SSRF-guarded fetch family, calling .text() / .json() / .arrayBuffer() / .blob() etc. directly on a Response that may have come from an untrusted (model- or plugin-controlled) URL can OOM the process if the upstream returns a multi-GB body. Use readResponseWithLimit() / readResponseTextSnippet() (which stream-and-bound) instead. A pre-buffer Content-Length check is not sufficient — the upstream can lie or omit Content-Length. metadata: category: security cwe: - CWE-400 ghsas: - GHSA-P536-VVPP-9MC8 - GHSA-J27P-HQ53-9WGC ghsa: GHSA-P536-VVPP-9MC8 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-P536-VVPP-9MC8 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.web-fetch-or-media-unbounded-response-read paths: include: - src/web-fetch/** - src/agents/tools/web-fetch*.ts - src/agents/tools/**/web-fetch*.ts - src/plugins/web-fetch-providers*.ts - src/media/** - src/infra/net/** exclude: - src/media/read-response-with-limit.ts - src/media/read-response-with-limit.test.ts patterns: - pattern-either: - pattern: $RESP.text() - pattern: $RESP.json() - pattern: $RESP.arrayBuffer() - pattern: $RESP.blob() - pattern: $RESP.bytes() - pattern: $RESP.formData() - pattern-not-inside: | readResponseTextSnippet($RESP, ...) - pattern-not-inside: | readResponseWithLimit($RESP, ...) - id: ghsa-pfv7-rr5m-qmv6.local-relay-json-endpoint-missing-auth-header-check languages: - typescript - javascript severity: WARNING message: Local relay servers that expose privileged /json* endpoints should enforce a relay-auth header before serving them. patterns: - pattern-inside: | createServer(($REQ, $RES) => { ... }) - pattern-either: - pattern: | if (($PATH === "/json/version" || $PATH === "/json/version/") && $COND) { ... } - pattern: | if ($LIST.has($PATH) && $COND) { ... } - pattern: | if ($PATH.startsWith("/json")) { ... } - pattern-not-inside: | if ($PATH.startsWith("/json")) { ... const $TOKEN = ...; if (!$TOKEN || $TOKEN !== $AUTH) { ... return; } ... } metadata: ghsa: GHSA-PFV7-RR5M-QMV6 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-PFV7-RR5M-QMV6 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: local-relay-json-endpoint-missing-auth-header-check - id: ghsa-q2qc-744p-66r2.ghsa-q2qc-post-resolution-agent-prefix-guard languages: - typescript - javascript message: Authorization/visibility logic records whether the original session reference was an explicit agent key, then rewrites that reference to a resolved canonical key and later re-checks the rewritten value with startsWith("agent:") instead of using the original explicit-key flag. severity: ERROR patterns: - pattern-inside: | const $EXPLICIT = $RAW.startsWith("agent:"); ... $RAW = $RESOLVED; ... if ($GUARD && !$RAW.startsWith("agent:")) { ... } - metavariable-pattern: metavariable: $RESOLVED pattern-either: - pattern: $OBJ.key - pattern: $CALL(...) - pattern-not-inside: | if ($GUARD && !$EXPLICIT) { ... } metadata: ghsa: GHSA-Q2QC-744P-66R2 category: authz-bypass confidence: medium detector: A advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-Q2QC-744P-66R2 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: ghsa-q2qc-post-resolution-agent-prefix-guard - id: ghsa-q447-rj3r-2cgh.openclaw.webhook-request-stream-read-without-shared-limit-helper languages: - typescript severity: ERROR message: Webhook/request handler manually reads request stream data instead of using the shared bounded body helpers. Manual req.on("data") readers often miss unified maxBytes + timeoutMs enforcement and can reintroduce oversized-body or slow-upload DoS. See GHSA-Q447-RJ3R-2CGH. metadata: ghsa: GHSA-Q447-RJ3R-2CGH category: security cwe: - CWE-400 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-Q447-RJ3R-2CGH detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.webhook-request-stream-read-without-shared-limit-helper paths: include: - extensions/**/src/**/monitor*.ts - extensions/**/src/**/webhook*.ts - extensions/**/src/**/nostr-profile-http.ts - src/gateway/hooks.ts - src/line/**/*.ts - src/slack/**/*.ts - src/telegram/**/*.ts exclude: - "**/*.test.ts" - src/infra/http-body.ts - src/plugin-sdk/** patterns: - pattern-either: - pattern: $REQ.on("data", ...) - pattern: $REQ.on('data', ...) - metavariable-regex: metavariable: $REQ regex: ^(req|request|params\.req)$ - pattern-not-inside: | readRequestBodyWithLimit(...) - pattern-not-inside: | readJsonBodyWithLimit(...) - pattern-not-inside: | installRequestBodyLimitGuard(...) - id: ghsa-q6qf-4p5j-r25g.openclaw.sandbox-image-tool.workspace-only-omission languages: - typescript severity: WARNING message: Sandboxed image tool path resolution is using the legacy helper that never enforces tools.fs.workspaceOnly for mounted host paths. This shape is the vulnerable pre-fix image-tool family from GHSA-Q6QF-4P5J-R25G. pattern: | await resolveSandboxedImagePath({ sandbox: $SANDBOX, imagePath: $IMAGE, }) metadata: cwe: - CWE-200 - CWE-284 ghsa: GHSA-Q6QF-4P5J-R25G category: security confidence: medium rationale: The vulnerable helper only accepted {root, bridge}, so any call to it in sandboxed image loading implies missing workspaceOnly enforcement. advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-Q6QF-4P5J-R25G detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.sandbox-image-tool.workspace-only-omission - id: ghsa-qcj9-wwgw-6gm8.openclaw-workspace-trust-root-env-read languages: - typescript - javascript severity: WARNING message: Workspace dotenv loading should not be followed by reads of OpenClaw bundled trust-root env vars; block them in the workspace loader instead. patterns: - pattern-either: - pattern: | loadWorkspaceDotEnvFile(...) ... process.env.OPENCLAW_BUNDLED_PLUGINS_DIR - pattern: | loadWorkspaceDotEnvFile(...) ... process.env.OPENCLAW_BUNDLED_HOOKS_DIR - pattern: | loadWorkspaceDotEnvFile(...) ... process.env.OPENCLAW_BUNDLED_SKILLS_DIR - pattern: | loadWorkspaceDotEnvFile(...) ... process.env.OPENCLAW_BROWSER_CONTROL_MODULE metadata: ghsa: GHSA-QCJ9-WWGW-6GM8 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-QCJ9-WWGW-6GM8 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-workspace-trust-root-env-read - id: ghsa-qf48-qfv4-jjm9.openclaw-extension-upload-direct-file-read-before-sandboxed-media-load languages: - typescript - javascript severity: ERROR message: Extension upload helper reads a local file path directly before upload. Upload helpers must use sandbox-aware media/path loading (for example loadWebMedia/localRoots/workspace-scoped helpers) so tool callers cannot exfiltrate arbitrary host files through provider uploads. See GHSA-QF48-QFV4-JJM9. metadata: ghsa: GHSA-QF48-QFV4-JJM9 category: security cwe: - CWE-22 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-QF48-QFV4-JJM9 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-extension-upload-direct-file-read-before-sandboxed-media-load paths: include: - extensions/**/src/**/*.ts exclude: - "**/*.test.ts" - "**/*.spec.ts" patterns: - pattern-inside: | async function $F(...) { ... } - pattern-either: - pattern: const $BUF = await fs.readFile($PATH); - pattern: const $BUF = await readFile($PATH); - pattern: const $BUF = await fsp.readFile($PATH); - metavariable-regex: metavariable: $F regex: (?i).*(resolve.*Upload.*|upload.*(Image|File|Media|Attachment)|.*UploadInput.*|send.*(Image|File|Media|Attachment)).* - pattern-not-inside: | ... loadWebMedia(...) ... - pattern-not-inside: | ... resolveStrictExistingPathsWithinRoot(...) ... - pattern-not-inside: | ... resolveExistingPathsWithinRoot(...) ... - id: ghsa-qpjj-47vm-64pj.openclaw-browser-control-routes-missing-auth-middleware languages: - typescript severity: ERROR message: Browser control routes are registered without installBrowserAuthMiddleware(). See GHSA-QPJJ-47VM-64PJ. metadata: ghsa: GHSA-QPJJ-47VM-64PJ category: security cwe: - CWE-306 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-QPJJ-47VM-64PJ detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-browser-control-routes-missing-auth-middleware paths: include: - extensions/browser/src/server.ts - src/browser/server.ts patterns: - pattern: registerBrowserRoutes(...) - pattern-not-inside: | ... installBrowserAuthMiddleware(...) ... - id: ghsa-qqq7-4hxc-x63c.openclaw-trusted-tool-media-alias-bypass languages: - typescript - javascript severity: ERROR message: Exact raw-name registration guards are missing before trusted tool MEDIA paths are preserved. patterns: - pattern-either: - pattern: | if (isToolResultMediaTrusted($TOOL, $RESULT)) { ... return $MEDIA; } - pattern: | if (isToolResultMediaTrusted($TOOL, $RESULT)) return $MEDIA; - pattern-not-inside: | if (isToolResultMediaTrusted($TOOL, $RESULT)) { ... if ($NAMES !== undefined) { ... if (!$RAW || !$NAMES.has($RAW)) { ... return ...; } } ... } paths: include: - src/**/*.ts - .artifacts/ghsa-detector-review-runs/**/*.ts metadata: ghsa: GHSA-QQQ7-4HXC-X63C advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-QQQ7-4HXC-X63C detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-trusted-tool-media-alias-bypass - id: ghsa-qxgf-hmcj-3xw3.raw-image-download-fetch-without-ssrf-guard languages: - typescript - javascript severity: ERROR message: Image download helper uses raw fetch instead of a shared SSRF-guarded fetch path. patterns: - pattern-either: - pattern: | async function $F(...){ ... const $RESP = await fetch($URL, ...); ... } - pattern: | const $F = async (...) => { ... const $RESP = await fetch($URL, ...); ... } - metavariable-regex: metavariable: $F regex: .*(fetchImage|downloadImage|loadImage|download).* - pattern-not-inside: | const { response: $RESP, ...$REST } = await fetchWithSsrFGuard(...) metadata: ghsa: GHSA-QXGF-HMCJ-3XW3 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-QXGF-HMCJ-3XW3 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: raw-image-download-fetch-without-ssrf-guard - id: ghsa-r294-2894-92j3.exported-session-html-unsafe-marked-setup languages: - javascript message: Exported session viewer configures Marked renderer callbacks without an html() raw-HTML escape handler; review for stored XSS from untrusted markdown/metadata. severity: ERROR patterns: - pattern: | marked.use({ ..., renderer: { ..., }, ..., }) - pattern-not: | marked.use({ ..., renderer: { ..., html($TOKEN) { return escapeHtml(...); }, ..., }, ..., }) - pattern-not: | marked.use({ ..., renderer: { ..., html($TOKEN) { return escapeHtmlTags(...); }, ..., }, ..., }) metadata: category: security cwe: - CWE-79 ghsa: GHSA-R294-2894-92J3 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-R294-2894-92J3 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: exported-session-html-unsafe-marked-setup - id: ghsa-r5h9-vjqc-hq3r.nextcloud-talk-allowlist-display-name-match languages: - typescript - javascript message: Nextcloud Talk allowlist checks should compare stable senderId, not mutable senderName/display name. severity: ERROR patterns: - pattern-either: - pattern: | resolveNextcloudTalkAllowlistMatch({ ..., senderName: $NAME, ... }) - pattern: | resolveNextcloudTalkGroupAllow({ ..., senderName: $NAME, ... }) metadata: ghsa: GHSA-R5H9-VJQC-HQ3R advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-R5H9-VJQC-HQ3R detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: nextcloud-talk-allowlist-display-name-match - id: ghsa-rchv-x836-w7xp.openclaw-dashboard-auth-query-credentials message: Dashboard gateway credentials are being placed into URL query parameters. Use URL fragments/session-only handoff instead, and never propagate the gateway password into browser URLs. See GHSA-RCHV-X836-W7XP. severity: ERROR languages: - swift metadata: ghsa: GHSA-RCHV-X836-W7XP category: security cwe: - CWE-598 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-RCHV-X836-W7XP detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-dashboard-auth-query-credentials paths: include: - apps/macos/Sources/OpenClaw/**/*.swift pattern-regex: \bqueryItems\s*\.\s*append\s*\(\s*URLQueryItem\s*\(\s*name:\s*"(?:token|password)" - id: ghsa-rhfg-j8jq-7v2h.openclaw.extension-configurable-baseurl-raw-fetch-bypasses-ssrf-guard languages: - typescript - javascript severity: ERROR mode: taint message: | Channel/provider extension lets an operator/account-configurable URL flow into a raw HTTP client without going through fetchWithSsrFGuard. The configured value can point to a private-network destination (RFC1918, 169.254.169.254 metadata, loopback). See GHSA-RHFG-J8JQ-7V2H. Replace with fetchWithSsrFGuard(...) and thread the account's allowPrivateNetwork through an SsrFPolicy. TRIAGE NOTE: This rule only fires when baseUrl/endpoint flows from a params/config/opts-shaped object (i.e. operator- or LLM-supplied input). Hardcoded constants (e.g. `this.baseUrl = "https://api.twilio.com/..."`) are NOT flagged because they are not attacker-controllable. If you see a finding where the URL is verifiably a compile-time constant, it is a false positive — please add a nosem comment and confirm the constant cannot be overridden at runtime. metadata: category: security cwe: - CWE-918 ghsas: - GHSA-RHFG-J8JQ-7V2H ghsa: GHSA-RHFG-J8JQ-7V2H advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-RHFG-J8JQ-7V2H detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.extension-configurable-baseurl-raw-fetch-bypasses-ssrf-guard paths: include: - extensions/**/*.ts - extensions/**/*.tsx - extensions/**/*.js - extensions/**/*.mjs exclude: - extensions/**/*.test.ts - extensions/**/*.test.tsx - extensions/**/test-harness* - extensions/**/*.spec.ts pattern-sources: - patterns: - pattern: | const { ..., $URL, ... } = $PARAMS; - metavariable-regex: metavariable: $URL regex: ^(baseUrl|serverUrl|apiBaseUrl|endpoint|host)$|^[a-z][a-zA-Z0-9]*(BaseUrl|BaseURL|ServerUrl|ServerURL|ApiBaseUrl|Endpoint|Host)$ - pattern-not: | const { ..., $URL, ... } = { ... }; - pattern-not: | const { ..., $URL, ... } = $OBJ[$KEY]; - patterns: - pattern: $PARAMS.$URL - metavariable-regex: metavariable: $URL regex: ^(baseUrl|serverUrl|apiBaseUrl|endpoint|host)$|^[a-z][a-zA-Z0-9]*(BaseUrl|BaseURL|ServerUrl|ServerURL|ApiBaseUrl|Endpoint|Host)$ - metavariable-regex: metavariable: $PARAMS regex: ^(params|config|options|opts|input|args|cfg|settings|account|credentials|ext)$|^[a-z][a-zA-Z0-9]*(Params|Config|Options|Opts|Input|Args|Cfg|Settings|Account|Credentials|Ext)$ pattern-sanitizers: - pattern: fetchWithSsrFGuard(...) - pattern: fetchWithSsrfGuard(...) - pattern: $X.fetchWithSsrFGuard(...) - pattern: ssrFCheck(...) - pattern: validateUrlForSsrF(...) pattern-sinks: - pattern-either: - pattern: fetch($URL, ...) - pattern: undiciFetch($URL, ...) - pattern: undici.fetch($URL, ...) - pattern: $CLIENT.fetch($URL, ...) - pattern: axios($URL, ...) - pattern: axios.$M($URL, ...) - pattern: got($URL, ...) - pattern: got.$M($URL, ...) - pattern: ky($URL, ...) - pattern: wretch($URL) - pattern: superagent.$M($URL) - pattern: needle.$M($URL, ...) - pattern: phin($URL, ...) - pattern: http.request($URL, ...) - pattern: https.request($URL, ...) - pattern: http.get($URL, ...) - pattern: https.get($URL, ...) - id: ghsa-rm2p-j3r7-4x4j.slack-reaction-handler-missing-system-event-authorization languages: - typescript - javascript severity: ERROR message: Slack reaction ingress that enqueues system events should first resolve authorizeAndResolveSlackSystemEventContext and bail out when authorization fails. patterns: - pattern-either: - pattern: | ctx.app.event("reaction_added", async (...) => { ... enqueueSystemEvent($TEXT, $OPTS) ... }) - pattern: | ctx.app.event("reaction_removed", async (...) => { ... enqueueSystemEvent($TEXT, $OPTS) ... }) - pattern-not: | ctx.app.event($EVENT, async (...) => { ... const $CTX = await authorizeAndResolveSlackSystemEventContext(...) if (!$CTX) { ... } ... enqueueSystemEvent($TEXT, $OPTS) ... }) metadata: ghsa: GHSA-RM2P-J3R7-4X4J advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-RM2P-J3R7-4X4J detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: slack-reaction-handler-missing-system-event-authorization - id: ghsa-rqp8-q22p-5j9q.openclaw-multi-account-plugin-route-replacement languages: - typescript - javascript severity: ERROR message: "Plugin registers an account-scoped webhook route with replaceExisting: true. Duplicate webhook paths can replace another account's handler and collapse per-account policy context. See GHSA-RQP8-Q22P-5J9Q." metadata: ghsa: GHSA-RQP8-Q22P-5J9Q category: security cwe: - CWE-284 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-RQP8-Q22P-5J9Q detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-multi-account-plugin-route-replacement paths: include: - extensions/**/src/**/*.ts pattern: | registerPluginHttpRoute({ ..., replaceExisting: true, ..., accountId: $ACCOUNT, ..., }) - id: ghsa-rvqr-hrcc-j9vv.unresolved-discovery-routing-from-txt-hints languages: - typescript - javascript severity: WARNING message: Discovery routing falls back from resolved host/port fields to TXT-only host or port hints, which can let unresolved metadata steer the chosen endpoint. patterns: - pattern-either: - patterns: - pattern-either: - pattern: | $HOST = $BEACON.host || $BEACON.tailnetDns || $BEACON.lanHost - pattern: | $HOST = $BEACON.host || $BEACON.lanHost || $BEACON.tailnetDns - pattern: | $HOST = $BEACON.tailnetDns || $BEACON.lanHost || $BEACON.host - pattern: | $HOST = $BEACON.tailnetDns || $BEACON.host || $BEACON.lanHost - pattern: | $HOST = $BEACON.lanHost || $BEACON.host || $BEACON.tailnetDns - pattern: | $HOST = $BEACON.lanHost || $BEACON.tailnetDns || $BEACON.host - pattern: | return $BEACON.host || $BEACON.tailnetDns || $BEACON.lanHost - pattern: | return $BEACON.host || $BEACON.lanHost || $BEACON.tailnetDns - pattern: | return $BEACON.tailnetDns || $BEACON.lanHost || $BEACON.host - pattern: | return $BEACON.tailnetDns || $BEACON.host || $BEACON.lanHost - pattern: | return $BEACON.lanHost || $BEACON.host || $BEACON.tailnetDns - pattern: | return $BEACON.lanHost || $BEACON.tailnetDns || $BEACON.host - metavariable-regex: metavariable: $HOST regex: .*(host|Host|targetHost).* - patterns: - pattern-either: - pattern: | $PORT = $BEACON.port ?? $BEACON.gatewayPort ?? $DEFAULT - pattern: | return $BEACON.port ?? $BEACON.gatewayPort ?? $DEFAULT - metavariable-regex: metavariable: $PORT regex: .*(port|Port).* metadata: confidence: medium category: security bug-family: unresolved-discovery-routing ghsa: GHSA-RVQR-HRCC-J9VV advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-RVQR-HRCC-J9VV detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: unresolved-discovery-routing-from-txt-hints - id: ghsa-rwj8-p9vq-25gv.bluebubbles-media-read-without-root-allowlist languages: - typescript - javascript severity: ERROR message: A non-HTTP media source is converted with resolveLocalMediaPath(...) and then read from disk without first enforcing a root allowlist validator such as assertLocalMediaPathAllowed. metadata: ghsa: GHSA-RWJ8-P9VQ-25GV cwe: CWE-22 category: security confidence: medium advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-RWJ8-P9VQ-25GV detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: bluebubbles-media-read-without-root-allowlist patterns: - pattern: | const $LOCAL = resolveLocalMediaPath(...); ... const $FS = await import("node:fs/promises"); ... const $DATA = await $FS.readFile($LOCAL); - pattern-not: | const $SAFE = await assertLocalMediaPathAllowed(...); ... const $DATA = $SAFE.data; - id: ghsa-v3j7-34xh-6g3w.loopback-cdp-probe-copies-relay-auth-headers message: Loopback CDP discovery/probe code should not merge extension relay auth headers into generic HTTP headers. This can leak a gateway-derived relay token to any local /json/version listener. severity: ERROR languages: - typescript - javascript patterns: - pattern-either: - pattern: | const $RELAY = $GET($URL); ... const $MERGED = { ...$RELAY, ...$HEADERS }; - pattern: | const $MERGED = { ...$GET($URL), ...$HEADERS }; - metavariable-regex: metavariable: $GET regex: ^(getChromeExtensionRelayAuthHeaders|.*relay.*Headers|.*relay.*Auth.*)$ metadata: category: security confidence: medium ghsa: GHSA-V3J7-34XH-6G3W detector: A advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-V3J7-34XH-6G3W detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: loopback-cdp-probe-copies-relay-auth-headers - id: ghsa-v3qc-wrwx-j3pw.openclaw.gateway.config-write.missing-protected-path-guard languages: - typescript - javascript severity: ERROR message: Sensitive gateway config writes should call assertGatewayConfigMutationAllowed before forwarding config.apply/config.patch. patterns: - pattern-either: - pattern: | if ($ACTION === "config.apply") { ... $RESULT = await callGatewayTool("config.apply", $OPTS, $PARAMS); ... } - pattern: | if ($ACTION === "config.patch") { ... $RESULT = await callGatewayTool("config.patch", $OPTS, $PARAMS); ... } - pattern-not-inside: | if ($ACTION === $KIND) { ... assertGatewayConfigMutationAllowed(...); ... $RESULT = await callGatewayTool($KIND, $OPTS, $PARAMS); ... } metadata: ghsa: GHSA-V3QC-WRWX-J3PW advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-V3QC-WRWX-J3PW detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.gateway.config-write.missing-protected-path-guard - id: ghsa-v6x2-2qvm-6gv8.prompt-hash-secret-falls-back-to-gateway-auth-token languages: - typescript - javascript severity: WARNING message: Prompt or owner-display hashing secret falls back to gateway auth or remote tokens, reusing an auth secret across trust domains. metadata: category: security confidence: medium ghsa: GHSA-V6X2-2QVM-6GV8 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-V6X2-2QVM-6GV8 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: prompt-hash-secret-falls-back-to-gateway-auth-token patterns: - pattern-either: - pattern: | ownerDisplaySecret: $CFG?.commands?.ownerDisplaySecret ?? $CFG?.gateway?.auth?.token ?? $CFG?.gateway?.remote?.token - pattern: | ownerDisplaySecret: $CFG?.commands?.ownerDisplaySecret || $CFG?.gateway?.auth?.token || $CFG?.gateway?.remote?.token - pattern: | $CFG?.commands?.ownerDisplaySecret?.trim() || $CFG?.gateway?.auth?.token?.trim() || $CFG?.gateway?.remote?.token?.trim() - pattern: | $X.hashSecret || $X.auth?.token || $X.remoteToken - pattern: | $X.hashSecret || $X.auth.token || $X.remoteToken - id: ghsa-v865-p3gq-hw6m.repeated-decode-without-limit-anomaly-check languages: - typescript - javascript severity: WARNING message: Repeated path decode loops should enforce a decode-depth anomaly check before treating the path as safe for auth decisions. patterns: - pattern-inside: | function $F(...){ ... } - pattern: | for (let $PASS = 0; $PASS < $LIMIT; $PASS++) { ... $NEXT = decodeURIComponent($DECODED); ... } - pattern-not-inside: | function $F(...){ ... $ANOMALY = decodeURIComponent($DECODED) !== $DECODED; ... } metadata: confidence: medium rationale: catches bounded repeated-decode canonicalizers that never fail closed on leftover encodings ghsa: GHSA-V865-P3GQ-HW6M advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-V865-P3GQ-HW6M detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: repeated-decode-without-limit-anomaly-check - id: ghsa-v8cg-4474-49v8.openclaw-slack-system-event-missing-sender-authorization languages: - typescript severity: WARNING message: Slack member/message subtype handler enqueues a system event without first resolving sender authorization via authorizeAndResolveSlackSystemEventContext(). Unauthorized Slack users can otherwise inject trusted system events. See GHSA-V8CG-4474-49V8. metadata: ghsa: GHSA-V8CG-4474-49V8 category: security cwe: - CWE-862 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-V8CG-4474-49V8 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-slack-system-event-missing-sender-authorization paths: include: - extensions/slack/src/monitor/events/members.ts - extensions/slack/src/monitor/events/messages.ts - src/slack/monitor/events/members.ts - src/slack/monitor/events/messages.ts patterns: - pattern: enqueueSystemEvent(...) - pattern-not-inside: | ... authorizeAndResolveSlackSystemEventContext(...) ... enqueueSystemEvent(...) - id: ghsa-v8wv-jg3q-qwpq.outbound-media-alias-not-normalized languages: - typescript - javascript severity: ERROR message: Sandbox media normalization or attachment hydration handles canonical media/path keys but omits mediaUrl/fileUrl aliases, which can bypass local root validation. paths: include: - src/infra/outbound/*.ts pattern-either: - patterns: - pattern: | const $KEYS: Array<"media" | "path" | "filePath"> = ["media", "path", "filePath"]; - pattern-not: | const $ANY = ["media", "path", "filePath", "mediaUrl", "fileUrl"] - patterns: - pattern: | const $MEDIA = readStringParam($ARGS, "media", { trim: false }); ... const $FILE = readStringParam($ARGS, "path", { trim: false }) ?? readStringParam($ARGS, "filePath", { trim: false }); - pattern-not: | readStringParam($ARGS, "mediaUrl", { trim: false }) - pattern-not: | readStringParam($ARGS, "fileUrl", { trim: false }) metadata: ghsa: GHSA-V8WV-JG3Q-QWPQ advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-V8WV-JG3Q-QWPQ detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: outbound-media-alias-not-normalized - id: ghsa-vfg3-pqpq-93m4.openclaw-tlon-cites-before-final-auth-general message: Cite expansion happens before a final DM or channel authorization decision. severity: WARNING languages: - typescript - javascript patterns: - pattern-either: - pattern: | const $CITED = await resolveAllCites($CONTENT); ... if (!isDmAllowed($SENDER, $ALLOWLIST)) { ... return; } - pattern: | const $CITED = await resolveAllCites($CONTENT); ... const { mode, allowedShips } = resolveChannelAuthorization($CFG, $NEST, $SETTINGS); ... if (mode === "restricted") { ... if (!$ALLOWED.includes($SENDER)) { ... return; } } metadata: ghsa: GHSA-VFG3-PQPQ-93M4 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-VFG3-PQPQ-93M4 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-tlon-cites-before-final-auth-general - id: ghsa-vfw7-6rhc-6xxg.openclaw.cli-backend-unsanitized-env-merge languages: - typescript - javascript severity: ERROR message: Unsanitized env merge passed to child-process spawn. Workspace-config-derived env vars can override host vars and lead to code execution. Sanitize via sanitizeHostExecEnv() first. See GHSA-VFW7-6RHC-6XXG. metadata: ghsa: GHSA-VFW7-6RHC-6XXG category: security cwe: - CWE-77 - CWE-426 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-VFW7-6RHC-6XXG detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.cli-backend-unsanitized-env-merge patterns: - pattern-either: - pattern: | const $ENV = { ...process.env, ...$BACKEND.env }; - pattern: | const $ENV = Object.assign({}, process.env, $BACKEND.env); - pattern: | let $ENV = { ...process.env, ...$BACKEND.env }; - pattern: | const $ENV = { ...process.env, ...$BACKEND.env, ...$EXTRA }; - pattern-either: - pattern-inside: | function $F(...) { ... spawn($CMD, $ARGS, { ..., env: $ENV, ... }) ... } - pattern-inside: | function $F(...) { ... spawnSync($CMD, $ARGS, { ..., env: $ENV, ... }) ... } - pattern-inside: | function $F(...) { ... spawn($CMD, $ARGS, { ..., env: $ENV }) ... } - pattern-inside: | ($CTX) => { ... spawn($CMD, $ARGS, { ..., env: $ENV, ... }) ... } - pattern-inside: | ($CTX) => { ... return spawn($CMD, $ARGS, { ..., env: $ENV, ... }) ... } - pattern-inside: | return spawn($CMD, $ARGS, { ..., env: $ENV, ... }) - pattern-not-inside: | $ENV = sanitizeHostExecEnv($X); - id: ghsa-vj3g-5px3-gr46.openclaw.untrusted-feishu-key-or-skill-name-into-temp-path-join languages: - typescript - javascript severity: WARNING message: | Untrusted name/identifier from an external source flows into a path.join() call rooted at a temp/sandbox/skill destination, without passing through a validated containment helper. This is the bug class behind CVE-style path-traversal advisories where an attacker-controlled value escapes the intended directory. metadata: category: security cwe: - CWE-22 ghsas: - GHSA-VJ3G-5PX3-GR46 - GHSA-XW4P-PW82-HQR7 ghsa: GHSA-VJ3G-5PX3-GR46 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-VJ3G-5PX3-GR46 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw.untrusted-feishu-key-or-skill-name-into-temp-path-join mode: taint pattern-sources: - patterns: - pattern-either: - pattern: $X.imageKey - pattern: $X.fileKey - pattern: $X.image_key - pattern: $X.file_key - pattern: | const { ..., imageKey, ... } = $RESP; - pattern: | const { ..., fileKey, ... } = $RESP; - pattern: | const { ..., image_key, ... } = $RESP; - pattern: | const { ..., file_key, ... } = $RESP; - pattern: $X.skill.name - pattern: $X.skill.id - pattern: $X.frontmatter.$Y pattern-sanitizers: - patterns: - pattern-either: - pattern: sanitizeTempFileName(...) - pattern: withTempDownloadPath(...) - pattern: createTempDownloadTarget(...) - pattern: resolveSandboxPath(...) - pattern: resolvePathWithinRoot(...) - pattern: resolveWritablePathWithinRoot(...) - pattern: isPathInside(...) pattern-sinks: - patterns: - pattern-either: - pattern: path.join($TMP, ...) - pattern: path.resolve($TMP, ...) - id: ghsa-vmqr-rc7x-3446.openclaw-safe-bins-external-helper-flag languages: - typescript - javascript severity: WARNING message: safeBins sort profiles must deny --compress-program instead of allowing it as a value-bearing option, because the flag launches an external helper. pattern-regex: (?s)sort\s*:\s*\{.*?valueFlags\s*:\s*\[[^\]]*["\']--compress-program["\'][^\]]*\] metadata: ghsa: GHSA-VMQR-RC7X-3446 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-VMQR-RC7X-3446 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-safe-bins-external-helper-flag - id: ghsa-vvgp-4c28-m3jm.trusted-proxy-control-ui-bypass-without-operator-role message: Trusted-proxy Control UI pairing bypass should require an explicit operator-role guard on the trustedProxyAuthOk helper. severity: ERROR languages: - typescript - javascript patterns: - pattern: | const $TP = isControlUi && ... && $MODE === "trusted-proxy" && ... && $AUTH_METHOD === "trusted-proxy"; - pattern-not: | const $TP = isControlUi && ... && $ROLE === "operator" && ... && $MODE === "trusted-proxy" && ... && $AUTH_METHOD === "trusted-proxy"; metadata: ghsa: GHSA-VVGP-4C28-M3JM advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-VVGP-4C28-M3JM detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: trusted-proxy-control-ui-bypass-without-operator-role - id: ghsa-vw3h-q6xq-jjm5.websocket-missing-maxpayload-noserver languages: - typescript - javascript severity: WARNING message: WebSocketServer created with noServer but without maxPayload; unauthenticated oversized frames may reach application parsing. patterns: - pattern: | new WebSocketServer({ ..., noServer: true, ... }) - pattern-not: | new WebSocketServer({ ..., noServer: true, ..., maxPayload: $MAX, ... }) metadata: category: security cwe: - CWE-400 - CWE-770 ghsa: GHSA-VW3H-Q6XQ-JJM5 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-VW3H-Q6XQ-JJM5 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: websocket-missing-maxpayload-noserver - id: ghsa-w235-x559-36mg.docker-workspace-mount-ro-guard languages: - typescript - javascript severity: WARNING message: Workspace bind mount uses a conditional :ro suffix tied to an extra equality check instead of directly enforcing non-rw access. patterns: - pattern: | const $SUFFIX = $ACCESS === "ro" && $SRC === $OTHER ? ":ro" : ""; - pattern-inside: | ... $ARGS.push("-v", `${$SRC}:$DEST${$SUFFIX}`) metadata: category: security confidence: medium cwe: CWE-250 ghsa: GHSA-W235-X559-36MG advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-W235-X559-36MG detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: docker-workspace-mount-ro-guard - id: ghsa-w235-x559-36mg.docker-workspace-mount-ro-guard-let languages: - typescript - javascript severity: WARNING message: Workspace bind mount uses a conditional :ro suffix tied to an extra equality check instead of directly enforcing non-rw access. patterns: - pattern: | let $SUFFIX = $ACCESS === "ro" && $SRC === $OTHER ? ":ro" : ""; - pattern-inside: | ... $ARGS.push("-v", `${$SRC}:$DEST${$SUFFIX}`) metadata: category: security confidence: medium cwe: CWE-250 ghsa: GHSA-W235-X559-36MG advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-W235-X559-36MG detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: docker-workspace-mount-ro-guard-let - id: ghsa-w45g-5746-x9fp.openclaw-unguarded-cron-webhook-fetch languages: - typescript - javascript severity: ERROR message: Cron webhook delivery should use fetchWithSsrFGuard instead of direct fetch to avoid SSRF bypasses. patterns: - pattern-inside: | if ($TARGET && $EVENT.summary) { ... } - pattern-either: - pattern: | fetch($TARGET.url, { ... }) - pattern: | await fetch($TARGET.url, { ... }) - pattern-not-inside: | fetchWithSsrFGuard({ ... }) - metavariable-regex: metavariable: $TARGET regex: .*[Ww]ebhook.* metadata: category: security cwe: "CWE-918: Server-Side Request Forgery (SSRF)" ghsa: GHSA-W45G-5746-X9FP advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-W45G-5746-X9FP detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-unguarded-cron-webhook-fetch - id: ghsa-w76h-8m22-hpgh.msteams-shared-link-canonicalization-missing message: MSTeams attachment URLs should be canonicalized with tryBuildGraphSharesUrlForSharedLink before direct use as a download candidate URL. severity: WARNING languages: - typescript - javascript paths: include: - extensions/msteams/src/attachments/*.ts patterns: - pattern: | return { ..., url: $URL, ... }; - metavariable-pattern: metavariable: $URL patterns: - pattern-either: - pattern: contentUrl - pattern: $ATT.contentUrl - pattern-not-inside: | const $GRAPH = tryBuildGraphSharesUrlForSharedLink(...); ... return { ..., url: $GRAPH, ... }; metadata: category: security cwe: CWE-918 ghsa: GHSA-W76H-8M22-HPGH rationale: Directly returning MSTeams attachment contentUrl as a download candidate without Graph shared-link canonicalization can bypass the intended media host restrictions. advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-W76H-8M22-HPGH detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: msteams-shared-link-canonicalization-missing - id: ghsa-w7j5-j98m-w679.dockerfile-missing-user-directive languages: - dockerfile severity: WARNING message: Dockerfile appears to omit any runtime USER directive, so the final runtime user may stay root/default. metadata: ghsa: GHSA-W7J5-J98M-W679 detector: A category: security cwe: CWE-250 confidence: medium advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-W7J5-J98M-W679 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: dockerfile-missing-user-directive paths: include: - "**/Dockerfile" - "**/Dockerfile.*" exclude: - "**/vendor/**" pattern-regex: (?s)\AFROM\b(?:(?!\nUSER\b).)*\Z - id: ghsa-w9j9-w4cp-6wgr.openclaw-host-exec-manual-env-merge languages: - typescript - javascript severity: WARNING message: Manual host-exec env merging that only blocks PATH can miss dangerous interpreter or startup env vars; use centralized host env sanitization. patterns: - pattern-either: - pattern: | for (const [$RAW, $VALUE] of Object.entries($OVERRIDES)) { ... const $KEY = $RAW.trim(); ... const $UPPER = $KEY.toUpperCase(); ... if ($UPPER === "PATH") { continue; } ... $MERGED[$KEY] = $VALUE; ... } - pattern: | for (const [$RAW, $VALUE] of Object.entries($OVERRIDES)) { ... const $UPPER = $RAW.toUpperCase(); ... if ($UPPER === "PATH") { continue; } ... $MERGED[$RAW] = $VALUE; ... } - pattern-not-inside: | if (isDangerousHostEnvVarName(...)) { ... } - pattern-not-inside: | if (blockedEnvKeys.has(...)) { ... } - pattern-not-inside: | if (blockedEnvPrefixes.some(($PREFIX) => ...)) { ... } paths: include: - "**/*.ts" - "**/*.js" metadata: ghsa: GHSA-W9J9-W4CP-6WGR advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-W9J9-W4CP-6WGR detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-host-exec-manual-env-merge - id: ghsa-wh94-p5m6-mr7j.openclaw-discord-moderation-dispatch-missing-sender-permission-check languages: - typescript severity: WARNING message: Discord moderation action dispatches timeout/kick/ban without verifySenderModerationPermission(). See GHSA-WH94-P5M6-MR7J. metadata: ghsa: GHSA-WH94-P5M6-MR7J category: security cwe: - CWE-862 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-WH94-P5M6-MR7J detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-discord-moderation-dispatch-missing-sender-permission-check paths: include: - extensions/discord/src/actions/runtime.moderation.ts - src/agents/tools/discord-actions-moderation.ts patterns: - pattern-either: - pattern: timeoutMemberDiscord(...) - pattern: kickMemberDiscord(...) - pattern: banMemberDiscord(...) - pattern-not-inside: | ... verifySenderModerationPermission(...) ... - id: ghsa-wj55-88gf-x564.queued-node-action-delivery-without-current-policy-recheck message: Pending node actions are delivered from the raw queue without current-policy revalidation. severity: WARNING languages: - typescript - javascript patterns: - pattern: | const $PENDING = listPendingNodeActions($NODE_ID); - pattern-not-inside: | const $PENDING = listPendingNodeActions($NODE_ID); ... const $ALLOWED = $PENDING.filter((entry) => { ... const $RESULT = isNodeCommandAllowed(...); ... }); metadata: category: security ghsa: GHSA-WJ55-88GF-X564 bug_family: stale-queued-node-actions advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-WJ55-88GF-X564 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: queued-node-action-delivery-without-current-policy-recheck - id: ghsa-wq58-2pvg-5h4f.gateway-http-json-endpoint-missing-required-operator-method languages: - typescript - javascript severity: ERROR message: Gateway HTTP handlers that call handleGatewayPostJsonEndpoint should set requiredOperatorMethod when the endpoint mutates chat/session state. patterns: - pattern-either: - pattern: | handleGatewayPostJsonEndpoint($REQ, $RES, { ..., pathname: "/v1/chat/completions", ... }) - pattern: | handleGatewayPostJsonEndpoint($REQ, $RES, { ..., pathname: "/v1/responses", ... }) - pattern: | const $HANDLED = await handleGatewayPostJsonEndpoint($REQ, $RES, { ..., pathname: "/v1/chat/completions", ... }) - pattern: | const $HANDLED = await handleGatewayPostJsonEndpoint($REQ, $RES, { ..., pathname: "/v1/responses", ... }) - pattern-not: | handleGatewayPostJsonEndpoint($REQ, $RES, { ..., requiredOperatorMethod: $METHOD, ... }) - pattern-not: | const $HANDLED = await handleGatewayPostJsonEndpoint($REQ, $RES, { ..., requiredOperatorMethod: $METHOD, ... }) metadata: category: authorization confidence: medium review: family-detector ghsa: GHSA-WQ58-2PVG-5H4F advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-WQ58-2PVG-5H4F detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: gateway-http-json-endpoint-missing-required-operator-method - id: ghsa-x2m8-53h4-6hch.discord-voice-ingress-missing-authorize-review message: Discord voice ingress forwards senderIsOwner to agentCommandFromIngress without calling authorizeDiscordVoiceIngress in the same file. See GHSA-X2M8-53H4-6HCH. severity: ERROR languages: - typescript metadata: ghsa: GHSA-X2M8-53H4-6HCH category: authorization cwe: - CWE-863 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-X2M8-53H4-6HCH detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: discord-voice-ingress-missing-authorize-review paths: include: - extensions/discord/src/voice/** patterns: - pattern: agentCommandFromIngress(...) - pattern-not-inside: | import { ..., authorizeDiscordVoiceIngress, ... } from "$X"; ... - pattern-not-inside: | import { authorizeDiscordVoiceIngress } from "$X"; ... - pattern-not-inside: | import { authorizeDiscordVoiceIngress, ... } from "$X"; ... - id: ghsa-x9cf-3w63-rpq9.openclaw-remote-media-direct-scp-without-source-policy languages: - typescript severity: ERROR message: Remote media staging directly scpFile()s `source` from MediaRemoteHost. The source must first be checked against remote attachment roots via isAllowedSourcePath(). See GHSA-X9CF-3W63-RPQ9. metadata: ghsa: GHSA-X9CF-3W63-RPQ9 category: security cwe: - CWE-22 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-X9CF-3W63-RPQ9 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-remote-media-direct-scp-without-source-policy paths: include: - src/auto-reply/reply/stage-sandbox-media.ts pattern-regex: scpFile\(ctx\.MediaRemoteHost,\s*source,\s*dest\) - id: ghsa-xhq5-45pm-2gjr.nextcloud-talk-room-name-fallback-match message: Nextcloud Talk room authorization must match on the stable roomToken only — display names are collidable across rooms and let an attacker with create-room permission bypass the allowlist by reusing an allowed room's name. See GHSA-XHQ5-45PM-2GJR. severity: ERROR languages: - typescript - javascript metadata: ghsa: GHSA-XHQ5-45PM-2GJR category: authorization cwe: - CWE-863 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-XHQ5-45PM-2GJR detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: nextcloud-talk-room-name-fallback-match paths: include: - extensions/nextcloud-talk/src/** patterns: - pattern-either: - pattern: buildChannelKeyCandidates($TOKEN, $ROOM_NAME, ...) - pattern: buildChannelKeyCandidates($TOKEN, ..., normalizeChannelSlug($ROOM_NAME)) - pattern: buildChannelKeyCandidates($TOKEN, ..., $ROOM_NAME, ...) - id: ghsa-xp9r-prpg-373r.openclaw-browser-request-reset-profile-mutation languages: - typescript message: browser.request mutation guards should treat POST /reset-profile like other persistent-profile mutations severity: ERROR patterns: - pattern-either: - pattern: | if ($METHOD === "POST" && $PATH === "/profiles/create") { ... } - pattern: | if ($METHOD === "POST" && $PATH == "/profiles/create") { ... } - pattern: | if ($METHOD === "POST" && $PATH === "/profiles/create") return ...; - pattern: | if ($METHOD === "POST" && $PATH == "/profiles/create") return ...; - pattern-not-inside: | if ( $METHOD === "POST" && ($PATH === "/profiles/create" || $PATH === "/reset-profile") ) { ... } - pattern-not-inside: | if ( $METHOD == "POST" && ($PATH == "/profiles/create" || $PATH == "/reset-profile") ) { ... } - pattern-not: | if ($METHOD === "POST" && ($PATH === "/profiles/create" || $PATH === "/reset-profile")) { ... } - pattern-not: | if ($METHOD == "POST" && ($PATH == "/profiles/create" || $PATH == "/reset-profile")) { ... } metadata: category: security cwe: CWE-863 ghsa: GHSA-XP9R-PRPG-373R advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-XP9R-PRPG-373R detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: openclaw-browser-request-reset-profile-mutation - id: ghsa-xwcj-hwhf-h378.media-fetch-logs-unredacted-url languages: - typescript - javascript severity: ERROR message: Error messages should redact URL values before embedding them in media-fetch failures. patterns: - pattern-either: - pattern: | new MediaFetchError($CODE, `Failed to fetch media from ${$URL}: ${...}`) - pattern: | new MediaFetchError($CODE, `Failed to fetch media from ${$URL}${$REST}: ${...}`) - metavariable-pattern: metavariable: $URL patterns: - pattern-not: sourceUrl - pattern-not: redactMediaUrl(...) metadata: category: security ghsa: GHSA-XWCJ-HWHF-H378 detector: A advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-XWCJ-HWHF-H378 detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: media-fetch-logs-unredacted-url - id: ghsa-xwjm-j929-xq7c.browser-download-route-missing-resolve-writable-output-path message: Browser download route handler calls Playwright download without resolving the path through the temp-downloads-root gate. An authenticated CLI/RPC caller can supply a path that traverses outside the temp downloads dir, leading to arbitrary file write. See GHSA-XWJM-J929-XQ7C. severity: ERROR languages: - typescript metadata: ghsa: GHSA-XWJM-J929-XQ7C category: security cwe: - CWE-22 advisory-url: https://github.com/openclaw/openclaw/security/advisories/GHSA-XWJM-J929-XQ7C detector-bucket: precise source-run: 2026-04-17T07-37-10Z source-rule-id: browser-download-route-missing-resolve-writable-output-path paths: include: - extensions/browser/src/browser/routes/**.ts - src/browser/routes/**.ts patterns: - pattern-either: - pattern: pw.waitForDownloadViaPlaywright(...) - pattern: pw.downloadViaPlaywright(...) - pattern-not-inside: | import { ..., resolveWritableOutputPathOrRespond, ... } from "$X"; ... - pattern-not-inside: | import { resolveWritableOutputPathOrRespond } from "$X"; ... - pattern-not-inside: | import { resolveWritableOutputPathOrRespond, ... } from "$X"; ... - pattern-not-inside: | import { ..., resolvePathWithinRoot, ... } from "$X"; ... - pattern-not-inside: | import { resolvePathWithinRoot } from "$X"; ... - pattern-not-inside: | import { resolvePathWithinRoot, ... } from "$X"; ... - id: openclaw-policy-raw-http2-connect.no-raw-http2-connect languages: - typescript - javascript severity: ERROR message: Use connectApnsHttp2Session() from src/infra/push-apns-http2.ts instead of raw http2.connect() so APNs HTTP/2 honors managed proxy policy. metadata: advisory-id: OPENCLAW-POLICY-RAW-HTTP2-CONNECT advisory-url: https://github.com/openclaw/openclaw/pull/74905 cwe: - CWE-441 category: security confidence: HIGH detector-bucket: precise source-rule-id: no-raw-http2-connect source-file: security/opengrep/rules/openclaw-policy/no-raw-http2-connect.yml paths: include: - src/**/*.ts - src/**/*.mts - src/**/*.js - src/**/*.mjs - extensions/**/*.ts - extensions/**/*.mts - extensions/**/*.js - extensions/**/*.mjs exclude: - src/infra/push-apns-http2.ts - "**/*.test.ts" - "**/*.test.mts" - "**/*.test.js" - "**/*.test.mjs" patterns: - pattern: http2.connect(...)