Files
openclaw/security/opengrep/precise.yml
Jesse Merhi 6de9d71bfb feat(security): add GHSA detector-review pipeline and OpenGrep CI workflows (#69483)
* feat(security): add GHSA detector-review pipeline and OpenGrep CI workflows [AI-assisted]

Stand up an end-to-end pipeline that turns every published openclaw GitHub
Security Advisory into a reusable OpenGrep rule, and wire the compiled rules
into manual-dispatch GitHub Actions workflows that publish SARIF to GitHub
Code Scanning.

The pipeline is harness-agnostic: any coding-agent CLI (Rovo Dev, Claude
Code, Codex, OpenCode, or anything you can shell out to) can drive it via
the runner script's --harness flag. Built-in adapters cover the four common
harnesses; --harness-cmd '<template>' supports anything else with shell-style
{prompt}/{model}/{output_file} substitution.

Pipeline pieces:

- scripts/run-ghsa-detector-review-batch.mjs runs your chosen coding harness
  in parallel against every advisory using the agent-agnostic detector-review
  spec at security/detector-review/detector-review-spec.md. Each case
  produces an opengrep general-rule.yml (precise) and broad-rule.yml
  (review-aid), plus a coverage-validated report against the vulnerable
  commit's changed files.
- scripts/compile-opengrep-rules.mjs walks a run directory, rewrites each
  rule's id to ghsa-detector.<ghsa>.<orig-id>, injects ghsa/advisory-url/
  detector-bucket/source-rule-id metadata, and uses opengrep itself to drop
  rules with InvalidRuleSchemaError so the published super-configs load
  cleanly.

Compiled outputs:

- security/opengrep/precise.yml     (336 rules)
- security/opengrep/broad.yml       (459 rules)
- security/opengrep/compile-manifest.json    (per-rule provenance map)

CI workflows (manual workflow_dispatch only):

- .github/workflows/opengrep-precise.yml
- .github/workflows/opengrep-broad.yml

Both install a pinned opengrep, run opengrep scan against src/, upload SARIF
to Code Scanning under categories opengrep-precise / opengrep-broad, and use
continue-on-error: true so findings never block the workflow.

Detector-review spec and assets:

- security/detector-review/detector-review-spec.md   the agent-agnostic spec
  the runner injects into each per-case prompt
- security/detector-review/references/{detector-rubric,report-template}.md
- security/detector-review/scripts/init_case.py
- security/prompt-suffix-coverage-first.md   mandatory prompt addendum that
  enforces coverage-first validation (rule must catch the OG vuln, not just
  pass synthetic fixtures)

Docs:

- security/README.md          end-to-end flow, supported harnesses, regen recipe
- security/opengrep/README.md compiled-config details + recompile recipe

* security: tighten GHSA OpenGrep detector workflow

* chore: refine precise opengrep workflow

* chore: remove stale opengrep metadata

* fix: harden GHSA OpenGrep workflow

* ci: split OpenGrep diff and full scans

* chore: remove performance-only opengrep rule

* ci: use OpenGrep installer path

* chore: enforce opengrep rule metadata provenance

* chore: generalize opengrep rule compilation

* docs: align opengrep rulepack guidance

* chore: support generic opengrep rule sources

* fix: validate opengrep rulepack-only changes

---------

Co-authored-by: Jesse Merhi <security-engineering@atlassian.com>
2026-04-30 02:42:20 +10:00

4979 lines
186 KiB
YAML

# 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: <unknown>
# Generated at : 2026-04-29T07:10:35.427Z
# Rule count : 147
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/<email> entries as email matches; that mixes a mutable email principal into a users/<id> 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<Ipv6Range>([
...
]);
- pattern-not: |
const BLOCKED_IPV6_SPECIAL_USE_RANGES = new Set<Ipv6Range>([
...,
"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<ReturnType<ipaddr.IPv6["range"]>>([
...
]);
- pattern-not: |
const BLOCKED_IPV6_SPECIAL_USE_RANGES = new Set<ReturnType<ipaddr.IPv6["range"]>>([
...,
"discard",
...
]);
- patterns:
- pattern: |
const BLOCKED_IPV6_SPECIAL_USE_RANGES = new Set<ReturnType<ipaddr.IPv6['range']>>([
...
]);
- pattern-not: |
const BLOCKED_IPV6_SPECIAL_USE_RANGES = new Set<ReturnType<ipaddr.IPv6['range']>>([
...,
"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";
...