@poolzin/pool-bot 2026.2.21 → 2026.2.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/agents/api-key-rotation.js +47 -0
- package/dist/agents/apply-patch-update.js +19 -9
- package/dist/agents/apply-patch.js +72 -47
- package/dist/agents/bash-tools.exec.js +141 -559
- package/dist/agents/cli-backends.js +49 -6
- package/dist/agents/cli-runner/helpers.js +69 -152
- package/dist/agents/cli-runner.js +70 -19
- package/dist/agents/identity.js +20 -1
- package/dist/agents/image-sanitization.js +9 -0
- package/dist/agents/live-auth-keys.js +123 -26
- package/dist/agents/live-model-filter.js +13 -4
- package/dist/agents/model-catalog.js +40 -9
- package/dist/agents/model-forward-compat.js +60 -23
- package/dist/agents/model-selection.js +134 -41
- package/dist/agents/pi-auth-json.js +2 -2
- package/dist/agents/pi-embedded-helpers/bootstrap.js +65 -15
- package/dist/agents/pi-embedded-helpers/errors.js +140 -15
- package/dist/agents/pi-embedded-helpers/images.js +22 -12
- package/dist/agents/pi-embedded-helpers.js +2 -2
- package/dist/agents/pi-embedded-runner/abort.js +10 -3
- package/dist/agents/pi-embedded-runner/compact.js +230 -32
- package/dist/agents/pi-embedded-runner/extra-params.js +203 -12
- package/dist/agents/pi-embedded-runner/google.js +109 -19
- package/dist/agents/pi-embedded-runner/history.js +35 -17
- package/dist/agents/pi-embedded-runner/run/attempt.js +386 -95
- package/dist/agents/pi-embedded-runner/run/images.js +81 -55
- package/dist/agents/pi-embedded-runner/run/payloads.js +89 -39
- package/dist/agents/pi-embedded-runner/run.js +193 -25
- package/dist/agents/pi-embedded-runner/run.overflow-compaction.mocks.shared.js +2 -2
- package/dist/agents/pi-embedded-runner/runs.js +17 -8
- package/dist/agents/pi-embedded-runner/tool-result-context-guard.js +262 -0
- package/dist/agents/pi-embedded-runner.js +1 -1
- package/dist/agents/pi-embedded-subscribe.handlers.tools.js +180 -10
- package/dist/agents/pi-embedded-subscribe.js +37 -0
- package/dist/agents/pi-embedded-subscribe.tools.js +127 -30
- package/dist/agents/pi-model-discovery.js +9 -2
- package/dist/agents/pi-tool-definition-adapter.js +60 -8
- package/dist/agents/pi-tools.before-tool-call.js +1 -1
- package/dist/agents/pi-tools.js +113 -94
- package/dist/agents/pi-tools.read.js +337 -38
- package/dist/agents/poolbot-tools.js +14 -5
- package/dist/agents/sandbox/docker.js +10 -5
- package/dist/agents/sandbox/registry.js +96 -46
- package/dist/agents/sandbox/sanitize-env-vars.js +82 -0
- package/dist/agents/sandbox-paths.js +43 -10
- package/dist/agents/session-tool-result-guard-wrapper.js +23 -11
- package/dist/agents/session-tool-result-guard.js +39 -39
- package/dist/agents/session-transcript-repair.js +36 -33
- package/dist/agents/session-write-lock.js +62 -44
- package/dist/agents/skills/frontmatter.js +49 -88
- package/dist/agents/skills/workspace.js +335 -28
- package/dist/agents/subagent-announce.js +508 -174
- package/dist/agents/subagent-registry.js +45 -4
- package/dist/agents/subagent-spawn.js +16 -33
- package/dist/agents/system-prompt-report.js +27 -10
- package/dist/agents/system-prompt.js +26 -32
- package/dist/agents/tool-call-id.js +69 -17
- package/dist/agents/tool-display-common.js +1 -1
- package/dist/agents/tool-images.js +64 -31
- package/dist/agents/tools/canvas-tool.js +17 -11
- package/dist/agents/tools/common.js +37 -19
- package/dist/agents/tools/cron-tool.js +40 -38
- package/dist/agents/tools/gateway.js +70 -2
- package/dist/agents/tools/message-tool.js +181 -40
- package/dist/agents/tools/nodes-tool.js +128 -36
- package/dist/agents/tools/nodes-utils.js +12 -38
- package/dist/agents/tools/session-status-tool.js +24 -71
- package/dist/agents/tools/sessions-helpers.js +38 -210
- package/dist/agents/tools/sessions-spawn-tool.js +28 -198
- package/dist/agents/tools/telegram-actions.js +58 -7
- package/dist/agents/tools/web-fetch-utils.js +112 -7
- package/dist/agents/tools/web-fetch.js +279 -175
- package/dist/agents/tools/web-shared.js +71 -8
- package/dist/agents/usage.js +25 -16
- package/dist/auto-reply/commands-registry.data.js +85 -11
- package/dist/auto-reply/dispatch.js +40 -21
- package/dist/auto-reply/reply/abort.js +102 -33
- package/dist/auto-reply/reply/commands-core.js +82 -33
- package/dist/auto-reply/reply/commands-export-session.js +1 -1
- package/dist/auto-reply/reply/commands-info.js +41 -12
- package/dist/auto-reply/reply/commands-subagents.js +352 -100
- package/dist/auto-reply/reply/commands-system-prompt.js +2 -2
- package/dist/auto-reply/reply/dispatch-from-config.js +100 -29
- package/dist/auto-reply/reply/elevated-unavailable.js +1 -1
- package/dist/auto-reply/reply/inbound-meta.js +12 -1
- package/dist/auto-reply/reply/mentions.js +18 -11
- package/dist/auto-reply/reply/normalize-reply.js +17 -8
- package/dist/auto-reply/reply/reply-dispatcher.js +62 -10
- package/dist/auto-reply/reply/session.js +102 -21
- package/dist/auto-reply/reply/streaming-directives.js +16 -5
- package/dist/auto-reply/status.js +73 -50
- package/dist/browser/extension-relay.js +3 -3
- package/dist/browser/http-auth.js +1 -1
- package/dist/browser/paths.js +2 -2
- package/dist/build-info.json +3 -3
- package/dist/channels/allowlist-match.js +20 -0
- package/dist/channels/allowlists/resolve-utils.js +65 -2
- package/dist/channels/chat-type.js +8 -4
- package/dist/channels/dock.js +127 -35
- package/dist/channels/draft-stream-loop.js +6 -2
- package/dist/channels/plugins/actions/telegram.js +42 -18
- package/dist/channels/plugins/allowlist-match.js +1 -1
- package/dist/channels/plugins/group-mentions.js +51 -41
- package/dist/channels/plugins/message-action-names.js +2 -0
- package/dist/channels/plugins/message-actions.js +24 -5
- package/dist/channels/plugins/normalize/discord.js +26 -4
- package/dist/channels/plugins/normalize/signal.js +35 -22
- package/dist/channels/plugins/onboarding/helpers.js +8 -26
- package/dist/channels/plugins/outbound/imessage.js +15 -14
- package/dist/channels/registry.js +20 -7
- package/dist/cli/acp-cli.js +7 -5
- package/dist/cli/browser-cli-extension.js +25 -12
- package/dist/cli/browser-cli-state.cookies-storage.js +25 -6
- package/dist/cli/browser-cli-state.js +101 -145
- package/dist/cli/command-options.js +28 -0
- package/dist/cli/completion-cli.js +6 -6
- package/dist/cli/cron-cli/register.cron-add.js +25 -1
- package/dist/cli/cron-cli/register.cron-edit.js +44 -0
- package/dist/cli/cron-cli/shared.js +7 -1
- package/dist/cli/daemon-cli/lifecycle-core.js +23 -21
- package/dist/cli/daemon-cli/lifecycle.js +23 -247
- package/dist/cli/daemon-cli/register-service-commands.js +25 -4
- package/dist/cli/daemon-cli.js +1 -0
- package/dist/cli/devices-cli.js +33 -20
- package/dist/cli/gateway-cli/register.js +37 -105
- package/dist/cli/gateway-cli/run.js +49 -11
- package/dist/cli/nodes-camera.js +59 -4
- package/dist/cli/nodes-cli/register.camera.js +27 -24
- package/dist/cli/nodes-cli/rpc.js +21 -38
- package/dist/cli/qr-cli.js +2 -2
- package/dist/cli/skills-cli.format.js +2 -2
- package/dist/cli/update-cli/progress.js +2 -2
- package/dist/cli/update-cli/restart-helper.js +28 -7
- package/dist/cli/update-cli/shared.js +7 -7
- package/dist/cli/update-cli/status.js +1 -1
- package/dist/cli/update-cli/update-command.js +14 -8
- package/dist/cli/update-cli/wizard.js +2 -2
- package/dist/cli/update-cli.js +21 -1027
- package/dist/commands/auth-choice.apply.anthropic.js +10 -2
- package/dist/commands/channels/add-mutators.js +3 -35
- package/dist/commands/channels/add.js +39 -51
- package/dist/commands/config-validation.js +1 -1
- package/dist/commands/configure.gateway-auth.js +52 -15
- package/dist/commands/configure.gateway.js +84 -40
- package/dist/commands/doctor-completion.js +3 -3
- package/dist/commands/doctor-config-flow.js +536 -16
- package/dist/commands/doctor-gateway-services.js +103 -79
- package/dist/commands/doctor-memory-search.js +9 -9
- package/dist/commands/doctor-platform-notes.js +57 -30
- package/dist/commands/doctor-prompter.js +26 -15
- package/dist/commands/doctor-session-locks.js +1 -1
- package/dist/commands/doctor.js +21 -9
- package/dist/commands/model-picker.js +120 -95
- package/dist/commands/models/set.js +2 -21
- package/dist/commands/models/shared.js +65 -37
- package/dist/commands/onboard-helpers.js +81 -39
- package/dist/commands/openai-codex-oauth.js +1 -1
- package/dist/commands/sessions.js +52 -53
- package/dist/commands/status.summary.js +52 -34
- package/dist/commands/test-wizard-helpers.js +2 -2
- package/dist/config/defaults.js +79 -42
- package/dist/config/group-policy.js +50 -18
- package/dist/config/includes.js +37 -10
- package/dist/config/schema.help.js +5 -4
- package/dist/config/schema.hints.js +2 -2
- package/dist/config/schema.labels.js +1 -0
- package/dist/config/sessions/group.js +12 -11
- package/dist/config/sessions/paths.js +137 -11
- package/dist/config/sessions/store.js +185 -65
- package/dist/config/sessions/types.js +15 -1
- package/dist/config/sessions.js +1 -0
- package/dist/config/telegram-custom-commands.js +3 -2
- package/dist/config/types.js +2 -0
- package/dist/config/zod-schema.agent-defaults.js +6 -27
- package/dist/config/zod-schema.agent-runtime.js +171 -79
- package/dist/config/zod-schema.providers-core.js +138 -65
- package/dist/config/zod-schema.session.js +49 -22
- package/dist/control-ui/assets/index-HRr1grwl.js.map +1 -1
- package/dist/cron/isolated-agent/run.js +224 -57
- package/dist/cron/normalize.js +48 -45
- package/dist/cron/run-log.js +14 -0
- package/dist/cron/service/jobs.js +190 -28
- package/dist/cron/service/normalize.js +29 -11
- package/dist/cron/service/store.js +30 -44
- package/dist/cron/service/timer.js +182 -96
- package/dist/cron/service.js +3 -0
- package/dist/cron/stagger.js +37 -0
- package/dist/daemon/inspect.js +132 -92
- package/dist/daemon/runtime-paths.js +25 -4
- package/dist/daemon/service-audit.js +47 -16
- package/dist/discord/accounts.js +23 -20
- package/dist/discord/monitor/agent-components.js +1115 -219
- package/dist/discord/monitor/allow-list.js +114 -34
- package/dist/discord/monitor/listeners.js +204 -97
- package/dist/discord/monitor/message-handler.js +21 -10
- package/dist/discord/monitor/message-handler.preflight.js +195 -101
- package/dist/discord/monitor/message-handler.process.js +384 -123
- package/dist/discord/monitor/message-utils.js +86 -23
- package/dist/discord/monitor/native-command.js +77 -57
- package/dist/discord/monitor/provider.js +122 -117
- package/dist/discord/monitor/reply-context.js +20 -16
- package/dist/discord/monitor/reply-delivery.js +40 -8
- package/dist/discord/monitor/rest-fetch.js +22 -0
- package/dist/discord/monitor/threading.js +117 -24
- package/dist/discord/send.js +2 -1
- package/dist/discord/send.outbound.js +124 -11
- package/dist/discord/send.shared.js +112 -72
- package/dist/discord/voice-message.js +3 -3
- package/dist/gateway/auth.js +119 -44
- package/dist/gateway/call.js +76 -34
- package/dist/gateway/channel-health-monitor.js +57 -50
- package/dist/gateway/client.js +63 -29
- package/dist/gateway/control-ui-contract.js +1 -1
- package/dist/gateway/gateway-config-prompts.shared.js +2 -2
- package/dist/gateway/net.js +109 -1
- package/dist/gateway/protocol/index.js +5 -8
- package/dist/gateway/protocol/schema/agent.js +19 -1
- package/dist/gateway/protocol/schema/channels.js +21 -0
- package/dist/gateway/protocol/schema/cron.js +43 -30
- package/dist/gateway/protocol/schema/protocol-schemas.js +6 -11
- package/dist/gateway/protocol/schema/sessions.js +5 -1
- package/dist/gateway/protocol/schema.js +0 -1
- package/dist/gateway/server/presence-events.js +12 -0
- package/dist/gateway/server/ws-connection/message-handler.js +203 -212
- package/dist/gateway/server/ws-connection.js +58 -21
- package/dist/gateway/server-broadcast.js +18 -13
- package/dist/gateway/server-cron.js +177 -10
- package/dist/gateway/server-methods/agent-job.js +131 -38
- package/dist/gateway/server-methods/send.js +60 -14
- package/dist/gateway/server-methods/sessions.js +160 -96
- package/dist/gateway/server-methods/system.js +5 -7
- package/dist/gateway/server-methods-list.js +8 -0
- package/dist/gateway/server-methods.js +24 -8
- package/dist/gateway/server-node-events.js +278 -68
- package/dist/gateway/session-utils.fs.js +316 -75
- package/dist/gateway/session-utils.js +224 -70
- package/dist/gateway/sessions-patch.js +63 -20
- package/dist/gateway/test-temp-config.js +1 -1
- package/dist/gateway/tools-invoke-http.js +118 -70
- package/dist/gateway/ws-log.js +135 -107
- package/dist/hooks/frontmatter.js +36 -82
- package/dist/hooks/install.js +149 -139
- package/dist/hooks/internal-hooks.js +29 -4
- package/dist/hooks/plugin-hooks.js +2 -1
- package/dist/imessage/monitor/deliver.js +10 -4
- package/dist/imessage/monitor/monitor-provider.js +138 -375
- package/dist/imessage/monitor/runtime.js +4 -8
- package/dist/imessage/send.js +65 -19
- package/dist/infra/exec-approvals-allowlist.js +7 -0
- package/dist/infra/exec-approvals.js +35 -920
- package/dist/infra/exec-safe-bin-trust.js +64 -0
- package/dist/infra/heartbeat-runner.js +207 -134
- package/dist/infra/heartbeat-wake.js +183 -22
- package/dist/infra/install-source-utils.js +47 -0
- package/dist/infra/net/ssrf.js +170 -36
- package/dist/infra/outbound/deliver.js +224 -58
- package/dist/infra/outbound/message-action-spec.js +12 -5
- package/dist/infra/outbound/outbound-session.js +27 -25
- package/dist/infra/poolbot-root.js +32 -22
- package/dist/infra/ports.js +14 -11
- package/dist/infra/skills-remote.js +48 -37
- package/dist/infra/system-events.js +25 -11
- package/dist/infra/system-presence.js +26 -33
- package/dist/infra/tmp-poolbot-dir.js +81 -2
- package/dist/infra/wsl.js +37 -1
- package/dist/line/bot-message-context.js +163 -191
- package/dist/logging/subsystem.js +59 -22
- package/dist/markdown/ir.js +124 -50
- package/dist/media/store.js +1 -1
- package/dist/media-understanding/runner.entries.js +42 -25
- package/dist/media-understanding/runner.js +53 -488
- package/dist/memory/embeddings-gemini.js +53 -38
- package/dist/memory/manager-embedding-ops.js +48 -69
- package/dist/pairing/pairing-store.js +178 -119
- package/dist/plugin-sdk/index.js +34 -6
- package/dist/plugins/hooks.js +135 -14
- package/dist/plugins/install.js +190 -152
- package/dist/polls.js +11 -0
- package/dist/routing/resolve-route.js +190 -56
- package/dist/routing/session-key.js +38 -22
- package/dist/runtime.js +35 -9
- package/dist/security/audit-channel.js +1 -1
- package/dist/sessions/session-key-utils.js +29 -11
- package/dist/shared/frontmatter.js +5 -5
- package/dist/shared/node-list-types.js +1 -0
- package/dist/shared/string-normalization.js +15 -0
- package/dist/signal/monitor/event-handler.js +68 -36
- package/dist/signal/send.js +29 -37
- package/dist/slack/monitor/allow-list.js +10 -11
- package/dist/slack/monitor/commands.js +14 -3
- package/dist/slack/monitor/events/interactions.js +4 -4
- package/dist/slack/monitor/media.js +224 -16
- package/dist/slack/monitor/message-handler/dispatch.js +247 -13
- package/dist/slack/monitor/message-handler/prepare.js +128 -45
- package/dist/slack/monitor/slash.js +357 -144
- package/dist/slack/streaming.js +77 -0
- package/dist/telegram/accounts.js +40 -13
- package/dist/telegram/allowed-updates.js +3 -0
- package/dist/telegram/bot/delivery.js +129 -66
- package/dist/telegram/bot/helpers.js +136 -122
- package/dist/telegram/bot-handlers.js +600 -339
- package/dist/telegram/bot-message-context.js +115 -73
- package/dist/telegram/bot-message-dispatch.js +235 -104
- package/dist/telegram/bot-native-command-menu.js +3 -1
- package/dist/telegram/bot-native-commands.js +213 -193
- package/dist/telegram/bot.js +24 -132
- package/dist/telegram/draft-stream.js +84 -75
- package/dist/telegram/format.js +150 -6
- package/dist/telegram/send.js +415 -255
- package/dist/telegram/targets.js +21 -2
- package/dist/telegram/update-offset-store.js +19 -3
- package/dist/terminal/restore.js +5 -2
- package/dist/test-utils/fetch-mock.js +5 -0
- package/dist/version.js +18 -5
- package/dist/web/auto-reply/monitor/broadcast.js +7 -3
- package/dist/web/auto-reply/monitor/on-message.js +6 -3
- package/dist/web/inbound/media.js +34 -8
- package/dist/web/inbound/monitor.js +34 -17
- package/dist/web/inbound/send-api.js +18 -17
- package/dist/web/outbound.js +12 -5
- package/dist/wizard/clack-prompter.js +40 -7
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/device-pair/index.ts +2 -2
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/discord/package.json +1 -1
- package/extensions/feishu/package.json +1 -1
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/irc/src/accounts.ts +1 -1
- package/extensions/irc/src/onboarding.ts +4 -4
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +10 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +10 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +10 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/openai-codex-auth/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/slack/package.json +1 -1
- package/extensions/telegram/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +10 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +10 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +10 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +10 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +1 -1
- package/skills/apple-reminders/SKILL.md +100 -49
- package/skills/coding-agent/SKILL.md +34 -28
- package/skills/github/SKILL.md +131 -16
- package/skills/imsg/SKILL.md +112 -15
- package/skills/openhue/SKILL.md +101 -19
- package/skills/tmux/SKILL.md +111 -79
- package/skills/weather/SKILL.md +88 -25
- package/dist/agents/openclaw-tools.js +0 -151
- package/dist/agents/tool-security.js +0 -96
- package/dist/gateway/url-validation.js +0 -94
- package/dist/infra/openclaw-root.js +0 -109
- package/dist/infra/tmp-openclaw-dir.js +0 -81
- package/dist/media/path-sanitization.js +0 -78
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool Security - Tool Gating and Access Control
|
|
3
|
-
*
|
|
4
|
-
* Based on OpenClaw 2026.2.4 security fixes:
|
|
5
|
-
* - Gate sensitive tools to owner senders only
|
|
6
|
-
* - Prevent tool hijacking by non-owners
|
|
7
|
-
*
|
|
8
|
-
* @version 2026.1.30
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* List of sensitive tools that require owner permissions
|
|
12
|
-
*/
|
|
13
|
-
export const SENSITIVE_TOOLS = [
|
|
14
|
-
// WhatsApp
|
|
15
|
-
"whatsapp_login",
|
|
16
|
-
// Gateway management
|
|
17
|
-
"gateway",
|
|
18
|
-
"gateway:restart",
|
|
19
|
-
"gateway:update",
|
|
20
|
-
// Config management
|
|
21
|
-
"gateway:config:apply",
|
|
22
|
-
"gateway:config:patch",
|
|
23
|
-
// Cron management
|
|
24
|
-
"cron:add",
|
|
25
|
-
"cron:remove",
|
|
26
|
-
"cron:update",
|
|
27
|
-
// Session management
|
|
28
|
-
"sessions_spawn", // Pode criar sub-agentes
|
|
29
|
-
];
|
|
30
|
-
/**
|
|
31
|
-
* Check if a tool is sensitive (requires owner permission)
|
|
32
|
-
*/
|
|
33
|
-
export function isSensitiveTool(toolName) {
|
|
34
|
-
const normalized = toolName.trim().toLowerCase();
|
|
35
|
-
return SENSITIVE_TOOLS.some((tool) => {
|
|
36
|
-
const normalizedTool = tool.toLowerCase();
|
|
37
|
-
// Exact match ou prefix match (ex: "gateway" match "gateway:restart")
|
|
38
|
-
return normalized === normalizedTool || normalized.startsWith(`${normalizedTool}:`);
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Check if a sender is an owner
|
|
43
|
-
*
|
|
44
|
-
* Owners are configured in poolbot.json:
|
|
45
|
-
* {
|
|
46
|
-
* "security": {
|
|
47
|
-
* "owners": ["+554498569337", "5140768830"]
|
|
48
|
-
* }
|
|
49
|
-
* }
|
|
50
|
-
*/
|
|
51
|
-
export function isOwner(sender, owners = []) {
|
|
52
|
-
if (!sender)
|
|
53
|
-
return false;
|
|
54
|
-
const normalizedSender = sender.trim();
|
|
55
|
-
if (!normalizedSender)
|
|
56
|
-
return false;
|
|
57
|
-
// Check if sender is in owners list
|
|
58
|
-
return owners.some((owner) => {
|
|
59
|
-
const normalizedOwner = owner.trim();
|
|
60
|
-
return normalizedOwner === normalizedSender;
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Check if a user can use a tool
|
|
65
|
-
*
|
|
66
|
-
* @param toolName - Tool name (ex: "whatsapp_login")
|
|
67
|
-
* @param sender - Sender identifier (phone number, user ID, etc.)
|
|
68
|
-
* @param owners - List of owner identifiers
|
|
69
|
-
* @returns true if user can use the tool, false otherwise
|
|
70
|
-
*/
|
|
71
|
-
export function canUseTool(toolName, sender, owners = []) {
|
|
72
|
-
// Non-sensitive tools são permitidas para todos
|
|
73
|
-
if (!isSensitiveTool(toolName)) {
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
// Sensitive tools requerem owner permission
|
|
77
|
-
return isOwner(sender, owners);
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Error message for denied tool access
|
|
81
|
-
*/
|
|
82
|
-
export function toolAccessDeniedMessage(toolName) {
|
|
83
|
-
return (`Tool "${toolName}" is restricted to owners only. ` +
|
|
84
|
-
`This tool requires owner permissions for security reasons. ` +
|
|
85
|
-
`Contact the bot owner for access.`);
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Validate tool access and throw if denied
|
|
89
|
-
*
|
|
90
|
-
* @throws Error if access is denied
|
|
91
|
-
*/
|
|
92
|
-
export function validateToolAccess(toolName, sender, owners = []) {
|
|
93
|
-
if (!canUseTool(toolName, sender, owners)) {
|
|
94
|
-
throw new Error(toolAccessDeniedMessage(toolName));
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gateway URL Override Security
|
|
3
|
-
* Prevents credential leakage via gateway URL redirects
|
|
4
|
-
*
|
|
5
|
-
* Based on OpenClaw 2026.2.4 security fix:
|
|
6
|
-
* - Require explicit credentials for gateway URL overrides
|
|
7
|
-
*
|
|
8
|
-
* @version 2026.1.30
|
|
9
|
-
*/
|
|
10
|
-
/**
|
|
11
|
-
* Default gateway URLs (considered safe)
|
|
12
|
-
*/
|
|
13
|
-
export const DEFAULT_GATEWAY_URLS = [
|
|
14
|
-
"http://127.0.0.1:18789",
|
|
15
|
-
"http://localhost:18789",
|
|
16
|
-
"http://[::1]:18789",
|
|
17
|
-
];
|
|
18
|
-
/**
|
|
19
|
-
* Minimum token length for security
|
|
20
|
-
*/
|
|
21
|
-
export const MIN_TOKEN_LENGTH = 32;
|
|
22
|
-
/**
|
|
23
|
-
* Check if URL is a default/safe gateway URL
|
|
24
|
-
*/
|
|
25
|
-
export function isDefaultGatewayUrl(url) {
|
|
26
|
-
if (!url)
|
|
27
|
-
return true; // No URL means use default
|
|
28
|
-
const normalized = url.trim().toLowerCase();
|
|
29
|
-
return DEFAULT_GATEWAY_URLS.some((defaultUrl) => normalized === defaultUrl.toLowerCase());
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Validate gateway URL override security
|
|
33
|
-
*
|
|
34
|
-
* @param config - Gateway configuration
|
|
35
|
-
* @throws Error if security requirements are not met
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```typescript
|
|
39
|
-
* // Safe: Using default URL
|
|
40
|
-
* validateGatewayUrlSecurity({ url: "http://localhost:18789" });
|
|
41
|
-
*
|
|
42
|
-
* // Safe: Custom URL with explicit token
|
|
43
|
-
* validateGatewayUrlSecurity({
|
|
44
|
-
* url: "http://custom.gateway.com",
|
|
45
|
-
* token: "very-long-secure-token-32chars+",
|
|
46
|
-
* requireExplicitToken: true
|
|
47
|
-
* });
|
|
48
|
-
*
|
|
49
|
-
* // Unsafe: Custom URL without explicit flag
|
|
50
|
-
* validateGatewayUrlSecurity({
|
|
51
|
-
* url: "http://malicious.com",
|
|
52
|
-
* token: "token"
|
|
53
|
-
* });
|
|
54
|
-
* // Throws: "Gateway URL override requires explicit token flag"
|
|
55
|
-
* ```
|
|
56
|
-
*/
|
|
57
|
-
export function validateGatewayUrlSecurity(config) {
|
|
58
|
-
// If URL is default/safe, no additional validation needed
|
|
59
|
-
if (isDefaultGatewayUrl(config.url)) {
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
// Custom URL detected - require explicit confirmation
|
|
63
|
-
if (!config.requireExplicitToken) {
|
|
64
|
-
throw new Error("Gateway URL override requires explicit token flag. " +
|
|
65
|
-
"Set 'requireExplicitToken: true' in your gateway config to confirm " +
|
|
66
|
-
"you want to use a custom gateway URL. This prevents accidental " +
|
|
67
|
-
"credential leakage to untrusted gateways.");
|
|
68
|
-
}
|
|
69
|
-
// Require token when using custom URL
|
|
70
|
-
if (!config.token) {
|
|
71
|
-
throw new Error("Gateway URL override requires a token. " +
|
|
72
|
-
"Provide a secure token when using a custom gateway URL.");
|
|
73
|
-
}
|
|
74
|
-
// Require strong token (32+ characters)
|
|
75
|
-
if (config.token.length < MIN_TOKEN_LENGTH) {
|
|
76
|
-
throw new Error(`Gateway URL override requires a strong token (${MIN_TOKEN_LENGTH}+ characters). ` +
|
|
77
|
-
`Current token length: ${config.token.length} characters.`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Check if gateway config is safe without throwing
|
|
82
|
-
*
|
|
83
|
-
* @param config - Gateway configuration
|
|
84
|
-
* @returns true if config is safe, false otherwise
|
|
85
|
-
*/
|
|
86
|
-
export function isGatewayConfigSafe(config) {
|
|
87
|
-
try {
|
|
88
|
-
validateGatewayUrlSecurity(config);
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import fsSync from "node:fs";
|
|
2
|
-
import fs from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
const CORE_PACKAGE_NAMES = new Set(["poolbot"]);
|
|
6
|
-
async function readPackageName(dir) {
|
|
7
|
-
try {
|
|
8
|
-
const raw = await fs.readFile(path.join(dir, "package.json"), "utf-8");
|
|
9
|
-
const parsed = JSON.parse(raw);
|
|
10
|
-
return typeof parsed.name === "string" ? parsed.name : null;
|
|
11
|
-
}
|
|
12
|
-
catch {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
function readPackageNameSync(dir) {
|
|
17
|
-
try {
|
|
18
|
-
const raw = fsSync.readFileSync(path.join(dir, "package.json"), "utf-8");
|
|
19
|
-
const parsed = JSON.parse(raw);
|
|
20
|
-
return typeof parsed.name === "string" ? parsed.name : null;
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
async function findPackageRoot(startDir, maxDepth = 12) {
|
|
27
|
-
let current = path.resolve(startDir);
|
|
28
|
-
for (let i = 0; i < maxDepth; i += 1) {
|
|
29
|
-
const name = await readPackageName(current);
|
|
30
|
-
if (name && CORE_PACKAGE_NAMES.has(name)) {
|
|
31
|
-
return current;
|
|
32
|
-
}
|
|
33
|
-
const parent = path.dirname(current);
|
|
34
|
-
if (parent === current) {
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
current = parent;
|
|
38
|
-
}
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
function findPackageRootSync(startDir, maxDepth = 12) {
|
|
42
|
-
let current = path.resolve(startDir);
|
|
43
|
-
for (let i = 0; i < maxDepth; i += 1) {
|
|
44
|
-
const name = readPackageNameSync(current);
|
|
45
|
-
if (name && CORE_PACKAGE_NAMES.has(name)) {
|
|
46
|
-
return current;
|
|
47
|
-
}
|
|
48
|
-
const parent = path.dirname(current);
|
|
49
|
-
if (parent === current) {
|
|
50
|
-
break;
|
|
51
|
-
}
|
|
52
|
-
current = parent;
|
|
53
|
-
}
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
function candidateDirsFromArgv1(argv1) {
|
|
57
|
-
const normalized = path.resolve(argv1);
|
|
58
|
-
const candidates = [path.dirname(normalized)];
|
|
59
|
-
// Resolve symlinks for version managers (nvm, fnm, n, Homebrew/Linuxbrew)
|
|
60
|
-
// that create symlinks in bin/ pointing to the real package location.
|
|
61
|
-
try {
|
|
62
|
-
const resolved = fsSync.realpathSync(normalized);
|
|
63
|
-
if (resolved !== normalized) {
|
|
64
|
-
candidates.push(path.dirname(resolved));
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
// realpathSync throws if path doesn't exist; keep original candidates
|
|
69
|
-
}
|
|
70
|
-
const parts = normalized.split(path.sep);
|
|
71
|
-
const binIndex = parts.lastIndexOf(".bin");
|
|
72
|
-
if (binIndex > 0 && parts[binIndex - 1] === "node_modules") {
|
|
73
|
-
const binName = path.basename(normalized);
|
|
74
|
-
const nodeModulesDir = parts.slice(0, binIndex).join(path.sep);
|
|
75
|
-
candidates.push(path.join(nodeModulesDir, binName));
|
|
76
|
-
}
|
|
77
|
-
return candidates;
|
|
78
|
-
}
|
|
79
|
-
export async function resolveOpenClawPackageRoot(opts) {
|
|
80
|
-
for (const candidate of buildCandidates(opts)) {
|
|
81
|
-
const found = await findPackageRoot(candidate);
|
|
82
|
-
if (found) {
|
|
83
|
-
return found;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
export function resolveOpenClawPackageRootSync(opts) {
|
|
89
|
-
for (const candidate of buildCandidates(opts)) {
|
|
90
|
-
const found = findPackageRootSync(candidate);
|
|
91
|
-
if (found) {
|
|
92
|
-
return found;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
function buildCandidates(opts) {
|
|
98
|
-
const candidates = [];
|
|
99
|
-
if (opts.moduleUrl) {
|
|
100
|
-
candidates.push(path.dirname(fileURLToPath(opts.moduleUrl)));
|
|
101
|
-
}
|
|
102
|
-
if (opts.argv1) {
|
|
103
|
-
candidates.push(...candidateDirsFromArgv1(opts.argv1));
|
|
104
|
-
}
|
|
105
|
-
if (opts.cwd) {
|
|
106
|
-
candidates.push(opts.cwd);
|
|
107
|
-
}
|
|
108
|
-
return candidates;
|
|
109
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
export const POSIX_POOLBOT_TMP_DIR = "/tmp/openclaw";
|
|
5
|
-
function isNodeErrorWithCode(err, code) {
|
|
6
|
-
return (typeof err === "object" &&
|
|
7
|
-
err !== null &&
|
|
8
|
-
"code" in err &&
|
|
9
|
-
err.code === code);
|
|
10
|
-
}
|
|
11
|
-
export function resolvePreferredOpenClawTmpDir(options = {}) {
|
|
12
|
-
const accessSync = options.accessSync ?? fs.accessSync;
|
|
13
|
-
const lstatSync = options.lstatSync ?? fs.lstatSync;
|
|
14
|
-
const mkdirSync = options.mkdirSync ?? fs.mkdirSync;
|
|
15
|
-
const getuid = options.getuid ??
|
|
16
|
-
(() => {
|
|
17
|
-
try {
|
|
18
|
-
return typeof process.getuid === "function" ? process.getuid() : undefined;
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
return undefined;
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
const tmpdir = options.tmpdir ?? os.tmpdir;
|
|
25
|
-
const uid = getuid();
|
|
26
|
-
const isSecureDirForUser = (st) => {
|
|
27
|
-
if (uid === undefined) {
|
|
28
|
-
return true;
|
|
29
|
-
}
|
|
30
|
-
if (typeof st.uid === "number" && st.uid !== uid) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
// Avoid group/other writable dirs when running on multi-user hosts.
|
|
34
|
-
if (typeof st.mode === "number" && (st.mode & 0o022) !== 0) {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
return true;
|
|
38
|
-
};
|
|
39
|
-
const fallback = () => {
|
|
40
|
-
const base = tmpdir();
|
|
41
|
-
const suffix = uid === undefined ? "poolbot" : `openclaw-${uid}`;
|
|
42
|
-
return path.join(base, suffix);
|
|
43
|
-
};
|
|
44
|
-
try {
|
|
45
|
-
const preferred = lstatSync(POSIX_POOLBOT_TMP_DIR);
|
|
46
|
-
if (!preferred.isDirectory() || preferred.isSymbolicLink()) {
|
|
47
|
-
return fallback();
|
|
48
|
-
}
|
|
49
|
-
accessSync(POSIX_POOLBOT_TMP_DIR, fs.constants.W_OK | fs.constants.X_OK);
|
|
50
|
-
if (!isSecureDirForUser(preferred)) {
|
|
51
|
-
return fallback();
|
|
52
|
-
}
|
|
53
|
-
return POSIX_POOLBOT_TMP_DIR;
|
|
54
|
-
}
|
|
55
|
-
catch (err) {
|
|
56
|
-
if (!isNodeErrorWithCode(err, "ENOENT")) {
|
|
57
|
-
return fallback();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
try {
|
|
61
|
-
accessSync("/tmp", fs.constants.W_OK | fs.constants.X_OK);
|
|
62
|
-
// Create with a safe default; subsequent callers expect it exists.
|
|
63
|
-
mkdirSync(POSIX_POOLBOT_TMP_DIR, { recursive: true, mode: 0o700 });
|
|
64
|
-
try {
|
|
65
|
-
const preferred = lstatSync(POSIX_POOLBOT_TMP_DIR);
|
|
66
|
-
if (!preferred.isDirectory() || preferred.isSymbolicLink()) {
|
|
67
|
-
return fallback();
|
|
68
|
-
}
|
|
69
|
-
if (!isSecureDirForUser(preferred)) {
|
|
70
|
-
return fallback();
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
return fallback();
|
|
75
|
-
}
|
|
76
|
-
return POSIX_POOLBOT_TMP_DIR;
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
return fallback();
|
|
80
|
-
}
|
|
81
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Media Path Sanitization
|
|
3
|
-
* Prevents path traversal attacks in media attachments
|
|
4
|
-
*
|
|
5
|
-
* Based on OpenClaw 2026.2.4 security fix:
|
|
6
|
-
* - Enforce sandboxed media paths for message tool attachments
|
|
7
|
-
*
|
|
8
|
-
* @version 2026.1.30
|
|
9
|
-
*/
|
|
10
|
-
import path from "node:path";
|
|
11
|
-
import fs from "node:fs";
|
|
12
|
-
/**
|
|
13
|
-
* Sanitize media path to prevent path traversal
|
|
14
|
-
*
|
|
15
|
-
* @param inputPath - User-provided path (may contain ../ or absolute paths)
|
|
16
|
-
* @param baseDir - Base directory for media files (sandbox root)
|
|
17
|
-
* @returns Sanitized absolute path within baseDir
|
|
18
|
-
* @throws Error if path is outside baseDir or file doesn't exist
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```typescript
|
|
22
|
-
* // Safe usage:
|
|
23
|
-
* const safe = sanitizeMediaPath("photo.jpg", "/root/.poolbot/media/");
|
|
24
|
-
* // Returns: "/root/.poolbot/media/photo.jpg"
|
|
25
|
-
*
|
|
26
|
-
* // Blocked (path traversal):
|
|
27
|
-
* sanitizeMediaPath("../../etc/passwd", "/root/.poolbot/media/");
|
|
28
|
-
* // Throws: "Path traversal detected"
|
|
29
|
-
* ```
|
|
30
|
-
*/
|
|
31
|
-
export function sanitizeMediaPath(inputPath, baseDir) {
|
|
32
|
-
// 1. Normalize base directory (ensure trailing slash)
|
|
33
|
-
const normalizedBase = path.resolve(baseDir);
|
|
34
|
-
// 2. Resolve absolute path (follows ../ and resolves relative paths)
|
|
35
|
-
const resolved = path.resolve(normalizedBase, inputPath);
|
|
36
|
-
// 3. Security check: must be within baseDir
|
|
37
|
-
if (!resolved.startsWith(normalizedBase + path.sep) && resolved !== normalizedBase) {
|
|
38
|
-
throw new Error(`Path traversal detected: "${inputPath}" resolves to "${resolved}" ` +
|
|
39
|
-
`which is outside the allowed directory "${normalizedBase}"`);
|
|
40
|
-
}
|
|
41
|
-
// 4. Check if file exists
|
|
42
|
-
if (!fs.existsSync(resolved)) {
|
|
43
|
-
throw new Error(`File not found: ${inputPath}`);
|
|
44
|
-
}
|
|
45
|
-
// 5. Check if it's a file (not directory)
|
|
46
|
-
const stats = fs.statSync(resolved);
|
|
47
|
-
if (!stats.isFile()) {
|
|
48
|
-
throw new Error(`Path is not a file: ${inputPath}`);
|
|
49
|
-
}
|
|
50
|
-
return resolved;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Sanitize multiple media paths
|
|
54
|
-
*
|
|
55
|
-
* @param inputPaths - Array of user-provided paths
|
|
56
|
-
* @param baseDir - Base directory for media files
|
|
57
|
-
* @returns Array of sanitized paths
|
|
58
|
-
* @throws Error if any path is invalid
|
|
59
|
-
*/
|
|
60
|
-
export function sanitizeMediaPaths(inputPaths, baseDir) {
|
|
61
|
-
return inputPaths.map((p) => sanitizeMediaPath(p, baseDir));
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Check if path is safe without throwing
|
|
65
|
-
*
|
|
66
|
-
* @param inputPath - User-provided path
|
|
67
|
-
* @param baseDir - Base directory
|
|
68
|
-
* @returns true if path is safe, false otherwise
|
|
69
|
-
*/
|
|
70
|
-
export function isMediaPathSafe(inputPath, baseDir) {
|
|
71
|
-
try {
|
|
72
|
-
sanitizeMediaPath(inputPath, baseDir);
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
}
|