T09 · Insecure Skill Coding Practices
- Location
assets/docker-compose.yml:8- Finding
Deployment Uses Predictable Default Credentials on a Network-Exposed Service
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a real Akaunting integration, but it handles financial data with insecure HTTP/default-credential setup and includes privileged container patching that users should review before installing.
Review before installing. Use only with a dedicated low-privilege Akaunting account, change all default passwords, bind the service to localhost or protect it behind HTTPS and firewall rules, avoid sending Basic Auth over HTTP, restrict permissions on any credential file, and treat the Docker repair script as an administrator maintenance action that changes application code.
assets/docker-compose.yml:8Deployment Uses Predictable Default Credentials on a Network-Exposed Service
scripts/akaunting.py:36Basic Authentication Credentials Can Be Transmitted over Plaintext HTTP
SKILL.md:49Plaintext Credential File Is Created Without Enforced Restrictive Permissions
assets/docker-compose.yml:5Unpinned Mutable Container Image Creates a Supply-Chain Risk
The documented behavior goes beyond REST API interaction and includes deployment, application patching, and source/configuration modification. This mismatch is dangerous because users may invoke an accounting skill expecting limited API operations, while the skill can perform maintenance or invasive host/container changes that materially expand the attack surface.
The setup instructions expose the service over plain HTTP and later pair that with Basic Auth credentials. This creates a clear risk of credential interception and financial data disclosure via network sniffing or man-in-the-middle attacks, especially if users follow the example on non-local or shared networks.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
GET /api/accounts/{id} # Get single account POST /api/accounts # Create account PUT /api/accounts/{id} # Update account DELETE /api/accounts/{id} # Delete account
**Create account:**
The skill advertises network, shell, and environment-dependent behavior but does not declare any tool scope or permission boundaries. In an agent setting, this makes the skill harder to constrain and review, increasing the chance of unintended command execution, credential access, or network actions beyond the user's expectations.
The trigger conditions are broad enough to activate on many ordinary accounting or invoicing conversations. In an agent ecosystem, overbroad routing can cause this skill to handle prompts it should not, leading to unnecessary access to financial systems, credentials, or transaction-creation capabilities.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
akaunting categories
akaunting transactions
akaunting income --amount 100 --category Sales --description "Payment received" akaunting expense --amount 50 --category Other --description "Office supplies"
The documentation instructs users to store credentials in plaintext config and use HTTP Basic Auth, but provides no warning about local secret exposure, process leakage, or transport risks. Because this skill manages financial data, compromise of these credentials could allow unauthorized access to accounts, transactions, and other sensitive bookkeeping records.
This markdown API reference documents DELETE /api/accounts/{id} as an available operation, but nowhere around the endpoint or elsewhere in the file does it warn that the action may permanently remove account data. For markdown files, destructive or irreversible behaviors should be disclosed so users understand the risk before using the skill or API.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
def cmd_income(args, config):
"""Create income transaction."""
# Get category ID
categories = api_request("GET", "categories", config, params={"search": f"name:{args.category}"})
cat_id = None
The script performs a POST that creates an income transaction immediately from command-line inputs, with no confirmation prompt, dry-run mode, or safety warning before mutating accounting data. In an agent/automation context, this raises the risk of accidental or prompt-induced financial record creation, which can corrupt books or trigger downstream business processes.
The expense command issues a POST to create a financial expense record without any user confirmation or review step. For accounting software, unintended expense creation can alter ledgers, misstate reporting, and create audit/compliance issues if triggered erroneously by automation.
This file performs local Docker-based file patching and cache clearing inside the Akaunting container, including modifying application PHP source under /var/www/html/app/Providers/Event.php. That behavior is inconsistent with the skill's declared purpose of interacting with Akaunting over REST and creates an unexpected privileged maintenance backdoor that can alter application code and runtime behavior.
The skill has an unjustified ability to execute arbitrary commands in the Akaunting container despite being presented as a bookkeeping/API integration skill. In context, this mismatch is especially dangerous because users or orchestrators may grant the skill trust appropriate for invoice/accounting actions, not local code execution and application patching.
The script executes shell commands inside a Docker container via docker exec ... bash -c, which creates a command-execution capability beyond normal accounting/API operations. Although the current call sites use hardcoded commands rather than direct user input, this still increases attack surface and enables container-side code modification if the script is invoked in the wrong context or later extended unsafely.
def run_docker(cmd: str) -> tuple[int, str]:
"""Run command in Docker container."""
result = subprocess.run(
["docker", "exec", CONTAINER_NAME, "bash", "-c", cmd],
capture_output=True,
text=True
This manifest sets LOCALE=en-US directly, which imposes a specific language/locale choice in configuration without any indication of user selection or region-specific justification. That matches the policy concern for natural-language locale restrictions when no opt-in is evident.
The item creation command sends a POST to create products/services directly, again without confirmation or warning. While less severe than financial transactions, unauthorized or accidental item creation can still pollute inventory/catalog data and affect invoicing workflows.
No suspicious patterns detected.