Back to skill

Security audit

here.now

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but it gives agents broad publishing, Drive storage, sharing-token, and persistent credential authority that deserves review before installation.

Review this skill before installing if you use shared machines or sensitive files. Only use it when you are comfortable letting the agent upload chosen local files to here.now/R2, publish public or access-controlled sites, manage private Drive contents, create sharing tokens, and store a here.now API key under ~/.herenow/credentials. Ask the agent to confirm exact paths, destination, visibility, token permissions, path prefix, TTL, and credential storage before it acts.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (24)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill description frames the capability primarily as website/file publishing, but the body also includes private Drive storage operations, reading/writing stored files, and token-based sharing flows. Undeclared data-storage and sharing behaviors are security-relevant because they expand what user data may be transmitted, persisted, or exposed beyond the advertised purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The skill description frames the capability primarily as website/file publishing, but the body also includes private Drive storage operations, reading/writing stored files, and token-based sharing flows. Undeclared data-storage and sharing behaviors are security-relevant because they expand what user data may be transmitted, persisted, or exposed beyond the advertised purpose.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

The skill exposes folder rename/delete endpoints and automatic folder creation from free-form names, which are account-mutating operations. In a broad-trigger skill, such write/delete capabilities can be abused or invoked unintentionally, causing organizational damage or data-management changes the user did not request.

Content

Scanner excerpt · SKILL.md (reported line 170)May include surrounding context.

md
`--folder` takes a folder name or id. A name is matched case-insensitively and **created if it does not exist yet**, so this works the first time; the script reports the result as `publish_result.folder`. It requires an API key (anonymous Sites have no account to file in) and works with `--slug` (moves an existing Site) and `--workspace` (the workspace's folders).

Without the script, the same field is `folder` on `POST /api/v1/publish`, `PUT /api/v1/publish/{slug}`, and `PATCH /api/v1/publish/{slug}/metadata` (the way to file a Site without publishing a new version; `"folder": null` moves it back to the root). `GET /api/v1/folders` lists the account's folders; `GET /api/v1/publishes?folder={name-or-id}` lists one folder's Sites. Rename and delete are `PATCH`/`DELETE /api/v1/folders/{id}` (deleting a folder unfiles its Sites and deletes nothing else). Up to 50 folders per account, names up to 60 characters.

**Never invent folders or file Sites the user did not ask to file.** The folder structure is theirs; every folder appears as a tile in their dashboard. See https://here.now/docs#folders.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill clearly instructs use of network access (curl, API calls) and shell execution (./scripts/publish.sh, file writes), but it declares no explicit tool scope or permissions boundary. That increases the chance an agent platform grants broader capabilities than the user expects, making unintended external transmission or local state changes easier.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are broad (publish this, share this, generate a URL, build a chatbot) and overlap with ordinary requests that may not imply consent to upload data to an external service. That can cause unintended invocation and accidental exfiltration of user content to a public or semi-public hosting platform.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 8)May include surrounding context.

md
Publish HTML, documents, images, PDFs, videos, and static files to live
  URLs at {slug}.here.now or custom domains. Use when asked to "publish
  this", "host this", "deploy this", "share this on the web", "make a
  website", "put this online", "create a webpage", "generate a URL",
  "build a chatbot", "password protect this site", "make this site
  private", or "share this site with only certain people". here.now also
  includes workspaces — shared team accounts where Sites belong to the

Rp1

Medium
Category
MCP Rug Pull
Confidence
81% confidence
Finding

The install command uses npx skills add heredotnow/skill --skill here-now -g without pinning a version or digest. This creates a supply-chain risk: future upstream changes or a compromised package/version could alter the installed skill behavior unexpectedly.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
81% confidence
Finding

This second unpinned npx skills reference carries the same supply-chain exposure as the first: installs may resolve to whatever package version is current at execution time. That undermines reproducibility and trust in reviewed behavior.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

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.

Content

Scanner excerpt · SKILL.md (reported line 124)May include surrounding context.

md
Authenticated updates require a saved API key.

**Stale-base protection.** The live Site may have changed since your local files were published — the owner can edit it from other tools (another agent, the here.now Editor, a teammate). The script records the live `versionId` in `.herenow/state.json` after each publish and sends it as `baseVersionId` on the next update of the same slug from the same directory; if the live Site moved past it, the update is rejected with `code: "version_conflict"` naming the live version and what created it. When that happens, relay the message to the user and offer to (a) read the live files with `GET /api/v1/publish/{slug}/files` (lists them with a `url` each) and `GET /api/v1/publish/{slug}/files/{path}` (the bytes; owner API key, works for password-protected and restricted Sites without the visitor password), reconcile them into the local files, and republish, or (b) re-run with `--overwrite` to replace the live version anyway. Before editing local files for an authenticated Site you haven't touched recently, check for drift first: `GET /api/v1/publish/{slug}` returns `currentVersionId` plus `currentVersionSource` and `currentVersionCreatedAt` (what changed it and when, e.g. `editor`) — if the id differs from your state file's `versionId`, read the live files before editing. The published version is the shared truth; never fetch the public URL to read an owned Site (it is gated for protected Sites) and never ask the user for a visitor password to read their own Site. Anonymous Sites can't call these endpoints; they rely on the saved state and server enforcement. Omitting `baseVersionId` (or using `--overwrite`) is an unchecked full replacement — today's default for raw API callers.

Every publish records an immutable version. If the user asks to see earlier versions of a Site, undo a publish, or roll back: list history with `GET /api/v1/publish/{slug}/versions` and restore instantly with `POST /api/v1/publish/{slug}/versions/{versio
...[truncated 25 chars]

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 219)May include surrounding context.

To store a key, write it to the credentials file:

bash
mkdir -p ~/.herenow && echo "{API_KEY}" > ~/.herenow/credentials && chmod 600 ~/.herenow/credentials

IMPORTANT: After receiving an API key, save it immediately — run the command above yourself. Do not ask the user to run it manually. Avoid passing the key via CLI flags (e.g. --api-key) in interactive sessions; the credentials file is the preferred storage method.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · SKILL.md (reported line 251)May include surrounding context.

To store a key, write it to the credentials file:

bash
mkdir -p ~/.herenow && echo "{API_KEY}" > ~/.herenow/credentials && chmod 600 ~/.herenow/credentials

IMPORTANT: After receiving an API key, save it immediately — run the command above yourself. Do not ask the user to run it manually. Avoid passing the key via CLI flags (e.g. --api-key) in interactive sessions; the credentials file is the preferred storage method.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
84% confidence
Finding

The instruction to save returned API keys to ~/.herenow/credentials automatically encourages the agent to persist long-lived credentials on the local machine without an explicit consent checkpoint. Credential persistence expands the blast radius of compromise and may surprise users who expected ephemeral use.

Content

Scanner excerpt · SKILL.md (reported line 222)May include surrounding context.

mkdir -p ~/.herenow && echo "{API_KEY}" > ~/.herenow/credentials && chmod 600 ~/.herenow/credentials

text

**IMPORTANT**: After receiving an API key, save it immediately — run the command above yourself. Do not ask the user to run it manually. Avoid passing the key via CLI flags (e.g. `--api-key`) in interactive sessions; the credentials file is the preferred storage method.

Never commit credentials or local state files (`~/.herenow/credentials`, `.herenow/state.json`) to source control.

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

The skill instructs sending the user's email address to an external authentication endpoint to request a sign-in code. While this is functionally expected, it is still external transmission of personal data and should be treated as sensitive because it creates an off-platform authentication flow and links the user identity to the service.

Content

Scanner excerpt · SKILL.md (reported line 234)May include surrounding context.

  1. Request a one-time sign-in code:
bash
curl -sS https://here.now/api/auth/agent/request-code \
  -H "content-type: application/json" \
  -d '{"email": "user@example.com"}'

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
84% confidence
Finding

This repeats the same autonomous credential-persistence pattern after the verify-code flow: the agent is directed to store the API key itself rather than confirm with the user. Persisting secrets automatically can violate least surprise and create lingering access tokens on shared or managed systems.

Content

Scanner excerpt · SKILL.md (reported line 248)May include surrounding context.

-d '{"email":"user@example.com","code":"ABCD-2345"}'

text

5. Save the returned `apiKey` yourself (do not ask the user to do this):

```bash
mkdir -p ~/.herenow && echo "{API_KEY}" > ~/.herenow/credentials && chmod 600 ~/.herenow/credentials

Behavior Manipulation

Medium
Category
Prompt Injection
Confidence
75% confidence
Finding

Subtle instructions detected that may alter agent decision-making or introduce hidden biases.

Content

Scanner excerpt · SKILL.md (reported line 288)May include surrounding context.

md
- When `publish_result.folder` is non-empty, mention that the Site is filed in that folder in their dashboard.
- When `publish_result.auth_mode=authenticated`: tell the user the site is **permanent** and saved to their account. No claim URL is needed.
- When `publish_result.auth_mode=anonymous`: tell the user the site **expires in 24 hours**. Share the claim URL (if `publish_result.claim_url` is non-empty and starts with `https://`) so they can keep it permanently. Copy it byte-for-byte as a clickable link — never shorten, redact, summarize, or replace any part of it with `...`; a modified claim link will not work. Warn that claim tokens are only returned once and cannot be recovered.
- Never tell the user to inspect `.herenow/state.json` for claim URLs or auth status.

For Drives:

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest describes here.now as a website/file publishing and hosting skill, with workspace publishing and domain purchase. This script exposes a broader 'Drive' storage-management surface including creating/deleting drives, importing/exporting arbitrary folder trees, raw file reads/writes, and issuing/revoking drive access tokens, which is a materially broader behavior than the manifest claims.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/drive.sh (reported line 128)May include surrounding context.

sh
tmp=$(mktemp)
  local code
  if [[ -n "$body" ]]; then
    code=$(curl -sS -o "$tmp" -w "%{http_code}" -X "$method" "$url" "${auth_header[@]}" -H "content-type: application/json" -d "$body")
  else
    code=$(curl -sS -o "$tmp" -w "%{http_code}" -X "$method" "$url" "${auth_header[@]}")
  fi

External Transmission

Medium
Category
Data Exfiltration
Confidence
89% confidence
Finding

The code uploads arbitrary local file contents directly to an externally supplied upload URL on cloud storage. Although this is part of normal publish/import behavior, in an agent context it is dangerous because local files selected by the agent can be exfiltrated off-host to a third-party storage endpoint, and the endpoint host differs from the primary service domain.

Content

Scanner excerpt · scripts/drive.sh (reported line 223)May include surrounding context.

sh
upload_id=$(echo "$upload" | "$JQ_BIN" -r '.uploadId')
  # `|| http_code=000`: a connection-level failure would otherwise exit the
  # script under set -e with only curl's message, before the hint below.
  http_code=$(curl -sS -o /dev/null -w "%{http_code}" -X PUT "$upload_url" -H "Content-Type: $ct" --data-binary "@$local_file") || http_code="000"
  [[ "$http_code" -ge 200 && "$http_code" -lt 300 ]] || die "upload failed for $path (HTTP $http_code). The upload URL PUTs directly to *.r2.cloudflarestorage.com, not to here.now; if this environment restricts outbound network access, allow that host as well as here.now."
  api_json POST "$BASE_URL/api/v1/drives/$id/files/finalize" "$("$JQ_BIN" -n --arg u "$upload_id" '{uploadId:$u}')" | "$JQ_BIN" .
}

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script can mint share tokens with write access and optionally token-management privileges, enabling delegation of persistent modification rights to a drive subtree. In an agent setting, this is sensitive because a prompt asking to 'share files' could be translated into creation of broadly scoped write-capable credentials, leading to unauthorized data tampering, deletion, or further token proliferation.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/publish.sh (reported line 182)May include surrounding context.

sh
fi

  echo "publishing from Drive..." >&2
  RESPONSE=$(curl -sS -X POST "$BASE_URL/api/v1/publish/from-drive" \
    -H "authorization: Bearer $API_KEY" \
    -H "x-herenow-client: $CLIENT_HEADER_VALUE" \
    -H "content-type: application/json" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/publish.sh (reported line 383)May include surrounding context.

sh
# Step 1: Create/update publish
echo "creating publish ($file_count files)..." >&2
RESPONSE=$(curl -sS -X "$METHOD" "$URL" \
  "${AUTH_ARGS[@]+"${AUTH_ARGS[@]}"}" \
  "${CLIENT_ARGS[@]+"${CLIENT_ARGS[@]}"}" \
  "${ACCOUNT_ARGS[@]+"${ACCOUNT_ARGS[@]}"}" \

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/publish.sh (reported line 442)May include surrounding context.

sh
[[ -n "$upload_ct" ]] && ct_args=(-H "Content-Type: $upload_ct")

  # `|| http_code=000`: a connection-level failure (proxy refusing CONNECT,
  # DNS, TLS) exits curl non-zero, which under set -e would kill the script
  # here with only curl's own message. Fall through so the count and the
  # hint below are reached.
  http_code=$(curl -sS -o /dev/null -w "%{http_code}" -X PUT "$upload_url" \

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script performs direct network uploads of local file contents using curl PUT requests, which transmits user-selected local data to remote upload URLs. While the script logs progress like 'uploading ... files', it does not clearly disclose that local file contents are being sent off-host or warn about the privacy/integrity impact within the code comments, prompts, or visible user-facing warning text.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

The script blindly POSTs to FINALIZE_URL returned by the previous server response, reusing bearer auth and workspace headers without validating that the URL remains on the expected here.now origin. If a malicious or compromised API endpoint returned an attacker-controlled finalize URL, this could leak the API key and associated account-scoping headers to an arbitrary host.

Content

Scanner excerpt · scripts/publish.sh (reported line 468)May include surrounding context.

sh
# Step 3: Finalize
echo "finalizing..." >&2
FIN_RESPONSE=$(curl -sS -X POST "$FINALIZE_URL" \
  "${AUTH_ARGS[@]+"${AUTH_ARGS[@]}"}" \
  "${CLIENT_ARGS[@]+"${CLIENT_ARGS[@]}"}" \
  "${ACCOUNT_ARGS[@]+"${ACCOUNT_ARGS[@]}"}" \

Static analysis

No suspicious patterns detected.