clawgram 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,6 +14,14 @@ Clawgram is a personal-Telegram channel plugin for [OpenClaw](https://github.com
14
14
 
15
15
  > **WARNING**: Using a user account for automated messaging may violate Telegram's Terms of Service. Use a dedicated secondary account. Your account could be banned or restricted.
16
16
 
17
+ > **What this plugin can do with your account.** It logs in as a *full Telegram user*, not a bot:
18
+ > it can read private and group conversations within its configured scope and send messages that are
19
+ > indistinguishable from ones you typed yourself. Recipients cannot tell an assistant reply from a
20
+ > human one. Treat the account as compromised-if-leaked: `apiHash` and `sessionString` are bearer
21
+ > credentials for everything that account can reach. Scope reads with `readChats`, gate senders with
22
+ > `allowFrom`, and prefer a dedicated account over your primary one — see
23
+ > [Security and privacy](#security-and-privacy).
24
+
17
25
 
18
26
  ## Features
19
27
 
@@ -32,7 +40,11 @@ Clawgram is a personal-Telegram channel plugin for [OpenClaw](https://github.com
32
40
 
33
41
  ## Requirements
34
42
 
35
- - OpenClaw >= 2026.5.7
43
+ - OpenClaw >= 2026.5.26 — earlier releases carry published high-severity advisories
44
+ (among them a pairing-scoped session that could restore revoked node-token authority, fixed in
45
+ `2026.5.26`). Since this plugin reads messages and acts on an account, running it on a vulnerable
46
+ Gateway widens the blast radius, so 2.1.0 refuses to install below that version. Built and tested
47
+ against `2026.7.1-2`.
36
48
  - Telegram API credentials from [my.telegram.org](https://my.telegram.org)
37
49
  - Node.js >= 22
38
50
 
@@ -90,13 +102,14 @@ Please enter the code you received: 12345
90
102
  [2026-05-10T16:01:56.390] [INFO] - [Disconnecting from x.x.x.x:80/TCPFull...]
91
103
  Telegram authorization completed successfully.
92
104
 
93
- Session string:
94
- 1BAAOMTQ5LjE1NC4xNjcuOTEAUQZ1aeNwM6O5lSD+kX/irkoUFMj+nUy5hRhpVqbkuOhEP+JOT4FEobUVnUKPnpKPxXdwQ9e
95
- js+tWQTto86Heab4XSfyOoWK5WDA/dMhFYBuFxms/FF946HerCM+i5nh0gu//YGmIEntw7gY8JQQNYuvLB5SGdsDpa50LcJ5fK
96
- 686qqUsnlqmRTONdVG3EOdnV8RbTFTHg5BWLztfD5uLt1lIr/bG+BWCPCLAaA85yPL8SgGRLtX4QYXrnaEVmKui8SWq5J/
97
- Ol86oZGlrMcnj5DRQ/VeYY7yGcESwnoTSx44irCyk9GelCavzs/dfN6sAYfoZb6cN/L9jxEYXkkCQdig=
105
+ Session string received (352 chars) — kept out of this output.
98
106
  ```
99
107
 
108
+ > Since 2.1.0 the session string is **not** printed after a successful login: it is a bearer
109
+ > credential for the whole account, and stdout ends up in scrollback, CI logs and screen shares.
110
+ > It is written straight into `openclaw.json`, and only shown — behind an explicit warning — if you
111
+ > decline the automatic config update and have to paste it by hand.
112
+
100
113
  Since the plugin supports connecting multiple accounts, at this step the cli will ask you for the account ID, if you do not enter anything, the [default] key will be applied. You can also enter your own value.
101
114
 
102
115
  ```bash
@@ -564,6 +577,26 @@ Bindings
564
577
  ```
565
578
 
566
579
 
580
+ ## Security and privacy
581
+
582
+ This plugin holds credentials for a real Telegram account and handles private correspondence. What
583
+ that means in practice, and what the code does about it:
584
+
585
+ | Concern | Where it lives | What the plugin does |
586
+ | --- | --- | --- |
587
+ | `apiHash`, `sessionString` | `openclaw.json` | Written there by `--auth`. Never logged. Since 2.1.0 the session string is not printed after login either — only shown, behind an explicit warning, if you decline the automatic config write |
588
+ | Proxy password | `accounts.*.proxy.password` | Marked `sensitive` in `uiHints`; diagnostics say `socks4`/`socks5` and nothing more. An invalid proxy fails the account rather than falling back to a direct connection, which would leak the host IP to Telegram |
589
+ | Message bodies | channel logs | **Not logged.** Outbound sends record recipient, ids and `textLength`. Until 2.1.0 the full outbound text was written to the channel log — if you ran 2.0.x, treat those journal entries as containing private correspondence |
590
+ | Read scope | `accounts.*.readChats` | History and membership reads are confined to the listed chats. Absent means no restriction; an empty array denies everything |
591
+ | Who may talk to it | `allowFrom`, `groups.*.groupPolicy` | Direct-message senders and group behaviour are allowlisted; `mention` limits group replies to explicit mentions |
592
+
593
+ Two static tests (`test/no-secret-logging.test.ts`) fail the build if a message body or a credential
594
+ is ever added back to a log call, or if the auth flow prints the session string unprompted.
595
+
596
+ Found a security issue? Open an issue at
597
+ [github.com/d3pre5s/clawgram/issues](https://github.com/d3pre5s/clawgram/issues) — or, if it is
598
+ sensitive, contact the maintainer directly instead of filing publicly.
599
+
567
600
  ## Development
568
601
 
569
602
  ```bash
package/dist/channel.js CHANGED
@@ -1151,12 +1151,15 @@ const createChannelPlugin = (runtimes) => {
1151
1151
  };
1152
1152
  },
1153
1153
  async sendText(ctx) {
1154
+ // Never log `text`: outbound bodies are private correspondence and the
1155
+ // channel log is a plain journald sink. Length is enough to tell an
1156
+ // empty or truncated send apart from a real one.
1154
1157
  actionLog.info("clawgram outbound sendText", {
1155
1158
  accountId: ctx.accountId,
1156
1159
  rawTo: ctx.to,
1157
1160
  replyToId: ctx.replyToId ?? null,
1158
1161
  threadId: ctx.threadId ?? null,
1159
- text: ctx.text,
1162
+ textLength: ctx.text.length,
1160
1163
  });
1161
1164
  const gram = runtimes.get(ctx.accountId);
1162
1165
  if (!gram) {
package/dist/cli-core.js CHANGED
@@ -16,6 +16,15 @@ function printRestartNotice() {
16
16
  console.log("After applying config changes, restart OpenClaw:");
17
17
  console.log("openclaw gateway restart");
18
18
  }
19
+ // Printed only right before a fragment that carries apiHash and sessionString,
20
+ // i.e. when the operator declined the automatic config write and has to paste
21
+ // the values by hand.
22
+ function printSecretWarning() {
23
+ console.log("WARNING: the fragment below contains apiHash and sessionString.");
24
+ console.log("They grant full access to this Telegram account. Do not paste them");
25
+ console.log("into chats, issues or CI logs, and clear your terminal scrollback.");
26
+ console.log("");
27
+ }
19
28
  function createPrompt() {
20
29
  const rl = node_readline_1.default.createInterface({
21
30
  input: process.stdin,
@@ -137,8 +146,11 @@ async function runTelegramUserbotAuth(config) {
137
146
  const auth = await runTelegramAuthorization(prompt);
138
147
  console.log("Telegram authorization completed successfully.");
139
148
  console.log("");
140
- console.log("Session string:");
141
- console.log(auth.sessionString);
149
+ // The session string is a bearer secret for the whole Telegram account.
150
+ // It is not printed here: stdout ends up in scrollback, CI logs and
151
+ // screen-sharing. It is only shown below when the operator declines the
152
+ // automatic config write and therefore has to paste it by hand.
153
+ console.log(`Session string received (${auth.sessionString.length} chars) — kept out of this output.`);
142
154
  console.log("");
143
155
  const defaultAccountId = resolveDefaultAccountId(config);
144
156
  const rawAccountId = await prompt.ask(`Enter account id for config [${defaultAccountId}]: `);
@@ -147,6 +159,7 @@ async function runTelegramUserbotAuth(config) {
147
159
  const { snapshot } = await (0, config_runtime_1.readConfigFileSnapshotForWrite)();
148
160
  if (!shouldUpdateConfig) {
149
161
  console.log("");
162
+ printSecretWarning();
150
163
  console.log("JSON fragment for manual insertion:");
151
164
  console.log(JSON.stringify(buildConfigFragment(accountId, auth), null, 2));
152
165
  printRestartNotice();
@@ -156,6 +169,7 @@ async function runTelegramUserbotAuth(config) {
156
169
  console.log("");
157
170
  console.log("Automatic config update is unavailable because openclaw.json was not found.");
158
171
  console.log("");
172
+ printSecretWarning();
159
173
  console.log("JSON fragment for manual insertion:");
160
174
  console.log(JSON.stringify(buildConfigFragment(accountId, auth), null, 2));
161
175
  printRestartNotice();
@@ -184,6 +198,7 @@ async function runTelegramUserbotAuth(config) {
184
198
  }
185
199
  }
186
200
  console.log("");
201
+ printSecretWarning();
187
202
  console.log("JSON fragment for manual insertion:");
188
203
  console.log(JSON.stringify(buildConfigFragment(accountId, auth), null, 2));
189
204
  printRestartNotice();
@@ -2,7 +2,7 @@
2
2
  "id": "clawgram",
3
3
  "name": "Clawgram",
4
4
  "description": "Clawgram — personal Telegram (MTProto userbot) channel for OpenClaw. Your AI assistant reads and responds as you.",
5
- "version": "2.0.0",
5
+ "version": "2.1.0",
6
6
  "configSchema": {
7
7
  "type": "object",
8
8
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawgram",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Clawgram — personal Telegram (MTProto userbot) channel for OpenClaw. Your AI assistant reads and responds as you.",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -45,20 +45,20 @@
45
45
  "./dist/index.js"
46
46
  ],
47
47
  "compat": {
48
- "pluginApi": ">=2026.5.7",
49
- "minGatewayVersion": "2026.5.7"
48
+ "pluginApi": ">=2026.5.26",
49
+ "minGatewayVersion": "2026.5.26"
50
50
  },
51
51
  "build": {
52
- "openclawVersion": "2026.5.7",
53
- "pluginSdkVersion": "2026.5.7"
52
+ "openclawVersion": "2026.7.1-2",
53
+ "pluginSdkVersion": "2026.7.1-2"
54
54
  }
55
55
  },
56
56
  "devDependencies": {
57
- "openclaw": "2026.5.7",
57
+ "openclaw": "2026.7.1-2",
58
58
  "typescript": "^5.9.3"
59
59
  },
60
60
  "peerDependencies": {
61
- "openclaw": ">=2026.5.7"
61
+ "openclaw": ">=2026.5.26"
62
62
  },
63
63
  "installDependencies": true,
64
64
  "dependencies": {