T09 · Insecure Skill Coding Practices
- Location
env-example.txt:2- Finding
Gitea access token and repository data may be transmitted over plaintext HTTP
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill matches a meeting-briefing workflow, but it has broad automated access and several under-controlled paths that could expose data or change repositories unexpectedly.
Review before installing. Use only a dedicated least-privilege Gitea bot token, change the Gitea URL to HTTPS, restrict the skill to explicit repositories, avoid automatic sending for sensitive meetings, and do not pass arbitrary local files or unvalidated recipient lists into commit. Prefer fixing setup.sh to use a virtual environment and parse .env as data before use.
env-example.txt:2Gitea access token and repository data may be transmitted over plaintext HTTP
setup.sh:30Dotenv configuration is executed as arbitrary shell code during setup
scripts/commit_brief.py:143Caller-controlled HTML path and recipients create a local file disclosure path
setup.sh:13Unpinned dependencies are installed into the system Python environment
The declared description presents an autonomous scheduled task that generates and sends pre-meeting briefings and excludes meeting modification/cancellation scenarios. The supplied code, however, is specifically a command-line wrapper exposing scan and commit operations. Its documented responsibilities are narrower and different: scanning repository metadata, computing time windows, saving files to Gitea, and updating meta.yaml state. The code comments explicitly state that OpenClaw and other components perform activity collection, AI generation, HTML rendering, and email sending. Additionally, the --mark-only option is intended for rescheduled meetings, which conflicts with the declared exclusion of meeting modification scenarios. While scanning for the 15-minute-to-6-hour window aligns partially with the description, overall the implementation surface and responsibility boundaries materially differ from the declared purpose.
The declared description is for a specific cron job that identifies upcoming meetings and generates/sends pre-meeting progress briefings. The supplied code does not implement scheduling, meeting time-window filtering, briefing generation, or message sending. Instead, it is a general-purpose Gitea API helper module for repository access and file management. While some functions reference meetings directories, that is only repository content access and not the stated pre-brief workflow. This is a material description-behavior mismatch because the code’s primary purpose and capabilities are repository operations unrelated to the declared cron briefing task.
The declared description is for a scheduled business workflow that identifies upcoming meetings and generates/sends pre-meeting briefings. The actual code chunk does none of that. Instead, it performs repository-backed log persistence: fetching an existing daily log file, decoding/re-encoding content, and creating or updating the file through authenticated API requests. This is not merely a supporting detail of meeting briefing generation in the supplied chunk, because no meeting-related logic, scheduling logic, briefing generation, or sending behavior is present at all. The code’s primary purpose is materially different from the declared purpose.
The declared description is for a runtime cron skill that automatically generates and sends pre-meeting briefs within a specific time window. The supplied code chunk does not implement that business logic; it only performs installation and configuration for such a skill. It also reveals dependencies on Gitea, a separate routine-report skill, and an email component, which are not reflected in the declared permissions section. While setup scripts can be supporting details, this code chunk’s actual behavior is materially different from the declared operational purpose because it does not perform the promised scanning/brief-generation actions at all.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
SKILL_DIR="$(cd "$(dirname "$0")" && pwd)"
CONFIG_DIR="$HOME/.config/skill-b-pre-brief"
ENV_FILE="$CONFIG_DIR/.env"
echo "🚀 设置 Skill-B (pre_brief)..."
echo ""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
SKILL_DIR="$(cd "$(dirname "$0")" && pwd)"
CONFIG_DIR="$HOME/.config/skill-b-pre-brief"
ENV_FILE="$CONFIG_DIR/.env"
echo "🚀 设置 Skill-B (pre_brief)..."
echo ""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
SKILL_DIR="$(cd "$(dirname "$0")" && pwd)"
CONFIG_DIR="$HOME/.config/skill-b-pre-brief"
ENV_FILE="$CONFIG_DIR/.env"
echo "🚀 设置 Skill-B (pre_brief)..."
echo ""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
SKILL_DIR="$(cd "$(dirname "$0")" && pwd)"
CONFIG_DIR="$HOME/.config/skill-b-pre-brief"
ENV_FILE="$CONFIG_DIR/.env"
echo "🚀 设置 Skill-B (pre_brief)..."
echo ""
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
SKILL_DIR="$(cd "$(dirname "$0")" && pwd)"
CONFIG_DIR="$HOME/.config/skill-b-pre-brief"
ENV_FILE="$CONFIG_DIR/.env"
echo "🚀 设置 Skill-B (pre_brief)..."
echo ""
The skill declares no explicit tool scope or permission boundaries despite directing use of shell execution, filesystem access, environment-based configuration, networked repository access, and email delivery. In a cron-triggered workflow, missing least-privilege declarations increases the chance that the agent can invoke broader capabilities than intended, making misuse or accidental overreach harder to constrain or audit.
The workflow instructs automatic email delivery to all attendees using collected attendee email addresses, but it provides no explicit consent, privacy warning, recipient validation, or minimization controls. In a cron context, this can leak meeting details or participant addresses at scale if attendee data is stale, incorrect, or manipulated, and there is no human review gate before sending.
The manifest description broadens the skill from a narrowly scoped pre-brief cron job into 'full meeting-process automation' and explicit coordination with other skills. That scope expansion creates authority ambiguity and increases the chance the agent is invoked for actions beyond its approved purpose, especially in an unattended cron context that can trigger cross-skill workflows automatically.
The description references periodic cron scanning and coordination behavior without clearly constraining what qualifies as an in-scope target, what exclusions apply, or what guardrails prevent overreach. In a scheduled autonomous skill, ambiguous activation or selection criteria can cause unintended processing of meetings, unnecessary data access, or accidental outbound communication without a user checkpoint.
技能清单明确说明“不处理会议创建、会议修改、取消会议、会后纪要等场景”,但文件顶部用法文档和后续实现都显式支持“改期会议,只更新状态”的 mark-only 模式。这不是生成会前简报所必需的实现细节,而是把会议改期相关状态处理纳入了技能行为范围。
manifest 描述聚焦于在会前窗口内“自动生成并发送会前进度简报”,但这里的核心逻辑会拉取并修改 meetings/<meeting_dir>/meta.yaml 的 status 字段。对会议元数据进行持久化状态变更属于额外的仓库写操作,超出了“生成并发送简报”的直观语义范围。
The script emits the full recipient list and complete HTML brief in its JSON output. In a cron/automation environment, stdout is often collected by orchestrators, logs, or downstream systems, which can unintentionally expose personal email addresses and potentially sensitive meeting content beyond intended recipients.
The manifest describes a cron-triggered skill that generates and sends pre-meeting progress briefs, and explicitly excludes unrelated meeting lifecycle handling. This utility module includes generic repository write capabilities to create and update arbitrary files in Gitea, which is broader than merely generating/sending a brief and suggests code support for repository state mutation beyond the stated scope.
The function creates a file in a remote Gitea repository via an authenticated POST request, which modifies user-managed repository data. In this file there is no confirmation prompt, print/log message, or comment/docstring warning the user that remote repository contents will be created or changed.
This function updates an existing repository file through an authenticated PUT request, which is a safety-relevant remote write operation. The code contains no confirmation, logging, or explanatory comment/docstring warning that repository contents will be modified.
get_managed_repos performs broad repository enumeration via /repos/search and then probes each repository for a meetings directory. For a narrowly scoped pre-brief cron task, this expands access discovery beyond a single expected repository set and can enable unintended data exposure, over-collection, or misuse if the token has wide privileges.
This utility sends runtime log entries to a remote repository over the network, which exceeds the narrowly stated purpose of generating and sending pre-briefs. If entry contains meeting metadata, participant information, or tokens, the skill creates an undocumented exfiltration path and persistent storage location outside the immediate execution flow.
The code performs outbound network logging of arbitrary runtime entries without any visible notice, consent, or data minimization in this file. Because the function accepts a free-form entry object and silently suppresses exceptions, sensitive operational or user data could be transmitted and retained remotely without detection or auditability.
The script resolves attendee usernames to email addresses and includes those addresses in its JSON output for every matched meeting. In a cron-triggered automation that scans all managed repositories, this creates unnecessary exposure of personally identifiable information to downstream logs, operators, or other components that may not need raw email addresses.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
if [ ! -f "$ENV_FILE" ]; then
cp "$SKILL_DIR/env-example.txt" "$ENV_FILE"
chmod 600 "$ENV_FILE"
echo ""
echo "📝 已创建配置文件:$ENV_FILE"
echo "请编辑该文件,至少填入:"
The script executes source "$ENV_FILE" on a user-editable .env file, which means any shell code placed in that file will run with the privileges of whoever launches setup.sh. Because this installer is explicitly instructing users to edit that file and may be run in automation or by privileged operators, this creates a direct command-execution path rather than merely loading key/value configuration.
Detected: suspicious.dangerous_exec