T09 · Insecure Skill Coding Practices
- Location
scripts/post-moment-ai.js:159- Finding
Opaque Server-Generated Blockchain Transactions Are Signed Without Local Validation
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is not plainly malicious, but it can use a private wallet key to publish content and submit blockchain transactions automatically without strong local checks or confirmations.
Install only if you are comfortable giving this skill a dedicated, low-privilege LUKSO controller key and reviewing every live action before use. Do not use a high-value wallet key, avoid unattended cron until spend/posting limits and payload validation are added, and treat IPFS uploads and social posts as public and hard to undo.
scripts/post-moment-ai.js:159Opaque Server-Generated Blockchain Transactions Are Signed Without Local Validation
scripts/post-moment-with-image.js:36Caller-Controlled File Path Can Be Uploaded and Pinned to IPFS Without Validation
The description claims a multi-function Forever Moments skill covering several decentralized social and token operations. The supplied code chunk is much narrower: it exclusively automates creation of a moment with optional AI-generated imagery, IPFS pinning, and mint execution on LUKSO. That does align with the subset of the description about posting moments and automated AI-generated image posting, but it does not support the other prominently declared use cases such as LIKES token mint/buy, collection membership management, sale listing, or liking moments. This is a material description-to-behavior mismatch because the declared scope is substantially broader than the implemented behavior.
This is a material description-behavior mismatch. The description presents a broad Forever Moments/LUKSO integration skill with onchain and social-platform actions. The actual code only supports one small preparatory workflow: generate an AI image from predefined prompts and save accompanying metadata locally for later use. The script even states that minting is skipped and the API service is unavailable. While automated AI-generated posting is mentioned in the declared use cases, the actual implementation does not complete posting at all, so it falls well short of the declared primary purpose.
The supplied code chunk has a much narrower scope than the declared description. It implements a single posting flow: build mint payload for a moment, sign relay request with a controller private key, and submit it. That aligns with 'post a moment' on Forever Moments, but none of the other advertised capabilities are present. The success criteria also mention returning an IPFS CID and image pinning, which this code does not do; it only returns a transaction hash. There is no DALLE usage, no LIKES token logic, no collection membership logic, no marketplace/sale logic, and no code for sending likes. This is therefore a description-behavior mismatch due to substantial overstatement of capabilities.
Referenced artifact was not completely inspected
node scripts/post-moment-ai.js "Title" "Desc" "tags" "image prompt"
Referenced artifact was not completely inspected
node scripts/post-moment-ai.js "Title" "Desc" "tags" "image prompt"
The README explicitly documents automated posting via cron together with on-chain minting and relay submission, but it does not clearly warn that these actions create external side effects such as publishing content to a public social platform, pinning data to IPFS, and potentially spending assets or consuming relay quota. In an agent setting, this increases the risk that an operator enables unattended execution without understanding that the skill can trigger irreversible public and blockchain-visible actions.
The skill documents access to environment variables and multiple network endpoints, but it does not declare any tool scope or permission boundaries. In an agent setting, missing explicit scope increases the chance the skill can access secrets or make outbound requests beyond what reviewers and users expect.
The file says all operations are gasless while elsewhere stating LIKES minting costs LYX and may require spending approval. That contradiction can mislead users into authorizing value-bearing operations without understanding the financial impact, which is especially risky in a blockchain skill handling signing and token spending.
The skill instructs users to provide a controller private key and demonstrates raw-digest signing, but it does not prominently warn about the sensitivity of that key, the scope of permissions it may grant, or the irreversible consequences of signing arbitrary payloads. In this context, the combination of secret handling, transaction building, relay submission, and spending-related actions materially raises the risk of wallet compromise or unauthorized asset movement if the skill is misused or the API is malicious.
The document opens by saying the repo exposes an agent-friendly API for building transaction plans, which suggests a planner/builder scope. Later sections document POST /api/agent/v1/relay/submit as a proxy for sending signed requests to the relayer, which goes beyond merely building plans and into transaction submission/execution support.
The documentation explicitly tells agents/operators they need a controller EOA private key for signing relay digests, but it does not include strong handling guidance, storage restrictions, or warnings against exposing that key to untrusted agent flows. In this skill context, that is more dangerous because the skill is intended for automated posting and blockchain actions, increasing the chance that an agent runtime or integration will ingest, persist, or misuse highly sensitive signing credentials.
This script directly signs and submits a relay transaction that spends value on-chain to mint LIKES, using a configured private key and command-line amount, without any interactive confirmation, explicit irreversible-action warning, or spending guardrails. In the context of an agent skill for automated social actions, this is more dangerous because accidental invocation, parameter tampering, or downstream misuse can trigger real LYX expenditure from the configured Universal Profile with no last-mile user approval.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
throw new Error('DALLE_API_KEY not configured. Set it in environment variables.');
}
const response = await fetch('https://api.openai.com/v1/images/generations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
throw new Error('DALLE_API_KEY not configured. Set it in environment variables.');
}
const response = await fetch('https://api.openai.com/v1/images/generations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
User-supplied prompts are transmitted to OpenAI, and generated-image requests may expose sensitive or private content to third-party services without an explicit warning at the point of use. In a social-posting skill, users may assume local processing, so silent external transmission creates privacy and data-handling risk.
The script uploads generated images to IPFS via an external pinning endpoint without warning that the content may become publicly accessible and effectively permanent. Users may unintentionally publish sensitive, copyrighted, or private material, and the skill context makes this more dangerous because the upload is coupled directly to automated posting.
The script can sign and submit blockchain transactions using FM_PRIVATE_KEY with no interactive confirmation, policy check, spending cap, or dry-run gate. In the context of an automation/cron-capable social-posting skill, this increases the chance of unintended minting, gas spend, or abusive repeated posting if the script is misused or triggered unexpectedly.
The inline comment at L379 says random cron mode 'uses DALL-E 3 (premium)', while the earlier function documentation states Pollinations.ai is for cron/scheduled posts and DALL-E 3 is for manual posts (L36, L77). The code for --random also passes true at L382, which actually selects DALL-E, so the file contains actively conflicting intent documentation about which provider cron automation should use.
The header comment asserts that this version attempts direct posting without the API service. In practice, the code only downloads an image, writes metadata locally, and explicitly skips minting because the service is unavailable, so the documentation overstates the implemented behavior.
The code reads FM_PRIVATE_KEY, which is a credential-like secret, but only logs an error when variables are absent. There is no user disclosure or warning that the script handles sensitive key material, which is relevant for a cron-invoked automation script.
The script sends prompts to an external image-generation service without surfacing that data will leave the local environment. In an agent skill context, prompts can contain sensitive or user-derived content, so silent third-party transmission creates privacy and data-governance risk.
The manifest describes a skill for posting moments to Forever Moments and returning on-chain/IPFS results, but this script stops after generating an image and writing metadata to /tmp. Its own return path marks success even though no Forever Moments API call, IPFS pin, blockchain transaction, or minting step occurs.
The script automatically signs and submits a blockchain mint transaction using FM_PRIVATE_KEY with no interactive confirmation, spending review, or policy gate at the point of execution. In the context of a social-posting automation skill, this is risky because any caller or automation path that reaches postMoment can trigger on-chain actions under the configured Universal Profile controller, potentially causing unauthorized posting, relay abuse, or unintended asset/account activity if inputs or invocation are compromised.
The script signs and submits a transaction with a raw private key immediately after receiving relay data, with no interactive confirmation, policy check, or verification that the payload matches the user's intent. In this skill's context, that is especially risky because posting triggers an on-chain action from a Universal Profile controller, so misuse, compromised inputs, or unexpected API responses could cause unauthorized transactions to be signed and relayed automatically.
The 'What this API does' section frames the API as returning transaction plans for onchain actions. However, the endpoint map and later sections also document POST /api/pinata, which uploads binaries to IPFS and is not a transaction-plan endpoint, creating an intent/documentation inconsistency.
Detected: suspicious.env_credential_access