Back to skill

Security audit

Near Name Service

Security checks for vulnerabilities and agentic risk

Overview

This skill has a coherent NEAR name-registration purpose, but its registration command can execute unsafe shell input and may trigger blockchain actions without enough safeguards.

Review carefully before installing or running. Do not run the register command with untrusted names or account IDs, and do not rely on NEAR_ACCOUNT from an untrusted environment. A safer version should validate NEAR account/name inputs, avoid shell exec, require explicit confirmation for registration, and clearly distinguish testnet behavior from any real funded account use.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/nameservice.js:98
Finding

Shell Command Injection Through Registration Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/nameservice.js:98-105
Vulnerability Type: OS command injection through unsafe shell interpolation
Risk Level: High

Vulnerable Code

javascript
async function registerName(name, accountId) {
  const fullName = `${name}.near`;
  const cmd = isTestnet
    ? `near call ${NAMING_CONTRACT} register '{"account_id":"${fullName}"}' --accountId ${accountId} --networkId testnet`
    : `near call ${NAMING_CONTRACT} register '{"account_id":"${fullName}"}' --accountId ${accountId}`;

  try {
    await execAsync(cmd);

Technical Analysis

The name and accountId values originate from process.argv[3], process.argv[4], or the NEAR_ACCOUNT environment variable. They are inserted directly into a command string without validation or shell escaping.

The command is passed to child_process.exec(), via its promisified execAsync wrapper. Unlike argument-based process execution, exec() launches the command through a system shell. Shell metacharacters contained in either user-controlled value can therefore terminate or alter the intended near command and introduce additional commands.

accountId is especially directly exploitable because it is interpolated as an unquoted shell argument. The name value can also become exploitable by breaking out of the single-quoted JSON argument. This is a coding vulnerability rather than evidence that the package intentionally executes a malicious payload.

Attack Path

  1. An attacker supplies or convinces a user or Agent to use a crafted account ID, either as the fourth CLI argument or through NEAR_ACCOUNT.
  2. For example, a harmless proof-of-concept account argument could contain victim.near; touch /tmp/near-name-pwned; #.
  3. The registerName() function concatenates this value into the shell command.
  4. execAsync() invokes the shell, which treats the semicolon as a command separator and the hash cha ...[truncated 1106 chars]
Remediation
View remediation

Remediation Suggestions

  1. Replace exec() with execFile() or spawn() and pass every command component as a separate argument. Do not enable shell execution.
javascript
const { execFile } = require('child_process');
const { promisify } = require('util');
const execFileAsync = promisify(execFile);

async function registerName(name, accountId) {
  validateName(name);
  validateAccountId(accountId);

  const fullName = `${name}.near`;
  const args = [
    'call',
    NAMING_CONTRACT,
    'register',
    JSON.stringify({ account_id: fullName }),
    '--accountId',
    accountId,
  ];

  if (isTestnet) {
    args.push('--networkId', 'testnet');
  }

  await execFileAsync('near', args, {
    shell: false,
    timeout: 120000,
  });
}
  1. Validate name against the exact NEAR naming rules. Reject whitespace, quotes, shell metacharacters, path characters, control characters, and values already containing an unexpected suffix.

  2. Validate accountId against the documented NEAR account-ID grammar and impose a reasonable maximum length. Validation should use an allowlist rather than attempting to blacklist individual shell characters.

  3. Treat environment variables as untrusted input and apply the same validation to NEAR_ACCOUNT as to command-line arguments.

  4. Add regression tests containing semicolons, quotes, command substitutions, newlines, and option-like values to confirm they are rejected or passed only as literal process arguments.

  5. Consider adding -- where supported by the NEAR CLI to prevent values beginning with a hyphen from being interpreted as additional options.

Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

The description is partially accurate: the code does check availability, resolve, and register .near names/accounts. However, it overstates capability by claiming to 'manage names' without implementing actual management actions beyond registration. The script exposes only three CLI commands: check, resolve, and register. Its resolve/check logic is also based on account existence queries, which is narrower than a full name-service manager. This is a moderate description-behavior mismatch rather than a complete mismatch.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README provides direct registration commands for a paid, irreversible on-chain action without a clear warning immediately adjacent to the command that it will create a blockchain transaction and spend funds. Although the pricing section mentions approximate cost elsewhere, users may copy-paste the registration command without realizing it authorizes a real expenditure, which increases the risk of unintended financial loss.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill documents use of an environment variable (NEAR_ACCOUNT) but does not declare any permissions or allowed-tools scope, creating an undeclared capability boundary. In an agent setting, missing tool scope can let a caller or runtime expose environment access implicitly, reducing transparency and making it easier for sensitive context or account configuration to be used without explicit approval.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The registration command is presented like a routine CLI action without a prominent warning that it can trigger a real on-chain purchase with immediate cost and limited reversibility. In an agent-driven workflow, a user may authorize or auto-run register thinking it is a dry check, causing unintended spending or registration of the wrong name/account.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The manifest describes a skill for checking availability, registering, resolving, and managing .near names, but this implementation performs registration by spawning a local shell command through child_process.exec. Shell execution is a powerful host capability not inherently required by the stated purpose, since the rest of the skill already interacts with NEAR over RPC and registration could be implemented without arbitrary command execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The register path performs a real state-changing blockchain action immediately after minimal argument checks, with no confirmation prompt, dry-run mode, or explicit warning about wallet/account consequences. In an agent or automation context, this increases the risk of unintended registrations or transactions being triggered by user misunderstanding or prompt-driven misuse.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The file hard-codes isTestnet = true, which enforces a specific network locale/context without user opt-in or a documented selection mechanism. Under the policy, forced locale or context choices should either be user-selectable or clearly justified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.