Back to skill

Security audit

lark-wiki-writer

Security checks for vulnerabilities and agentic risk

Overview

This skill appears to do what it claims, but it asks users to handle powerful Lark credentials in risky ways and recommends broad document permissions.

Install only if you are comfortable giving this tool a Lark tenant app credential that can create and write documents. Prefer protected environment variables or a secret manager over command-line secrets or config.json, restrict the Lark app to a test or dedicated wiki space, grant the minimum API scopes available, and rotate the app secret if it was ever placed in shell history, logs, or a repository.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:60
Finding
Application Secret Exposed Through Command-Line Arguments## Vulnerability Details **File Location**: `SKILL.md:60-64`; supporting implementation at `lark_wiki_writer.py:433-436` **Vulnerability Type**: Application secret exposure through process arguments and command history **Risk Level**: Medium ### Vulnerable Code ```bash python3 lark_wiki_writer.py validate \ --app-id YOUR_APP_ID \ --app-secret YOUR_APP_SECRET \ --space-id YOUR_SPACE_ID ``` The implementation explicitly accepts the secret as a command-line argument: ```python parser.add_argument('--app-id', help='飞书应用 ID') parser.add_argument('--app-secret', help='飞书应用密钥') parser.add_argument('--space-id', help='知识库 Space ID') parser.add_argument('--wiki-domain', help='飞书域名') ``` ### Technical Analysis The documented invocation places a reusable Lark App Secret directly in the process argument vector. Depending on the host configuration, command-line arguments may be exposed through: - Shell history files. - Process inspection utilities and operating-system process interfaces. - CI/CD logs and job metadata. - Terminal session recording. - Monitoring, endpoint security, and observability agents. - Wrapper scripts that record invoked commands. The program does not print the secret itself, but avoiding output does not protect it from these process-level disclosure channels. Environment variables are already supported and present a more appropriate interface when populated through a secret manager, although environment variables must also be protected from logging and unauthorized process access. ### Attack Path 1. A user follows the documented command and supplies the real App Secret using `--app-secret`. 2. The command is retained in shell history, automation logs, process telemetry, or a process inspection interface. 3. A local account, monitoring-system user, CI log reader, or other party with access to that data retrieves the App ID and App Secret. 4. The attacker submits those credenti ...[truncated 876 chars]
Remediation
## Remediation Suggestions 1. Remove `--app-secret` from recommended commands and examples. 2. Prefer a dedicated secret manager that injects `LARK_APP_SECRET` only into the target process. 3. For interactive use, support hidden input through Python's `getpass` module. 4. If command-line secret input must remain for compatibility, mark it as deprecated and display a clear warning that it can leak through history and process inspection. 5. Ensure CI/CD systems mask the secret and do not echo generated commands. 6. Document immediate App Secret rotation procedures for suspected exposure. 7. Grant the associated Lark application only the minimum API scopes necessary for document creation and block insertion.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:47
Finding
Unsupported Plaintext Configuration Guidance Encourages Persistent Secret Storage## Vulnerability Details **File Location**: `SKILL.md:47-56`; example file at `config.example.json:1-6` **Vulnerability Type**: Insecure plaintext credential storage guidance **Risk Level**: Medium ### Vulnerable Code The documentation instructs users to create a plaintext `config.json` containing the application secret: ```json { "app_id": "cli_xxxxxxxxxx", "app_secret": "xxxxxxxxxxxxxx", "space_id": "7603663680785370844", "wiki_domain": "your-domain.larksuite.com" } ``` The distributed example reinforces the same storage pattern: ```json { "app_id": "YOUR_APP_ID_HERE", "app_secret": "YOUR_APP_SECRET_HERE", "space_id": "YOUR_SPACE_ID_HERE", "wiki_domain": "your-domain.larksuite.com" } ``` ### Technical Analysis A reusable application secret is shown as a normal JSON value without accompanying controls for file permissions, encryption, source-control exclusion, or secret-manager integration. The reviewed implementation does not load `config.json`; it only obtains credentials from constructor arguments or environment variables: ```python self.app_id = app_id or os.environ.get('LARK_APP_ID') self.app_secret = app_secret or os.environ.get('LARK_APP_SECRET') self.space_id = space_id or os.environ.get('LARK_SPACE_ID') self.wiki_domain = wiki_domain or os.environ.get('LARK_WIKI_DOMAIN', 'your-domain.larksuite.com') ``` Consequently, following the configuration-file instructions creates a persistent plaintext credential artifact without providing the advertised runtime benefit. Such files are commonly copied into repositories, backups, workspace archives, container build contexts, or shared directories. No real credential is embedded in the distributed example itself; the risk arises when a user replaces the placeholders with operational credentials. ### Attack Path 1. A user follows `SKILL.md` and creates `config.json` containing a valid Lark App Secret. 2. The file is ...[truncated 1003 chars]
Remediation
## Remediation Suggestions 1. Remove the unsupported `config.json` instructions unless secure configuration-file loading is implemented. 2. Prefer secret-manager injection or protected environment variables over persistent plaintext storage. 3. Add `config.json` and other local credential filenames to `.gitignore`. 4. If file-based configuration is implemented: - Separate secret and non-secret configuration. - Require owner-only file permissions, such as mode `0600` on supported systems. - Reject files with unsafe permissions where practical. - Support references to secret-manager entries rather than literal secrets. - Never print secret values during parsing or validation. 5. Keep example files limited to unmistakable placeholders. 6. Document repository-history cleanup and App Secret rotation procedures for accidentally committed credentials.

T05 · Unauthorized Access and Privilege Escalation

Note
Location
SKILL.md:16
Finding
Documented Lark Permissions Exceed the Demonstrated Workflow## Vulnerability Details **File Location**: `SKILL.md:16-20` **Vulnerability Type**: Excessive application permissions and violation of least privilege **Risk Level**: Low ### Vulnerable Configuration Guidance ```text 在应用管理页面,添加以下权限: - ✅ **知识库** → 查看、编辑和管理知识空间 - ✅ **文档** → 查看、编辑和管理文档 ``` This guidance instructs users to grant broad view, edit, and management access for Wiki spaces and documents. ### Technical Analysis The reviewed implementation performs a narrower set of operations: - Requests a tenant access token. - Creates a Wiki document node in a specified space. - Reads the created document's root block. - Adds child blocks to that document. - Optionally reads one Wiki space during configuration validation. No implementation was found for deleting documents, changing space settings, managing memberships, administering spaces, or broadly updating arbitrary existing documents. Recommending general management permissions therefore appears broader than the demonstrated create-and-write workflow. Excessive permissions do not directly compromise the application, but they increase the consequences of App Secret or access-token disclosure. This is particularly relevant because the documentation also recommends supplying the secret through command-line arguments and a plaintext configuration file. ### Attack Path 1. A user grants the broad Wiki and document management permissions recommended by the Skill. 2. The App Secret or tenant token is exposed through process arguments, plaintext storage, logs, or another host compromise. 3. An attacker exchanges the secret for a tenant token or reuses the exposed token. 4. The attacker invokes Lark APIs outside the Skill's implemented create-and-write workflow. 5. The attacker reads or modifies additional resources permitted by the application's broad scopes. This attack path depends on a separate credential or token compromise; excessive permissions amplify th ...[truncated 495 chars]
Remediation
## Remediation Suggestions 1. Identify and document the exact Lark API scopes required for each endpoint used by the implementation. 2. Request only the scopes required to: - Create a document node in the selected Wiki space. - Read the newly created document's root block. - Insert document blocks. 3. Treat the Wiki-space read permission used by `validate` as optional if it is not required for normal operation. 4. Avoid requesting deletion, membership-management, space-administration, or unrestricted document-management scopes unless corresponding functionality is implemented. 5. Document resource-level restrictions and recommend limiting the application to designated spaces. 6. Periodically review and revoke unused scopes in the Lark application console. 7. Rotate the App Secret and revoke active tokens after any suspected credential disclosure.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (8)

Credential Access

High
Category
Privilege Escalation
Content
raise ValueError("缺少 LARK_SPACE_ID,请通过参数或环境变量提供")
    
    def _get_token(self) -> str:
        """获取 access token"""
        url = f"{self.base_url}/open-apis/auth/v3/tenant_access_token/internal"
        data = json.dumps({
            "app_id": self.app_id,
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill documents storing App ID, App Secret, and other identifiers in environment variables and a config.json file, but it does not warn users about secret handling risks. This can encourage insecure storage of credentials in shell history, plaintext files, source repositories, or shared environments, potentially exposing access to the organization's Lark APIs.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The documentation explains commands that create and write documents into a user's Lark wiki space, but it does not clearly warn that running the skill will perform persistent remote modifications. This can lead users to execute it without understanding that it will create new wiki content in a live workspace, increasing the risk of unintended data creation, workspace clutter, or writing sensitive material into the wrong location.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The module title, docstrings, CLI descriptions, status messages, and error/help output are written exclusively in Chinese, which imposes a specific language on users. There is no natural-language indication that users may choose another language or that the skill is intentionally limited to a Chinese-speaking or region-specific environment.

Natural-Language Policy Violations

Low
Confidence
72% confidence
Finding
The README's substantive description is presented in Chinese with no indication of language choice or alternative locale. A skill that effectively forces one language in user-facing instructions can be a natural-language policy issue when no opt-in or documented locale scope is provided.

Missing User Warnings

Low
Confidence
83% confidence
Finding
This markdown file documents passing an app ID and app secret on the command line and using them to create remote wiki documents, but it does not include any user-facing warning about credential sensitivity or that content will be sent to an external service. For a markdown skill description, omission of privacy/system-impact warnings around credential use and remote writes fits the missing-warning category.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The file presents the skill instructions entirely in Chinese, effectively forcing a specific language for users without stating that the skill is intended only for a Chinese-speaking audience. The policy allows locale constraints when they are optional or clearly justified, but neither is documented here.

Natural-Language Policy Violations

Low
Confidence
85% confidence
Finding
The manifest description is written entirely in Chinese and does not indicate that the skill is intended only for Chinese-speaking users or that other language options are available. This can violate language/locale policy when a skill effectively assumes a specific language without user opt-in or documented regional justification.

Static analysis

No suspicious patterns detected.