mirror of
https://github.com/larksuite/cli.git
synced 2026-07-08 10:08:02 +08:00
feat/sidecar-remote-https
6 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
815db0c866 |
fix(mail): add missing scopes for mail +watch shortcut (#357)
* fix(mail): add missing event scope for mail watch The mail +watch shortcut requires scope mail:user_mailbox.event.mail_address:read to receive the mail_address field in WebSocket event payloads, but this scope was neither declared in the shortcut's Scopes list nor included in the auto-approve (recommend.allow) set. Without this scope, +watch events arrive without the mail_address field, which breaks mailbox filtering and fetch-mailbox resolution. - Add scope to mail +watch Scopes declaration - Add scope to scope_overrides.json recommend.allow list so that auth login --recommend requests it automatically * fix(mail): add missing mailbox profile scope for mail watch The +watch shortcut calls fetchMailboxPrimaryEmail (GET user_mailboxes/me/profile) to resolve the mailbox address for event filtering, which requires scope mail:user_mailbox:readonly. All other mail shortcuts that call this API (send, reply, forward, draft-create, draft-edit) already declare this scope, but +watch did not. * fix(mail): remove event scope from scope_overrides.json The mail:user_mailbox.event.mail_address:read scope only needs to be declared in the +watch shortcut's Scopes list, not in the global recommend.allow set. |
||
|
|
dc0d92708b |
fix(mail): restrict --output-dir to current working directory (#376)
* fix(mail): restrict --output-dir to current working directory Previously, mail +watch --output-dir accepted absolute paths (e.g. /etc, /tmp) and home directory paths (~/), allowing writes to arbitrary locations. Since mail content is sender-controlled, this posed a risk of writing attacker-influenced data to sensitive system directories. Now all --output-dir values go through validate.SafeOutputPath which: - Rejects absolute paths and ~ expansion - Resolves .. and symlinks - Enforces the result stays under CWD * fix(mail): reject tilde paths in --output-dir explicitly SafeOutputPath treats ~/x as a literal relative path, silently creating a directory named "~" under CWD. Reject ~ prefixed paths with a clear error message instead. * fix(mail): reject all tilde-prefixed paths and use ErrValidation - Broaden ~ check from "~ || ~/" to "~" prefix, covering ~user/path forms - Use output.ErrValidation for consistent error type (exit code 2) * fix(mail): add post-mkdir EvalSymlinks + CWD re-verification (TOCTOU) SafeOutputPath validates before MkdirAll, but an attacker could replace the newly created directory with a symlink between mkdir and the first write. Add EvalSymlinks after MkdirAll and re-verify the resolved path is still under CWD. Also broaden ~ rejection to all tilde-prefixed paths (~user/path) and use output.ErrValidation for consistent error types. * fix(mail): use validate.SafeOutputPath for post-mkdir TOCTOU check Replace direct os.Getwd and filepath.EvalSymlinks calls with a second SafeOutputPath call after MkdirAll. This satisfies the forbidigo lint rule (no direct os/filepath calls in shortcuts/) while maintaining the same TOCTOU protection. * fix(mail): use original relative path for post-mkdir re-validation SafeOutputPath rejects absolute paths, but after the first call outputDir was already resolved to an absolute path. Pass the original relative path to the second SafeOutputPath call so it can properly re-validate after MkdirAll. * fix(mail): remove redundant post-mkdir SafeOutputPath call The second SafeOutputPath call after MkdirAll provided no real TOCTOU protection: mail +watch is long-running, so the directory could be replaced at any point during the session, not just between mkdir and the check. The first SafeOutputPath already validates and resolves the path; one call is sufficient. |
||
|
|
c16a021ac6 |
fix(mail): replace os.Exit with graceful shutdown in mail watch (#350)
* fix(mail): replace os.Exit with graceful shutdown in mail watch The signal handler in mail +watch called os.Exit(0), which bypassed all deferred cleanup functions, made the code path untestable, and did not follow Go's idiomatic context cancellation pattern. Key changes: - Remove os.Exit(0) and use context.WithCancel to propagate shutdown - Run cli.Start in a separate goroutine so the main goroutine can return immediately on signal receipt (the Lark WebSocket SDK does not return promptly after context cancellation) - Extract handleMailWatchSignal as a testable standalone function - Use sync.Once + defer for idempotent cleanup on all exit paths - Fix eventCount data race with atomic.Int64 - Add signal.Reset to support forced termination via a second Ctrl+C Closes #268 * docs: add docstrings to handleMailWatchSignal test functions * fix(mail): cancel watch context on signal handler panic If handleMailWatchSignal panics, the recover block now calls cancelWatch() to unblock the main select. Without this, a panic would leave shutdownBySignal unclosed and watchCtx uncancelled, causing the process to hang. * fix(mail): use triggerShutdown to unblock main select on signal handler panic The previous panic recovery only called cancelWatch(), but since the WebSocket SDK does not return promptly after context cancellation, the main select could still hang waiting on startErrCh. Introduce triggerShutdown() that closes shutdownBySignal (via sync.Once) and cancels the watch context, used by both the normal signal path and the panic recovery path. This ensures the main select unblocks immediately regardless of how the signal goroutine exits. Add regression test that forces a panic and asserts shutdownBySignal is closed promptly. |
||
|
|
8db4528269 |
feat: add strict mode identity filter, profile management and credential extension (#252)
* feat: add strict mode identity filter, profile management and credential extension Port changes from feat/strict-mode-identity-filter_3 branch: - Add strict mode for identity filtering and configuration - Add profile management commands (add/list/remove/rename/use) - Add credential extension framework (registry, env provider) - Add VFS abstraction layer - Refactor factory default and client options - Update shortcuts to use new credential and validation patterns Change-Id: I8c104c6b147e1901d94aefcefe35a174932c742b Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: go mod tidy Change-Id: I0f610ccea6bc874248e84c24770944a3071dcc57 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: fix test failures from credential provider migration - Remove unused TAT stub registrations in api and service tests (CredentialProvider manages tokens, SDK no longer calls TAT endpoint) - Update strict mode integration test: +chat-create now supports user identity, so it should succeed under strict mode user Change-Id: Iab51c2e12a97995e0b95dcd71df212d2d1f76570 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor: migrate remaining os calls to internal/vfs Replace direct os.Stat/Open/MkdirAll/OpenFile/Remove/ReadDir/UserHomeDir with vfs equivalents in shortcuts/minutes, shortcuts/drive, and internal/keychain. Add ReadDir to the vfs interface and OsFs implementation. Change-Id: I8f97e5fb3e1731b4684d276644fcb10fae823067 * fix: resolve gofmt and goimports formatting issues Change-Id: If61578631f5698f7ca2d9a946ca59753651463fb * feat: add Flag.Input support for @file and stdin input sources Add framework-level support for reading flag values from files (@path) or stdin (-), solving the fundamental problem of passing complex text (markdown, multi-line content) via CLI arguments where shell escaping breaks content. Closes #239, fixes #163. - Add File/Stdin constants and Input field to Flag struct - Add resolveInputFlags() in runner pipeline (pre-Validate) - Support @@ escape for literal @ prefix - Guard against multiple stdin consumers - Auto-append "(supports @file, - for stdin)" to help text - Apply to: docs +create/+update --markdown, im +messages-send/+reply --text/--markdown/--content, task +comment --content, drive +add-comment --content Change-Id: I305a326d972417542aeadd70f37b74ea456461ef Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: fix pre-existing test failures in task, minutes, and registry - task/minutes: remove unused tenant_access_token httpmock stubs (TestFactory's testDefaultToken provides tokens directly, so the HTTP stub was never consumed and failed verification) - registry: fix hasEmbeddedData() to check for actual services instead of just byte length (meta_data_default.json has empty services array) Change-Id: Ic7b5fc7f9de09137a7254fe1ddf47d24ade40587 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: suppress nilerr lint for intentional nil returns Both cases intentionally return nil on error for graceful degradation: - profile list: show friendly message when config is not initialized - service: skip scope check when token resolution fails Change-Id: I7285c37277c9b0361a421ab00359244c2cd150b3 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address CodeRabbit review feedback - runner.go: fail fast when Input is used on non-string flags - remote_test.go: rename hasEmbeddedData → hasEmbeddedServices - profile/list.go: add omitempty to optional JSON fields - service.go: surface context cancellation errors in scope check Change-Id: I7072d41f8c711b4b37c542e32dfd8150f42b13c0 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: tighten credential resolution and profile flows Change-Id: I83f6d424540eab9b1708944b9b6e26e8477cc60d * refactor: centralize identity hint resolution Change-Id: I38d5f98160b92adb62dc929ae73697ae5b3d64f8 * fix: surface unverified extension identities Change-Id: Ia86d9bd19add9010176339ec4cc89deb033f5b4f * fix: honor runtime credential sources in config views Change-Id: I40b2ffedc5c1db5e08e86b9472ea2b84fa02bb29 * fix: prefer runtime values in config show commands Change-Id: I5663a53e147577f0f1f533f67d12bea504e6b839 * Revert "fix: prefer runtime values in config show commands" This reverts commit |
||
|
|
f68a41163e |
fix(mail): on-demand scope checks and watch event filtering (#198)
* fix(mail): on-demand scope checks, event filtering, and watch lifecycle - Remove mail:user_mailbox.folder:read from watch's static Scopes; add validateFolderReadScope and validateLabelReadScope that check permissions on-demand when listMailboxFolders/listMailboxLabels is called (same pattern as validateConfirmSendScope). - Resolve --mailbox me to real email address via profile API for event filtering, preventing other users' mail events from being processed. Block startup if resolution fails, with proper error type distinction. - Add unsubscribe cleanup (guarded by sync.Once) on all exit paths: SIGINT/SIGTERM, profile resolution failure, and WebSocket failure. - Remove bot from AuthTypes since bot tokens cannot subscribe. - Include profile lookup in dry-run output and update tests. - Update fetchMailboxPrimaryEmail to return error for diagnostics. - Update documentation for on-demand scope requirements. * fix(mail): preserve original error in enhanceProfileError fallback Return the original error directly for non-permission failures instead of wrapping with fmt.Errorf, so structured exit codes (ExitNetwork, ExitAPI) are preserved for scripting. |
||
|
|
83dfb068ad |
feat: open-source lark-cli — the official CLI for Lark/Feishu
Change-Id: I113d9cdb5403cec347efe4595415e34a18b7decf |