T08 · Insecure Dependencies
- Location
scripts/feishu_send.py:15- Finding
Automatic Installation of an Unpinned Python Dependency
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
Review recommended: the skill is mainly a Feishu file sender, but it automatically installs code dependencies and can duplicate or leave processed copies of local files while uploading data externally.
Install only if you are comfortable with this skill reading the exact local files you specify, using Feishu app credentials, uploading those files to Feishu, and sending messages as the configured app. Preinstall reviewed dependencies instead of relying on runtime pip install, avoid storing broad secrets in the skill .env file, and use caution with large non-media files because the ZIP splitting behavior can create persistent duplicate archives.
scripts/feishu_send.py:15Automatic Installation of an Unpinned Python Dependency
scripts/feishu_send.py:273Incorrect ZIP Splitting Causes Disk and Network Resource Amplification
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
if not APP_ID or not APP_SECRET:
raise Exception('未配置 FEISHU_APP_ID 或 FEISHU_APP_SECRET 环境变量。请设置后重试。')
url = 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal'
resp = requests.post(url, json={'app_id': APP_ID, 'app_secret': APP_SECRET}, timeout=10)
data = resp.json()
if data.get('code') != 0:
raise Exception(f'获取 token 失败: {data}')
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
if not APP_ID or not APP_SECRET:
raise Exception('未配置 FEISHU_APP_ID 或 FEISHU_APP_SECRET 环境变量。请设置后重试。')
url = 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal'
resp = requests.post(url, json={'app_id': APP_ID, 'app_secret': APP_SECRET}, timeout=10)
data = resp.json()
if data.get('code') != 0:
raise Exception(f'获取 token 失败: {data}')
This duplicate mismatch finding highlights the same core risk: the skill promises non-reencoding 20MB segmentation and simple ZIP handling, but may instead transcode audio, auto-merge separate streams, and create misleading ZIP parts. In a tool that transmits local data externally, behavior mismatches are security-relevant because users may expose more content than intended or trust incorrect handling guarantees.
This duplicate mismatch finding highlights the same core risk: the skill promises non-reencoding 20MB segmentation and simple ZIP handling, but may instead transcode audio, auto-merge separate streams, and create misleading ZIP parts. In a tool that transmits local data externally, behavior mismatches are security-relevant because users may expose more content than intended or trust incorrect handling guarantees.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
## 配置
### 方式一:.env 文件(推荐)
在技能目录下创建 `.env` 文件:
The script accesses a .env file in the skill directory and loads any key/value pairs into process environment variables automatically. In an agent or shared workspace context, this can cause unintended secret consumption from local files and makes credential use less visible to operators, increasing the risk of misuse or accidental exposure through subsequent network actions.
def load_env_from_skill_dir():
script_dir = os.path.dirname(os.path.abspath(__file__))
skill_dir = os.path.dirname(script_dir)
env_path = os.path.join(skill_dir, '.env')
if os.path.isfile(env_path):
with open(env_path, 'r', encoding='utf-8') as f:
for line in f:
The script automatically loads secrets from a plaintext .env file in the skill directory, which increases the chance of credential exposure through weak file permissions, accidental inclusion in archives, or unintended reuse by other local processes. In a skill that already performs outbound file transfer, colocating and auto-loading credentials from the working tree enlarges the blast radius if the directory contents are mishandled.
def load_env_from_skill_dir():
script_dir = os.path.dirname(os.path.abspath(__file__))
skill_dir = os.path.dirname(script_dir)
env_path = os.path.join(skill_dir, '.env')
if os.path.isfile(env_path):
with open(env_path, 'r', encoding='utf-8') as f:
for line in f:
The skill can read local files, access environment secrets, invoke shell tools, and send data over the network, but it does not declare an explicit tool scope such as allowed-tools or permissions. That omission reduces transparency and weakens policy enforcement, making it easier for a caller to invoke a data-exfiltration-capable skill without clear guardrails.
The skill description says it sends local files to Feishu, but it lacks a prominent explicit warning that local filesystem contents will be transmitted to an external service. For exfiltration-prone functionality, this missing warning makes accidental disclosure more likely, especially when paths may reference sensitive documents or media.
Automatically installing dependencies from pip during execution is a dangerous behavior for a skill whose stated purpose is file transfer. It introduces supply-chain risk and causes external code to be installed and potentially executed without explicit approval, which is especially risky in automated agent environments.
The script automatically installs Python packages at runtime via pip, which exceeds the stated file-sending purpose and causes code from external package repositories to be fetched and executed on the host. Even though the package name is hardcoded, auto-installing dependencies during skill execution expands the attack surface and can lead to unintended code execution or supply-chain exposure.
def install_python_package(package):
print(f'正在安装 Python 依赖: {package}...')
try:
subprocess.check_call([sys.executable, '-m', 'pip', 'install', package], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
print(f'{package} 安装成功')
return True
except subprocess.CalledProcessError:
The script silently reads credentials from the environment and a local .env file without prominent disclosure. In an agent skill setting, undeclared secret access is risky because operators may not realize the skill consumes sensitive authentication material from the workspace or runtime environment.
The script uploads arbitrary local files and recipient identifiers to Feishu but does not provide an explicit safety warning, confirmation step, or clear disclosure at the point of transfer. In an agent skill context, this increases the chance of accidental exfiltration of sensitive local data because the capability is broad and the destination is external.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
url = f'https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type={receive_id_type}'
body = {'receive_id': receive_id, 'msg_type': 'file', 'content': json.dumps({'file_key': file_key}), 'uuid': str(uuid.uuid4())}
headers = {'Authorization': f'Bearer {token}', 'Content-Type': 'application/json; charset=utf-8'}
resp = requests.post(url, headers=headers, json=body, timeout=60)
return resp.json()
def process_and_send_file(token, filepath, receive_id, receive_id_type):
Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.
def check_python_package(package):
try:
__import__(package)
return True
except ImportError:
return False
Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.
def check_python_package(package):
try:
__import__(package)
return True
except ImportError:
return False
The script automatically installs Python packages at runtime via pip without explicit user confirmation or pinning versions. In a skill whose purpose is to move local files off-host, silent dependency installation expands the trust boundary and can execute unreviewed package install hooks or pull tampered packages from the package index.
def install_python_package(package):
print(f'正在安装 Python 依赖: {package}...')
try:
subprocess.check_call([sys.executable, '-m', 'pip', 'install', package], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
print(f'{package} 安装成功')
return True
except subprocess.CalledProcessError:
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def check_system_command(cmd):
try:
result = subprocess.run([cmd, '-version'], capture_output=True, timeout=5)
return result.returncode == 0
except (FileNotFoundError, subprocess.TimeoutExpired):
return False
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def check_system_command(cmd):
try:
result = subprocess.run([cmd, '-version'], capture_output=True, timeout=5)
return result.returncode == 0
except (FileNotFoundError, subprocess.TimeoutExpired):
return False
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
'ffmpeg': {
'win32': 'choco install ffmpeg 或 winget install ffmpeg',
'darwin': 'brew install ffmpeg',
'linux': 'sudo apt install ffmpeg 或 sudo yum install ffmpeg'
},
'ffprobe': {
'win32': 'choco install ffmpeg 或 winget install ffmpeg',
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
'ffmpeg': {
'win32': 'choco install ffmpeg 或 winget install ffmpeg',
'darwin': 'brew install ffmpeg',
'linux': 'sudo apt install ffmpeg 或 sudo yum install ffmpeg'
},
'ffprobe': {
'win32': 'choco install ffmpeg 或 winget install ffmpeg',
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
'ffmpeg': {
'win32': 'choco install ffmpeg 或 winget install ffmpeg',
'darwin': 'brew install ffmpeg',
'linux': 'sudo apt install ffmpeg 或 sudo yum install ffmpeg'
},
'ffprobe': {
'win32': 'choco install ffmpeg 或 winget install ffmpeg',
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
'ffmpeg': {
'win32': 'choco install ffmpeg 或 winget install ffmpeg',
'darwin': 'brew install ffmpeg',
'linux': 'sudo apt install ffmpeg 或 sudo yum install ffmpeg'
},
'ffprobe': {
'win32': 'choco install ffmpeg 或 winget install ffmpeg',
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not APP_ID or not APP_SECRET:
raise Exception('未配置 FEISHU_APP_ID 或 FEISHU_APP_SECRET 环境变量。请设置后重试。')
url = 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal'
resp = requests.post(url, json={'app_id': APP_ID, 'app_secret': APP_SECRET}, timeout=10)
data = resp.json()
if data.get('code') != 0:
raise Exception(f'获取 token 失败: {data}')
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
if not APP_ID or not APP_SECRET:
raise Exception('未配置 FEISHU_APP_ID 或 FEISHU_APP_SECRET 环境变量。请设置后重试。')
url = 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal'
resp = requests.post(url, json={'app_id': APP_ID, 'app_secret': APP_SECRET}, timeout=10)
data = resp.json()
if data.get('code') != 0:
raise Exception(f'获取 token 失败: {data}')
No suspicious patterns detected.