Back to skill

Security audit

Warren - On-Chain NFT Deploy

Security checks for vulnerabilities and agentic risk

Overview

This NFT deployment skill is mostly purpose-aligned, but it needs review because it uses wallet signing authority to deploy opaque contract bytecode with an undisclosed default treasury and limited user confirmation.

Install only if you trust the publisher and are comfortable using a testnet wallet with this tool. Use a dedicated wallet with limited funds, avoid passing private keys on the command line, review the default TREASURY_ADDRESS and REGISTER_API settings, and treat the embedded contract bytecode as unaudited unless the publisher provides matching source and build verification.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
deploy-nft.js:502
Finding

Wallet Private Key Can Be Exposed Through Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: deploy-nft.js, lines 502-503
Vulnerability Type: Plaintext credential exposure through process arguments
Risk Level: High

Vulnerable Code:

js
const privateKey = getArg('private-key') || process.env.PRIVATE_KEY;
if (!privateKey) { console.error('Error: set PRIVATE_KEY env or use --private-key'); process.exit(1); }

The command-line interface explicitly documents this option at line 492:

js
--private-key <key>       Wallet private key (or set PRIVATE_KEY env)

Technical Analysis

The application accepts a raw wallet private key through the --private-key command-line option. Command-line arguments may be exposed through:

  • Process inspection utilities such as ps or /proc/<pid>/cmdline
  • Shell command history
  • Process monitoring and endpoint telemetry
  • CI/CD job logs
  • Debugging and crash-reporting systems

Any local user or monitoring process with permission to inspect the deployment process may recover the key while the command is running. The key may remain accessible afterward if the complete command is retained in shell history or logs.

Although using the PRIVATE_KEY environment variable avoids direct command-line exposure, environment variables can also be exposed through process inspection or diagnostic collection. An encrypted keystore or external signer is safer.

Attack Path

  1. A user starts a deployment using:
    bash
    node deploy-nft.js --private-key 0xSECRET... --generate-svg 10 --name "Example" --symbol "EX"
    
  2. The complete command is recorded in shell history or exposed in the process argument list.
  3. A local attacker, monitoring agent, or log reader obtains the argument value.
  4. The attacker imports the recovered private key into another wallet.
  5. The attacker signs arbitrary transactions as the victim and can transfer assets or exercise contract privileges controlled by that wallet. ...[truncated 390 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove support for the --private-key command-line option.
  2. Prefer an external wallet, hardware wallet, remote signer, or encrypted JSON keystore.
  3. If direct key entry remains necessary, read it from an interactive hidden prompt that does not echo or retain the value.
  4. Avoid printing, logging, serializing, or including the key in error objects.
  5. Clear references to sensitive key material as soon as practical, recognizing that JavaScript does not guarantee secure memory erasure.
  6. Warn users not to place secrets in shell history, source files, .env files committed to version control, or CI job definitions.
  7. Where environment variables must be supported, load them through a protected secret manager with restricted process and log access.

T08 · Insecure Dependencies

Warning
Location
setup.sh:4
Finding

Unpinned Dependency Installation Creates a Mutable Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: setup.sh, lines 4-5
Vulnerability Type: Unpinned third-party dependency installation
Risk Level: Medium

Vulnerable Code:

bash
npm init -y > /dev/null 2>&1
npm install ethers

Technical Analysis

The setup script installs ethers without an exact version and generates package metadata dynamically. No reviewed lockfile is used by this installation flow. Consequently, the code installed for the same project can change over time without any modification to the Skill itself.

This creates both security and reliability risks:

  • A compromised package release could introduce malicious executable code.
  • A future incompatible release could alter transaction handling or wallet behavior.
  • Dependency resolution may introduce changed transitive dependencies.
  • npm lifecycle scripts may execute during installation unless explicitly disabled.

This application handles a wallet private key and signs blockchain transactions, so compromise of its dependency chain has particularly significant consequences.

Attack Path

  1. An attacker compromises the npm package, a maintainer account, or a transitive dependency.
  2. A malicious version becomes the version resolved by npm install ethers.
  3. A user runs bash setup.sh, causing the mutable package version to be installed.
  4. Malicious code executes through an installation lifecycle script or when require('ethers') loads the package.
  5. The malicious dependency reads wallet credentials, changes transaction recipients or constructor parameters, or sends unauthorized signed transactions.

Impact Assessment

Exploitation could provide code execution with the privileges of the user running setup.sh or deploy-nft.js. Because the application loads wallet credentials and signs transactions, a compromised dependency could steal the private key, take control of wallet assets, modify deployments, or access oth ...[truncated 59 chars]

Remediation
View remediation

Remediation Suggestions

  1. Add a reviewed package.json with an exact dependency version rather than a floating version range.
  2. Generate, review, and commit package-lock.json.
  3. Replace dynamic initialization and installation with:
    bash
    npm ci --ignore-scripts
    
    when lifecycle scripts are not required.
  4. Verify dependency integrity and review all transitive dependencies before releases.
  5. Use automated dependency scanning while requiring manual review for lockfile changes.
  6. Consider vendoring or otherwise reproducibly building security-critical blockchain components.
  7. Run installation and deployment with the minimum required operating-system privileges.

T09 · Insecure Skill Coding Practices

Warning
Location
deploy-nft.js:319
Finding

Opaque Contract Bytecode Is Deployed with an Undocumented Third-Party Treasury

Content
View full analysis

Vulnerability Details

File Location: deploy-nft.js, lines 27 and 319-334
Vulnerability Type: Unverifiable smart-contract behavior and undisclosed financial configuration
Risk Level: Medium

Relevant Configuration:

js
const TREASURY_ADDRESS = process.env.TREASURY_ADDRESS || '0xcea9d92ddb052e914ab665c6aaf1ff598d18c550';

Deployment Code:

js
const factory = new ethers.ContractFactory(NFT_ABI, NFT_BYTECODE, wallet);
const deployTx = await factory.getDeployTransaction(
  RENDERER_ADDRESS,
  containerId,
  config.name,
  config.symbol,
  config.description,
  config.maxSupply,
  ethers.parseEther(config.whitelistPrice || '0'),
  ethers.parseEther(config.publicPrice || '0'),
  config.maxPerWallet,
  ethers.ZeroHash,
  config.royaltyReceiver || wallet.address,
  config.royaltyBps || 500,
  TREASURY_ADDRESS,
  wallet.address,
);

Technical Analysis

The application deploys a large embedded NFT_BYTECODE blob through an ABI but does not provide corresponding Solidity source code, compiler settings, build metadata, or reproducible bytecode verification instructions. The constructor also receives a default third-party treasury address.

The available JavaScript confirms that this treasury is included in every default deployment. However, the exact authority and financial behavior associated with the treasury cannot be reliably established from the supplied source. The project documentation does not clearly explain the treasury parameter, any platform fee, or the circumstances under which funds may be routed to it.

ABI declarations describe callable interfaces but do not prove that embedded bytecode implements only the represented or documented behavior. Users therefore cannot independently verify access controls, withdrawal behavior, fee routing, upgrade mechanisms, or other contract semantics before signing the deployment.

Attack Path

  1. A user trusts the do ...[truncated 1247 chars]
Remediation
View remediation

Remediation Suggestions

  1. Include the complete Solidity source code for the embedded NFT contract.
  2. Publish the exact compiler version, optimizer settings, dependency versions, and build command.
  3. Add a reproducible-build check that fails unless the compiled bytecode exactly matches NFT_BYTECODE.
  4. Verify deployed contracts on the relevant block explorer.
  5. Document the treasury’s owner, purpose, fee percentage, privileges, and all code paths that transfer funds to it.
  6. Display the effective treasury address and financial terms before deployment and require explicit user confirmation.
  7. Avoid silently applying a default third-party treasury; require an explicit configuration value where appropriate.
  8. Validate the configured treasury and contract addresses against an allowlist for the selected chain.
  9. Obtain an independent smart-contract audit and publish its scope and results.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (8)

Obfuscated Code

High
Category
Supply Chain
Confidence
50% confidence
Finding

Code contains obfuscation (base64, hex encoding with execution). This is often used to hide malicious functionality.

Content

Scanner excerpt · deploy-nft.js (reported line 74)May include surrounding context.

js
// Inline ABIs & Bytecode
// ============================================================================

const PAGE_BYTECODE = '0x60a0604052346100e45761025c80380380610019816100fc565b9283398101906020818303126100e4578051906001600160401b0382116100e4570181601f820112156100e4578051906001600160401b0382116100e85761006a601f8301601f19166020016100fc565b92828452602083830101116100e457815f9260208093018386015e8301015280518060401b6bfe61000180600a3d393df3000161fffe8211830152600b8101601583015ff09182156100d7575260805260405161013a908161012282396080518181816044015260d50152f35b63301164255f526004601cfd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b6040519190601f01601f191682016001600160401b038111838210176100e85760405256fe6080806040526004361015610012575f80fd5b5f3560e01c9081634822da1c146100c357506357de26a414610032575f80fd5b346100bf575f3660031901126100bf577f00000000000000000000000000000000000000000000000000000000000000006020608060405180935f19813b0164ffffffffff16905f6021830191601f8501903c808252016040810193846040528385528051938491826060850152018383015e5f828483010152603f1992601f8019910116810103010190f35b5f80fd5b346100bf575f3660031901126100bf577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f3fea2646970667358221220fe4f8a378a0b003d3e1438e45234630293b1a4f7cf94a9f28a4c2d2531789b9d64736f6c634300081a0033';
const PAGE_ABI = [{"type":"constructor","inputs":[{"name":"_content","type":"bytes"}],"stateMutability":"nonpayable"}];

const NFT_BYTECODE = '0x6080604052346105e957613ed180380380610019816105ed565b92833981016101c0828203126105e95761003282610612565b91602081015191604082015160018060401b0381116105e95781610057918401610626565b60608301519091906001600160401b0381116105e95781610079918501610626565b608084015190916001600160401b0382116105e957610099918501610626565b60a084015160c085015160e08601519161010087015193610120880151956100c46101408a01610612565b976101608a01519a60018060601b038c169c8d8d036105e9576100f76101a06100f06101808f01610612565b9d01610612565b6001600160a01b03
...[truncated 27 chars]

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · deploy-nft.js (reported line 74)May include surrounding context.

js
er = (total * 150n) / 100n;
  const MIN_GAS = 10_000_000n;
  const gasLimit = withBuffer < MIN_GAS ? MIN_GAS : withBuffer;
  return gasLimit < MAX_GAS_PER_TX ? gasLimit : MAX_GAS_PER_TX;
}

// ============================================================================
// Inline ABIs & Bytecode
// ============================================================================

const PAGE_BYTECODE = '0x60a0604052346100e45761025c80380380610019816100fc565b9283398101906020818303126100e4578051906001600160401b0382116100e4570181601f820112156100e4578051906001600160401b0382116100e85761006a601f8301601f19166020016100fc565b92828452602083830101116100e457815f9260208093018386015e8301015280518060401b6bfe61000180600a3d393df3000161fffe8211830152600b8101601583015ff09182156100d7575260805260405161013a908161012282396080518181816044015260d50152f35b63301164255f526004601cfd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b6040519190601f01601f191682016001600160401b038111838210176100e85760405256fe608080604052600436

Obfuscated Code

High
Category
Supply Chain
Confidence
50% confidence
Finding

Code contains obfuscation (base64, hex encoding with execution). This is often used to hide malicious functionality.

Content

Scanner excerpt · deploy-nft.js (reported line 77)May include surrounding context.

js
const PAGE_BYTECODE = '0x60a0604052346100e45761025c80380380610019816100fc565b9283398101906020818303126100e4578051906001600160401b0382116100e4570181601f820112156100e4578051906001600160401b0382116100e85761006a601f8301601f19166020016100fc565b92828452602083830101116100e457815f9260208093018386015e8301015280518060401b6bfe61000180600a3d393df3000161fffe8211830152600b8101601583015ff09182156100d7575260805260405161013a908161012282396080518181816044015260d50152f35b63301164255f526004601cfd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b6040519190601f01601f191682016001600160401b038111838210176100e85760405256fe6080806040526004361015610012575f80fd5b5f3560e01c9081634822da1c146100c357506357de26a414610032575f80fd5b346100bf575f3660031901126100bf577f00000000000000000000000000000000000000000000000000000000000000006020608060405180935f19813b0164ffffffffff16905f6021830191601f8501903c808252016040810193846040528385528051938491826060850152018383015e5f828483010152603f1992601f8019910116810103010190f35b5f80fd5b346100bf575f3660031901126100bf577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f3fea2646970667358221220fe4f8a378a0b003d3e1438e45234630293b1a4f7cf94a9f28a4c2d2531789b9d64736f6c634300081a0033';
const PAGE_ABI = [{"type":"constructor","inputs":[{"name":"_content","type":"bytes"}],"stateMutability":"nonpayable"}];

const NFT_BYTECODE = '0x6080604052346105e957613ed180380380610019816105ed565b92833981016101c0828203126105e95761003282610612565b91602081015191604082015160018060401b0381116105e95781610057918401610626565b60608301519091906001600160401b0381116105e95781610079918501610626565b608084015190916001600160401b0382116105e957610099918501610626565b60a084015160c085015160e08601519161010087015193610120880151956100c46101408a01610612565b976101608a01519a60018060601b038c169c8d8d036105e9576100f76101a06100f06101808f01610612565b9d01610612565b6001600160a01b03909c169d8e156105da576001600160a01b038d169081156105da576103e8106105cb5780638b78c6d819555f7f8be0079c531659141
...[truncated 27 chars]

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill advertises executable steps that require network access and use of environment-supplied secrets, but it does not declare an explicit tool/permission scope. This weakens least-privilege controls and transparency for users or agent platforms, increasing the chance the skill runs with broader capabilities than necessary or accesses sensitive environment data unexpectedly.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill instructs users to pass a raw PRIVATE_KEY inline on the command line, which can expose the secret through shell history, process listings, logs, CI output, or telemetry. Because this skill performs blockchain deployments and fund-bearing transactions, compromise of that key can directly lead to wallet takeover and irreversible asset loss.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script sends deployment metadata to an external API (REGISTER_API) after on-chain actions complete, but this behavior is not reflected in the skill description. Even though no private key is transmitted, it leaks wallet address, NFT address, container ID, and collection metadata to a third party and creates an unexpected outbound trust boundary for users running a deployment tool.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script automatically performs several state-changing transactions—minting a Genesis Key, deploying contracts, minting a container, and enabling public minting—without any user confirmation or dry-run checkpoint. In this context, a mistaken invocation can irreversibly spend funds, publish a collection, or change sale state before the operator has reviewed the consequences.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The CLI explicitly supports --private-key <key>, which encourages users to place a secret in shell history, process listings, logs, and automation output. In a blockchain deployment context this is especially dangerous because compromise of the key enables immediate theft of assets and full control over the wallet.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
deploy-nft.js:22