T09 · Insecure Skill Coding Practices
- Location
scripts/publish_guard.py:173- Finding
Active Credential Store Persists Authentication Secrets in Plaintext
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill has a coherent publishing-helper purpose, but it should be reviewed because it can persist real account credentials insecurely and verify arbitrary URLs from the agent host.
Review before installing. Do not store real platform tokens with this skill unless the credential path is fixed to use a proper secret store or audited encryption, and avoid verifying URLs that are not public posts on the intended platform. Also consider clearing audit logs because they may retain full URLs, titles, post IDs, and error details.
scripts/publish_guard.py:173Active Credential Store Persists Authentication Secrets in Plaintext
scripts/publish_guard.py:248Unrestricted Post Verification URL Enables Server-Side Request Forgery
scripts/vault_crypto.py:36Vault Master Key Is Derived from Predictable Machine Metadata
scripts/publish_guard.py:548Audit Logs Persist Full URLs and Publishing Metadata Without Explicit Access Controls
The module documentation materially misrepresents the cryptographic design by claiming AES-256-CBC and Fernet compatibility when the code actually implements a custom HMAC-derived XOR stream cipher. This can cause operators and downstream code to rely on interoperability and security properties that do not exist, increasing the chance that sensitive credentials are stored under a homegrown scheme without proper review.
The skill explicitly promotes persistent credential storage and audit logging, but the user-facing description does not prominently warn that sensitive publishing data, tokens, URLs, and activity history may be retained across sessions. In an agent skill context, undisclosed persistence materially increases the risk of accidental secret retention, privacy leakage, and misuse of historical publishing metadata by later runs or other components.
The BotMadang platform configuration states that titles must contain Korean characters, and the validator enforces this by rejecting titles without Korean. This is a natural-language locale constraint presented as a hard requirement, but the skill does not offer an opt-in choice or explain a policy justification for forcing that language behavior.
The skill automatically writes platform authentication data to persistent local storage without a clear user-facing warning or consent flow. This increases the chance that sensitive tokens are retained longer than intended, left behind in shared workspaces, or captured in snapshots and backups. In a multi-session agent environment, silent persistence of credentials is security-relevant because users may assume credentials are ephemeral.
The credential store persists authentication material to a JSON file in plaintext while the comments describe the location as a secure 'vault'. Any local user, compromised process, backup system, or accidental file disclosure can recover API tokens directly and use them to post or impersonate the agent on external platforms. In an agent skill whose purpose includes credential management, this materially increases the likelihood of secret exposure.
The validator programmatically rejects content unless the title contains Korean characters, which constitutes a language/locale restriction. Because the skill does not provide a language choice or clearly frame this as a justified region-specific compliance requirement, it matches the policy-violation criterion.
The comments state that the code implements AES-256-CTR, but no AES primitive exists in the Python standard library and the actual code uses HMAC output as a keystream. Mislabeling a custom cipher as AES can mislead reviewers into approving or depending on a stronger and more standardized primitive than is actually present.
Natural-language statements in comments and CLI output present strong security guarantees for a custom cryptographic construction, including a final message asserting the system is secure. Such blanket assurance can violate policy expectations around careful security claims because users may rely on these statements beyond what is justified or independently validated.
The migration routine irreversibly overwrites and deletes the plaintext credential file without confirmation, backup, or transactional safeguards. If migration fails partway, the wrong file path is supplied, or the encrypted vault is not actually usable on another system, users can lose access to credentials or destroy sensitive source data unexpectedly.
Tool defaults are unsafe or overly permissive (e.g. disabled TLS verification, no authentication, world-writable permissions). Unsafe defaults widen the attack surface.
# Verify permissions
import stat
mode = os.stat("/tmp/test_vault.vault").st_mode
assert not (mode & stat.S_IROTH), "FAIL: File is world-readable!"
assert not (mode & stat.S_IRGRP), "FAIL: File is group-readable!"
print(" ✅ File permissions: owner-only (0600)")
Natural-language statements in comments and CLI output present strong security guarantees for a custom cryptographic construction, including a final message asserting the system is secure. Such blanket assurance can violate policy expectations around careful security claims because users may rely on these statements beyond what is justified or independently validated.
The file states that BotMadang requires Korean in the title, which is a locale/language constraint presented as a platform-specific rule. In this skill description, that requirement is not framed as an optional user choice or clearly justified compliance limitation, so it may violate the language/locale policy criterion.
No suspicious patterns detected.