T09 · Insecure Skill Coding Practices
- Location
scripts/create_sign_task.py:42- Finding
Unrestricted API and Transfer Endpoints Can Exfiltrate Credentials, Contracts, and Signer Data
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This appears to be a real FaDaDa e-signing skill, but it needs review because it can send sensitive contracts, signer data, and credentials to configurable network destinations without strong guardrails.
Install only if you trust the publisher and need FaDaDa signing automation. Before use, keep credentials in environment variables or a secret manager, avoid command-line secrets, verify config files cannot set an unexpected server_url, confirm the exact contract file, recipient details, and destination before any send or batch operation, and treat signing/download links and generated reports as sensitive.
scripts/create_sign_task.py:42Unrestricted API and Transfer Endpoints Can Exfiltrate Credentials, Contracts, and Signer Data
SKILL.md:36Documented Configuration Workflow Stores API Secrets in Plaintext Without Enforcing Restrictive Permissions
scripts/fadada_sign.py:37App Secret Accepted as a Command-Line Argument
scripts/query_sign_status.py:165Unbounded and Unvalidated Network Transfers Can Cause Denial of Service or Invalid Document Writes
The description claims a complete electronic contract signing skill with operational features like sending contracts, checking signature status, and downloading signed contracts. However, the supplied code chunk is only a helper script for generating authentication headers and verifying callback signatures for the Fadada API. These are supporting utilities, but they do not implement the core declared functionality. Because the actual code’s primary behavior is materially narrower and different from the declared end-user purpose, this is a clear description-behavior mismatch.
代码与法大大电子签署场景总体一致,核心能力确实是发送合同供对方签署,包括文件上传、模板填充、创建签署任务和获取签署链接。因此主目的并未偏离声明,也没有发现明显的越权或无关资源访问。问题在于声明包含了更完整的能力范围——“查询签署状态、下载已签署合同”——而本代码片段仅覆盖“发起签署任务/发送合同签署”这部分,没有看到状态查询或已签合同下载接口实现。依据评估标准,这属于描述与实际行为不完全一致的能力性缺口,应判定为 mismatch。
声明描述的是完整的电子合同签署业务技能,核心能力应包括调用法大大接口发起合同、查询状态、下载文件等。但提供的代码片段没有任何网络请求、合同数据处理、状态查询或文件下载逻辑,只是一个底层辅助脚本,用于生成 API 鉴权请求头和校验回调签名。这属于与声明的主要用途存在实质性差异,因此应判定为描述与实际行为不一致。
声明把该技能描述为既能发起合同签署,也能查询状态、下载合同的综合电子签能力。但提供的代码块仅覆盖查询相关操作:获取access token、查询签署任务、下载已签署文件,以及额外的撤销任务和监控状态。最关键的声明能力“发送合同给对方签署”在代码中没有体现,因此描述与实际行为存在实质性偏差。此外,代码具备“撤销任务”这一未声明的敏感业务操作,属于未披露能力。虽然查询状态和下载合同与声明部分一致,但整体上仍应判定为描述与行为不完全匹配。
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
self._token = None
def _get_access_token(self) -> str:
"""获取 Access Token"""
if SDK_AVAILABLE:
response = self.service_client.get_access_token()
return response.data.access_token
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
self._token = None
def _get_access_token(self) -> str:
"""获取 Access Token"""
if SDK_AVAILABLE:
response = self.service_client.get_access_token()
return response.data.access_token
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
self._token = None
def _get_access_token(self) -> str:
"""获取 Access Token"""
if SDK_AVAILABLE:
response = self.service_client.get_access_token()
return response.data.access_token
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
self._token = None
def _get_access_token(self) -> str:
"""获取 Access Token"""
if SDK_AVAILABLE:
response = self.service_client.get_access_token()
return response.data.access_token
The README instructs users to store long-lived API credentials in a plaintext file under the home directory without mentioning file permissions or secret management controls. On multi-user systems, shared environments, backups, or compromised developer machines, these credentials could be recovered and used to access contract workflows, signer data, and documents.
方式二:配置文件
mkdir -p ~/.fadada
cat > ~/.fadada/config.json << EOF
{
"app_id": "your_app_id",
This markdown file documents operations that upload a contract file and transmit personal data such as signer names and mobile numbers to an external e-signature service. The README presents these actions as one-click or CLI workflows but does not include any warning about sharing documents and personal information with a third-party service.
The skill documents capabilities that read environment variables, read and write local files, and perform network operations, but it declares no explicit tool scope or permission boundary. In an agent setting, this weakens reviewability and increases the chance the skill is invoked with broader access than users expect, especially since it handles credentials, contract files, and signer data.
The trigger phrases are broad enough to match ordinary discussion about contracts or e-signing, which can cause unintended activation of a skill that uploads files and transmits personal data to a third party. In this context, accidental invocation is more dangerous because the skill handles sensitive business documents and signer PII.
The skill does not clearly warn users that contract contents and signer personal data will be transmitted to an external e-sign provider. This omission undermines informed consent and can lead to unintentional disclosure of sensitive legal and personal information.
Storing API credentials in a persistent config file under the user's home directory creates a lasting secret exposure point, especially since the example does not enforce restrictive permissions at creation time. If the file is readable by other local users, synced, backed up insecurely, or inadvertently exposed, the service account could be abused.
方式二:配置文件
# 创建配置文件
mkdir -p ~/.fadada
cat > ~/.fadada/config.json << EOF
{
"app_id": "your_app_id",
The documented upload_file workflow sends local contract documents to a cloud service, which is an intentional feature but still a real exfiltration risk if invoked on the wrong file or without clear consent. Because the files are contracts, the sensitivity is often high and may include regulated or confidential business information.
client = FaDaDaClient(...)
# 1. 上传文件
file_id = client.upload_file("/path/to/contract.pdf")
# 2. 创建签署任务
signer = Signer(name="张三", mobile="13800138000")
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.
- **App Secret 不要硬编码**在代码中,建议使用环境变量或配置文件
- **配置文件权限**建议设置为 `600`(仅所有者可读写)
- **生产环境**建议使用正式环境(sandbox=False)
## 🐛 错误处理
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.
- **App Secret 不要硬编码**在代码中,建议使用环境变量或配置文件
- **配置文件权限**建议设置为 `600`(仅所有者可读写)
- **生产环境**建议使用正式环境(sandbox=False)
## 🐛 错误处理
The module title and usage description are presented only in Chinese, and the rest of the user-facing strings in the file also assume Chinese-language users. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is explicitly justified.
All user-facing strings, comments, and docstrings in this example are written only in Chinese, with no indication that the skill is China-specific or that users may choose another language. This creates a natural-language locale policy concern because the skill effectively enforces a single language without opt-in or justification.
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.
# 步骤1:上传文件
print("1. 上传文件...")
file_id = client.upload_file("./contract.pdf")
print(f" File ID: {file_id}")
# 步骤2:创建签署任务
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.
# 步骤1:上传文件
print("1. 上传文件...")
file_id = client.upload_file("./contract.pdf")
print(f" File ID: {file_id}")
# 步骤2:创建签署任务
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.
# 步骤1:上传文件
print("1. 上传文件...")
file_id = client.upload_file("./contract.pdf")
print(f" File ID: {file_id}")
# 步骤2:创建签署任务
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.
# 步骤1:上传文件
print("1. 上传文件...")
file_id = client.upload_file("./contract.pdf")
print(f" File ID: {file_id}")
# 步骤2:创建签署任务
Data is uploaded to cloud storage (S3 / GCS / Azure Blob). This may be a legitimate backup or exfiltration to an external bucket. Manual review is recommended.
# 步骤1:上传文件
print("1. 上传文件...")
file_id = client.upload_file("./contract.pdf")
print(f" File ID: {file_id}")
# 步骤2:创建签署任务
The trigger phrases are broad enough to activate on common mentions of contracts, signing, or e-signing, which can cause the agent to invoke an external contract-signing capability without sufficiently specific user intent. In this skill’s context, accidental activation is more dangerous than usual because it can lead to handling sensitive legal documents, participant identities, and outbound notifications through a third-party service.