Back to skill

Security audit

Warren NFT Deploy(mainnet)

Security checks for vulnerabilities and agentic risk

Overview

The skill largely does what it says, but it uses irreversible wallet signing authority and has privacy and key-handling issues users should review before installing.

Install only if you are comfortable using a dedicated low-balance deployment wallet on MegaETH mainnet. Avoid passing private keys with --private-key, assume off-chain registration to the Warren API may occur even if REGISTER_API is set empty, and review the unpinned npm install before running setup.

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)

T08 · Insecure Dependencies

Warning
Location
setup.sh:6
Finding

Unpinned Dependency Installation Creates Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: setup.sh:6 and package.json:13-15
Vulnerability Type: Unpinned third-party dependency installation
Risk Level: Medium

Affected Code:

setup.sh:6

bash
npm install ethers

package.json:13-15

json
"dependencies": {
  "ethers": "^6.16.0"
}

Technical Analysis

The setup script installs ethers without requesting an exact version, while package.json permits any compatible minor or patch release through the caret constraint ^6.16.0. The project does not include a lockfile in the audited artifact.

Consequently, dependency resolution can change between installations without corresponding changes to the reviewed project. npm packages and their transitive dependencies can execute lifecycle scripts during installation. If a future compatible release or transitive dependency is compromised, running the documented setup command could execute attacker-controlled code with the privileges of the user performing the installation.

This finding does not establish that the current ethers package is malicious. It identifies an unsafe and non-reproducible dependency installation process.

Attack Path

  1. An attacker compromises a future version of ethers permitted by ^6.16.0, or compromises one of its newly resolved transitive dependencies.
  2. A user runs the documented bash setup.sh command.
  3. npm install ethers resolves and downloads the compromised package version because no reviewed lockfile fixes the dependency graph.
  4. Malicious package code or an npm lifecycle script executes during installation or when deploy-nft.js imports the package.
  5. The payload runs with the installing user's local privileges.

Impact Assessment

Successful exploitation could permit arbitrary code execution under the account running setup. Depending on that account's permissions, an attacker could read accessible files and environment variab ...[truncated 222 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin ethers to an exact reviewed version rather than a caret range:
    json
    "dependencies": {
      "ethers": "6.16.0"
    }
    
  2. Generate, review, and commit package-lock.json.
  3. Replace npm install ethers in setup with deterministic installation:
    bash
    npm ci
    
  4. Use npm ci --ignore-scripts if the selected dependency graph does not require lifecycle scripts.
  5. Run dependency vulnerability and provenance checks in CI, and review lockfile changes before accepting dependency updates.
  6. Avoid running setup as root or another privileged account.

T09 · Insecure Skill Coding Practices

Note
Location
deploy-nft.js:29
Finding

Documented Registration Opt-Out Is Ineffective

Content
View full analysis

Vulnerability Details

File Location: deploy-nft.js:29 and deploy-nft.js:383-403
Vulnerability Type: Broken privacy control and unintended metadata transmission
Risk Level: Low

Affected Code:

deploy-nft.js:29

javascript
const REGISTER_API = process.env.REGISTER_API || 'https://thewarren.app/api/container-nfts';

deploy-nft.js:383-403

javascript
async function registerToDB(nftAddress, containerId, ownerAddress, config) {
  console.log('\n📝 Phase 4: Registering to DB...');
  try {
    const res = await fetch(REGISTER_API, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        containerId,
        nftAddress,
        ownerAddress,
        name: config.name,
        symbol: config.symbol,
        maxSupply: config.maxSupply,
        mintState: 2,
        publicPrice: config.publicPrice || '0',
        wlPrice: config.whitelistPrice || '0',
        maxPerWallet: config.maxPerWallet,
        description: config.description,
      }),
    });

The documentation states that registration can be disabled by setting REGISTER_API to an empty value. However, the logical OR operator treats an empty string as false and substitutes the default Warren endpoint. There is also no conditional check before fetch().

Technical Analysis

In JavaScript, '' || defaultValue evaluates to defaultValue. Therefore, a user invoking the tool with REGISTER_API="" does not disable registration. After deployment, the script still sends the wallet address and collection metadata to the default remote API.

The transmitted payload does not include the private key or image contents. It does include ownerAddress, NFT and container identifiers, collection name and description, supply limits, wallet mint limits, and pricing information. Much of this information may already be inferable from the public blockchain, bu ...[truncated 932 chars]

Remediation
View remediation

Remediation Suggestions

  1. Distinguish an undefined environment variable from an explicitly empty value:
    javascript
    const REGISTER_API =
      process.env.REGISTER_API !== undefined
        ? process.env.REGISTER_API
        : 'https://thewarren.app/api/container-nfts';
    
  2. Skip registration when the value is empty:
    javascript
    if (!REGISTER_API) {
      console.log('\n📝 Phase 4: DB registration disabled.');
      return;
    }
    
  3. Prefer explicit opt-in configuration, such as --register, for off-chain metadata submission.
  4. Validate configured endpoints and require HTTPS unless an explicit development mode is active.
  5. Add a test confirming that REGISTER_API="" results in no network request.

T09 · Insecure Skill Coding Practices

Error
Location
deploy-nft.js:519
Finding

Wallet Private Key Can Be Exposed Through Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: deploy-nft.js:509 and deploy-nft.js:519-520
Vulnerability Type: Sensitive credential exposure through process arguments and shell history
Risk Level: High

Affected Code:

deploy-nft.js:509

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

deploy-nft.js:519-520

javascript
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); }

Technical Analysis

The application accepts a wallet private key directly in the process command line through --private-key. Command-line arguments are commonly recorded in interactive shell history and may be visible to process-monitoring utilities, telemetry agents, crash reporters, audit systems, or other local users, depending on operating-system configuration.

A blockchain private key is a bearer credential: possession generally provides full signing authority for the associated wallet. Unlike an ordinary password, unauthorized transactions cannot normally be reversed and rotating the key requires transferring assets and authority to another wallet.

This interface also conflicts with the documentation's broad assurance that the private key is never stored, because a command containing the key may be persisted automatically by the user's shell.

Attack Path

  1. A user follows the CLI help and starts deployment with:
    bash
    node deploy-nft.js --private-key 0xSECRET... --generate-svg 10 --name Example --symbol EX
    
  2. The complete command is retained in shell history or exposed in the process argument list while the deployment is running.
  3. Another local user, endpoint-monitoring product, support bundle, history backup, or malicious process reads the argument.
  4. The observer extracts the private key and imports it into another wallet or si ...[truncated 672 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove support for --private-key and remove it from the CLI help.
  2. Prefer a secret manager, protected file descriptor, or interactive hidden prompt. If an environment variable remains supported, document that it can still be visible to privileged local processes and child processes.
  3. For interactive operation, use a non-echoing prompt and avoid logging the supplied value.
  4. Clear secret references as soon as practical after wallet initialization, recognizing that JavaScript does not guarantee immediate memory erasure.
  5. Encourage use of a dedicated deployment wallet holding only the minimum required balance and permissions.
  6. Add automated tests ensuring that errors, debug logs, and generated output never contain private-key material.
  7. Update the security documentation to state the precise handling guarantees rather than claiming the key can never be stored.
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The supplied code is only a JavaScript module exporting compiled bytecode for a Page.sol contract used to store arbitrary data as immutable bytecode, consistent with an SSTORE2 storage primitive. While this may support storing image/data blobs on-chain, it does not implement the declared end-to-end purpose of deploying NFT collections on MegaETH mainnet or publishing them through WarrenContainer and WarrenLaunchedNFT. There are no NFT minting, collection creation, publisher integrations, or deployment workflow elements visible in this chunk. Therefore the description materially overstates and misrepresents what this code actually does.

Content

No source excerpt is available for this finding.

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 · page_bytecode.js (reported line 14)May include surrounding context.

js
* To reproduce: cd foundry-app && forge build
 * Then: cat out/Page.sol/Page.json | jq -r .bytecode.object
 */
module.exports = '0x60a0604052346100e45761025c80380380610019816100fc565b9283398101906020818303126100e4578051906001600160401b0382116100e4570181601f820112156100e4578051906001600160401b0382116100e85761006a601f8301601f19166020016100fc565b92828452602083830101116100e457815f9260208093018386015e8301015280518060401b6bfe61000180600a3d393df3000161fffe8211830152600b8101601583015ff09182156100d7575260805260405161013a908161012282396080518181816044015260d50152f35b63301164255f526004601cfd5b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b6040519190601f01601f191682016001600160401b038111838210176100e85760405256fe6080806040526004361015610012575f80fd5b5f3560e01c9081634822da1c146100c357506357de26a414610032575f80fd5b346100bf575f3660031901126100bf577f00000000000000000000000000000000000000000000000000000000000000006020608060405180935f19813b0164ffffffffff16905f6021830191601f8501903c808252016040810193846040528385528051938491826060850152018383015e5f828483010152603f1992601f8019910116810103010190f35b5f80fd5b346100bf575f3660031901126100bf577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f3fea2646970667358221220fe4f8a378a0b003d3e1438e45234630293b1a4f7cf94a9f28a4c2d2531789b9d64736f6c634300081a0033';

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill declares environment and network capabilities via metadata and documented behavior, but it does not explicitly scope or constrain tool permissions with an allowlist. Because the skill requires a PRIVATE_KEY and performs networked blockchain transactions plus optional HTTP POST registration, the absence of explicit tool scope increases the risk of unintended or overly broad access if executed by an agent framework.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script automatically calls mint() on a separate NFT contract if the wallet lacks a Genesis Key, causing an on-chain action unrelated to the core deployment flow. Even if advertised as free, it spends gas, modifies the operator wallet state, and creates an additional trust dependency on an external contract without explicit confirmation.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script performs an undisclosed outbound POST to a third-party Warren API after deployment, sending collection metadata and owner address. While this is presented as 'non-critical' registration, it expands the skill's behavior beyond on-chain deployment and leaks operator/deployment data to an external service the user may not expect or consent to.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The dependency version for ethers is specified with a caret range (^6.16.0), which allows newer compatible releases to be installed automatically. This creates supply-chain risk because a compromised or breaking upstream release could be pulled into deployments without review, which is especially relevant in a blockchain deployment skill that may handle contract interactions and asset creation.

Content

Scanner excerpt · package.json (reported line 14)May include surrounding context.

json
"license": "ISC",
  "type": "commonjs",
  "dependencies": {
    "ethers": "^6.16.0"
  }
}

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