If you discover a security vulnerability, do not open a public issue.
Email the maintainer directly or use GitHub's private vulnerability reporting feature.
Include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if any)
We aim to acknowledge reports within 48 hours and provide a fix timeline within 7 days.
This project operates as a single-user local daemon:
- The daemon runs on your local machine under your user account
- No network listeners are opened; it connects outbound to Feishu/Lark APIs only
- Authentication is handled by the Feishu/Lark bot token mechanism
- Access control is enforced via allowed sender ID lists (
CTI_FEISHU_ALLOWED_USERS) applied to both inbound messages and card button callbacks
- Empty allowlist (the variable is unset or has no values) — all senders are rejected. This is the secure default.
- Specific IDs (e.g.
ou_alice,ou_bob) — only those exact open_id / user_id / union_id values are allowed. - Single wildcard
*— allow every sender. This is dangerous: anyone who can DM your bot or share a group with it can create sessions, run shell commands as your user, and approve permission cards. Use it only on personal machines where the bot is privately scoped. - Mixed (e.g.
*,ou_alice) —*is not treated as a wildcard when combined with specific IDs. Only the literal IDs match. This avoids the "I added myself but forgot to remove*" trap.
| Threat | Mitigation |
|---|---|
| Token leakage | File permissions (600), log redaction, .gitignore exclusion |
| Unauthorized message senders | Allowlist filtering on inbound text/image messages and card button callbacks |
| Local privilege escalation | Runs as unprivileged user process |
| Sensitive data in chat | Structured input prompts redirect sensitive content to local CLI |
All credentials are stored in ~/.agents-to-im/config.env with file permissions set to 600 (owner read/write only). This file is never committed to version control. The bridge is designed for single-user local use — it assumes the operating-system account itself is the security boundary, and does not try to defend against attackers who already have write access to your home directory.
config.env is never evaluated as a shell script on any platform. Earlier versions used set -a; source config.env on POSIX, which would execute any embedded shell command (e.g. EVIL=$(rm -rf ~)). The current loader uses Node's --env-file= flag (a strict KEY=VALUE parser, no shell interpretation) to read the file, then re-exports the resulting variables to the daemon process via POSIX-escaped export lines (scripts/dump-env.mjs). Values containing $(...), backticks, or quotes are preserved as literal strings. On native Windows the daemon process reads config.env directly through an in-process strict KEY=VALUE parser (src/config/config.ts), which likewise never invokes a shell.
All tokens and secrets are masked in log output and terminal display. Only the last 4 characters of any secret are shown (e.g., ****abcd). This applies to:
- Startup and diagnostic output
agents-to-im logscommand- Error messages and stack traces
If a token is compromised or expired:
- Revoke the old token on the Feishu/Lark platform
- Generate a new token
- Update
~/.agents-to-im/config.env - Run
agents-to-im restart
If you suspect a token has been leaked:
- Immediately revoke the token on the Feishu/Lark platform
- Run
agents-to-im stop - Update
config.envwith a new token - Review
~/.agents-to-im/logs/for unauthorized activity - Run
agents-to-im startwith the new credentials
Security updates are applied to the latest version on main. There is no LTS or backporting at this time.