T09 · Insecure Skill Coding Practices
- Location
scripts/ftp_resolver.py:91- Finding
SanMar SFTP Credentials Can Be Redirected to an Arbitrary Host
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The SanMar skill is mostly purpose-built for vendor lookups and ordering, but it needs review because it can expose credentials/order data and uses unsafe SFTP handling.
Install only after reviewing whether this agent should handle live SanMar credentials and purchase-order submission. Prefer a patched version that redacts raw SOAP output, verifies the SFTP host key, restricts SFTP to the official SanMar endpoint unless explicitly configured with separate credentials, and uses secure secret handling instead of pasting passwords into chats or logs.
scripts/ftp_resolver.py:91SanMar SFTP Credentials Can Be Redirected to an Arbitrary Host
scripts/ftp_resolver.py:159SFTP Server Identity Is Not Verified Before Password Authentication
scripts/sanmar_tools.py:495Purchase-Order Results Expose SOAP Passwords and Customer Data
scripts/sanmar_client.py:276Unescaped Input Is Interpolated into SOAP XML Requests
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def pre_submit_po(self, draft: PurchaseOrderDraft) -> CartValidationResult:
payload = self.build_po_envelope(draft, pre_submit=True)
text = self._post_soap(
self.endpoints.po_url(self.credentials.environment),
payload,
soap_action="getPreSubmitInfo",
operation="getPreSubmitInfo",
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def pre_submit_po(self, draft: PurchaseOrderDraft) -> CartValidationResult:
payload = self.build_po_envelope(draft, pre_submit=True)
text = self._post_soap(
self.endpoints.po_url(self.credentials.environment),
payload,
soap_action="getPreSubmitInfo",
operation="getPreSubmitInfo",
The skill documentation declares access to environment variables, local files, and networked services, but it does not constrain that access with an explicit tool scope such as permissions or allowed-tools. In an agent setting, this increases the blast radius: a prompt or implementation mistake could let the skill read secrets from env, access unintended files, or make outbound requests beyond the narrowly intended SanMar operations.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
- Prefer explicit timestamps from feed metadata where available.
- If freshness is critical, include source timestamp/date in response payload.
- Never assume a missing record is permanent without checking relevant active/closeout feeds.
## Error handling contract for this SME
The examples explicitly state that credentials may be passed inline in stdin JSON, which is risky because secrets can be exposed through shell history, process inspection, CI logs, terminal recording, or copied command transcripts. In this skill context, the danger is elevated because the credentials grant access to live supplier pricing, inventory, ordering, and possibly FTP-backed data sources, so exposed secrets could enable unauthorized order activity or data access.
This section instructs the agent to ask the user for sensitive credentials and then demonstrates resubmitting them inline, without any privacy or handling safeguards. That is dangerous because it normalizes collecting and retransmitting passwords in plain text, increasing the chance of disclosure in chat transcripts, orchestration logs, shell history, and downstream tool telemetry; in a purchasing skill, compromise could lead to unauthorized supplier account use and fraudulent order submission.
The CLI explicitly allows credentials such as username, password, customer_number, and ftp_password to be passed inline in stdin JSON. While stdin is safer than command-line arguments, this design still increases the chance that secrets are embedded in scripts, shell history wrappers, logs, CI job definitions, or agent transcripts, especially in an automation-focused skill that brokers purchase orders and pricing data. The skill context makes this more sensitive because it operates on real vendor accounts and order workflows, so credential mishandling could expose pricing, inventory, or purchasing capabilities.
The client exposes a direct order-submission method that creates real external purchase orders with no built-in confirmation, dry-run safeguard, or explicit caller acknowledgement requirement. In an agent/tooling context, this increases the chance of unintended side effects from prompt mistakes, ambiguous user intent, or chaining errors, because calling this method immediately triggers a state-changing transaction against SanMar.
This markdown file describes live SOAP endpoints and later identifies request keys such as sanMarCustomerNumber, which implies sending customer/account-linked data to an external network service. Under the markdown-specific warning rule, the document should disclose privacy or operational implications of contacting production services and transmitting identifiers.
This code file documents that credentials may be sourced from SANMAR_* environment variables, which is access to sensitive credential material. While the behavior is mentioned in an internal module docstring, there is no user-facing confirmation, warning, or visible disclosure at runtime when credentials are pulled from the environment.
The module will implicitly read SanMar FTP credentials from ambient environment variables when explicit credentials are not passed. In an agent/runtime setting, this can broaden the skill’s authority beyond user-supplied inputs, causing unintended use of host secrets and creating a boundary violation if the runtime exposes credentials the current task was not meant to access.
All user-facing usage and action descriptions in the docstring are presented only in English, and the file does not offer any language or locale choice. Under the stated policy, forcing a specific language without user opt-in can be a natural-language policy violation.
This code packages username and password into a plain dictionary for downstream transmission, but there is no inline warning, confirmation, or user-facing disclosure in this file about handling sensitive credentials. Because this is an auth-related code path and the surrounding docstrings emphasize portability rather than sensitivity, users and integrators are not alerted to the security implications of passing raw credentials.
Detected: suspicious.exposed_secret_literal