T09 · Insecure Skill Coding Practices
- Location
scripts/publisher_git.py:104- Finding
Unvalidated Category Values Permit Path Traversal During Blog Publication
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill has a coherent blog-automation purpose, but it can automatically publish to Notion and GitHub with overly broad Git and file-write behavior that needs review before installation.
Review this skill before installing. Use only restricted Notion and GitHub credentials, test against a disposable blog repository, require a clean working tree, avoid scripts that run as background publishers, and fix category path validation, git staging scope, dotenv handling, and pinned Mermaid dependencies before live use.
scripts/publisher_git.py:104Unvalidated Category Values Permit Path Traversal During Blog Publication
scripts/publisher_git.py:133Repository-Wide Git Staging Can Push Unrelated or Sensitive Files
scripts/notion_publisher.py:76Mermaid Conversion Downloads and Executes an Unpinned npm Package at Runtime
scripts/writer.py:127Untrusted News Feed Content Is Embedded in LLM Prompts Without Injection Defenses
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
}
try:
response = requests.post(query_url, headers=headers, json=payload)
response.raise_for_status()
data = response.json()
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# 2. 환경 변수 로드
# 프로젝트 루트의 .env 파일 우선적으로 로드
env_path = PROJECT_ROOT / ".env"
if env_path.exists():
load_dotenv(env_path, override=True)
else:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# 2. 환경 변수 로드
# 프로젝트 루트의 .env 파일 우선적으로 로드
env_path = PROJECT_ROOT / ".env"
if env_path.exists():
load_dotenv(env_path, override=True)
else:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# 2. 환경 변수 로드
# 프로젝트 루트의 .env 파일 우선적으로 로드
env_path = PROJECT_ROOT / ".env"
if env_path.exists():
load_dotenv(env_path, override=True)
else:
The skill commits and pushes to the remote repository automatically without any approval checkpoint. In an agent context this is dangerous because simply invoking the skill can publish attacker-controlled or erroneous content to a live site, create irreversible repository history, and potentially leak sensitive material if the workspace contains unintended changes.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
import importlib.util
from dotenv import load_dotenv
# Load .env
env_path = '/Users/nabang/Documents/OpenClaw/.env'
load_dotenv(env_path, override=True)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
import importlib.util
from dotenv import load_dotenv
# Load .env
env_path = '/Users/nabang/Documents/OpenClaw/.env'
load_dotenv(env_path, override=True)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
import importlib.util
from dotenv import load_dotenv
# Load .env
env_path = '/Users/nabang/Documents/OpenClaw/.env'
load_dotenv(env_path, override=True)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
import importlib.util
from dotenv import load_dotenv
# Load .env
env_path = '/Users/nabang/Documents/OpenClaw/.env'
load_dotenv(env_path, override=True)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
import importlib.util
from dotenv import load_dotenv
# Load .env
env_path = '/Users/nabang/Documents/OpenClaw/.env'
load_dotenv(env_path, override=True)
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
from dotenv import load_dotenv
# Load .env
env_path = '/Users/nabang/Documents/OpenClaw/.env'
load_dotenv(env_path, override=True)
# Load NotionPublisher directly
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
from dotenv import load_dotenv
# Load .env
env_path = '/Users/nabang/Documents/OpenClaw/.env'
load_dotenv(env_path, override=True)
# Load NotionPublisher directly
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
from dotenv import load_dotenv
# Load .env
env_path = '/Users/nabang/Documents/OpenClaw/.env'
load_dotenv(env_path, override=True)
# Load NotionPublisher directly
Automated add/commit/push to main occurs with no explicit confirmation. In this skill context that materially increases danger because externally sourced article content is transformed into repository changes and immediately published, creating a direct path from untrusted input to remote side effects.
The script hard-codes an absolute path to a local .env file and explicitly loads it, which couples execution to a sensitive credential source. In a shared development environment, CI runner, or redistributed skill, this can encourage unsafe secret handling and accidental exposure of API keys or internal filesystem structure.
from pathlib import Path
from dotenv import load_dotenv
# Load .env
env_path = '/Users/nabang/Documents/OpenClaw/.env'
load_dotenv(env_path, override=True)
Calling load_dotenv on a hard-coded local path with override=True can overwrite already-set environment variables with values from a file, increasing the chance of using unintended or less secure credentials. This is especially risky in automation or multi-user contexts where environment isolation matters and secrets should be centrally managed.
from dotenv import load_dotenv
# Load .env
env_path = '/Users/nabang/Documents/OpenClaw/.env'
load_dotenv(env_path, override=True)
# Load NotionPublisher directly
The description advertises auto-deployment to GitHub Pages via Git, which is an external side effect affecting a public-facing publishing target. Even with a stated Human-in-the-Loop workflow, broad triggers and automation around content generation and deployment raise the risk of unintended, premature, or manipulated publication.
---
name: auto-sec-blogger
version: 1.1.0
description: AI-powered security blog automation system (identical to github.com/rebugui/intelligence-agent). Collects news from Google News, arXiv, HackerNews → generates blog posts with GLM-4.7 → publishes to Notion → auto-deploys to GitHub Pages via Git. Features Human-in-the-Loop approval workflow. Use when you want to automate blog writing, news collection, or content generation with the exact functionality of the original intelligence-agent repository. Triggers: "블로그 글 작성", "보안 뉴스 발행", "깃헙 블로그 발행", "intelligence agent", "지능형 에이전트", "자동 글쓰기".
---
# Intelligence Agent
The trigger list includes broad phrases such as '자동 글쓰기' and generic references to 'intelligence agent', which can cause the skill to activate for common writing or automation requests beyond the user's clear intent. In a skill that can collect external data, call APIs, and publish content, overbroad activation increases the chance of unintended execution of external actions.
The visible user-facing documentation and invocation phrases are primarily in Korean, and the file does not indicate that users may choose another language or that the skill is intentionally limited to a Korean-only audience. Under the language/locale policy, forcing a specific language without opt-in can be a natural-language policy issue.
The skill describes automated collection, LLM generation, Notion publishing, and Git-based deployment, but does not clearly warn that article content, prompts, metadata, and possibly user-supplied text will be transmitted to third-party services. This creates a meaningful data handling and consent risk because users may provide proprietary or sensitive material without understanding it leaves the local environment.
The skill is explicitly configured to transmit data to an external LLM endpoint at api.z.ai, and elsewhere also indicates writes to Notion and GitHub-related services. External transmission is expected for the feature set, but it is still security-relevant because prompts, article content, URLs, and possibly user-provided or internal data may be exposed to third-party infrastructure.
# GLM API
GLM_API_KEY=your_glm_api_key
GLM_BASE_URL=https://api.z.ai/api/coding/paas/v4
# Notion
NOTION_API_KEY=ntn_xxx
The architecture document is written entirely in Korean, including all operational descriptions and workflow instructions, with no indication that language choice is optional or that the skill is intended only for a Korean-speaking context. This can violate a language/locale policy when users are not offered an opt-in or alternative locale.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
class NotionPublisher:
def create_article(self, blog_post):
# Notion API 호출
response = requests.post(
f"https://api.notion.com/v1/pages",
headers={
"Authorization": f"Bearer {NOTION_API_KEY}",
The code accesses the NOTION_API_KEY environment variable, which is a sensitive credential. While the script's purpose implies Notion access, there is no user-facing disclosure, prompt, or explicit warning in this file that credentials will be read from the local environment.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
}
try:
response = requests.post(query_url, headers=headers, json=payload)
response.raise_for_status()
data = response.json()
No suspicious patterns detected.