registry  /  @rubytech/create-sitedesk-code  /  0.1.392

@rubytech/create-sitedesk-code@0.1.392

Install SiteDesk — automated back office for independent building contractors

AI Security Review

scanned 10d ago · by lpm-firewall-ai

LPM treats this as warn-only first-party agent extension lifecycle risk. User-invoked installer provisions a full SiteDesk/Claude-based local platform and mutates system/package-owned agent extension surfaces. This is high-risk agent lifecycle behavior but not an unconsented npm lifecycle hijack.

Static reason
High-risk behavior combination matched malicious policy.; source matched previously finalized malicious package; routed for review
Trigger
Running the create-sitedesk-code bin, e.g. via npx or global install command invocation.
Impact
Can create persistent local services and a brand-scoped Claude agent environment with broad tool permissions; operator consent is implied by invoking the installer.
Mechanism
first-party installer registers Claude plugins, seeds bypassPermissions, installs dependencies, and provisions services
Policy narrative
The package is a large installer for a SiteDesk local platform. When the CLI is run, it installs system dependencies, Claude Code and plugins, writes a brand-scoped Claude configuration with bypassPermissions, provisions services/cron/launchd/systemd units, and deploys bundled payload files. These are powerful agent-extension lifecycle actions, but they are package-aligned, brand-scoped, and not triggered by npm install lifecycle hooks.
Rationale
Static inspection confirms dangerous installer and agent-control capabilities, but activation is explicit via the bin and the Claude control surface is scoped to the package-owned ~/.sitedesk-code namespace. This fits warn-only agent extension lifecycle risk rather than malicious lifecycle hijack or covert malware.
Evidence
package.jsondist/index.jsdist/permissions-seed.jsdist/specialist-registration.jspayload/platform/config/brand.json~/.sitedesk-code/.claude/settings.json~/.sitedesk-code/.claude/plugins/installed_plugins.json~/.config/systemd/user/sitedesk-code.service~/Library/LaunchAgents/com.rubytech.sitedesk-code.plist
Network endpoints9
registry.npmjs.org/dl.google.com/linux/linux_signing_key.pubdl.google.com/linux/chrome/deb/deb.nodesource.com/setup_22.xdebian.neo4j.comollama.ai/install.shastral.sh/uv/install.shgithub.com/cloudflare/cloudflared/releases/download/2026.6.0/cloudflared-linux-${arch}.debgithub.com/ggerganov/whisper.cpp.git

Decision evidence

public snapshot
AI called this Suspicious at 90.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • dist/index.js bin performs large user-invoked installer with sudo/systemd/launchd/cron mutations.
  • dist/permissions-seed.js writes brand-scoped Claude settings defaultMode=bypassPermissions and autoMode trust rules.
  • dist/index.js registers Claude plugin marketplaces/plugins under CLAUDE_CONFIG_DIR=~/.sitedesk-code/.claude.
  • dist/index.js installs @anthropic-ai/claude-code@latest and pre-caches @playwright/mcp@latest.
  • dist/index.js writes persistent services, cron heartbeat, launchd/systemd units, and audit/samba/neo4j/ollama config.
Evidence against
  • package.json has no install/preinstall/postinstall hook; prepublishOnly is publisher-side only.
  • Dangerous actions are reached by explicit bin invocation create-sitedesk-code, not package import/install.
  • Claude/plugin writes are scoped to the package-owned ~/.sitedesk-code/.claude namespace, not ~/.claude by default.
  • No credential harvesting or covert exfiltration found; generated secrets are stored locally under brand config paths.
  • Network use aligns with installer dependencies and service setup rather than hidden payload retrieval.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsEvalFilesystemNativeBindingsNetworkShell
Supply chain
HighEntropyStringsMinifiedObfuscatedProtestwareTelemetryUrlStrings
Manifest
NoLicense
scanned 642 file(s), 11.3 MB of source, external domains: 0.0.0.0, 127.0.0.1, api.anthropic.com, api.replicate.com, api.telegram.org, appcenter.intuit.com, astral.sh, brew.sh, chevrotain.io, claude.ai, deb.nodesource.com, debian.neo4j.com, dl.google.com, docs.getmaxy.com, docs.realagent.network, en.wikipedia.org, fonts.googleapis.com, fonts.gstatic.com, getmaxy.com, github.com, graph.microsoft.com, langium.org, llmstxt.org, login.microsoftonline.com, maxy.bot, maxy.setup, ns.adobe.com, oauth.platform.intuit.com, ollama.ai, one.dash.cloudflare.com, platform.claude.com, player.vimeo.com, quickbooks.api.intuit.com, react.dev, registry.npmjs.org, sandbox-quickbooks.api.intuit.com, schema.org, www.anthropic.com, www.linkedin.com, www.w3.org, www.xfa.org, www.youtube-nocookie.com

Source & flagged code

24 flagged · loading source
payload/platform/scripts/smoke-boot-services.shView file
334patternName = generic_password severity = medium line = 334 matchedText = local ne...:-}"
Medium
Secret Pattern

Package contains a possible secret pattern.

payload/platform/scripts/smoke-boot-services.shView on unpkg · L334
dist/index.jsView file
137for (const host of ["registry.npmjs.org", "github.com"]) { L138: const dns = spawnSync("host", ["-W", "5", host], { encoding: "utf-8", stdio: "pipe", timeout: 10_000 }); L139: logFile(`DNS ${host}: ${dns.status === 0 ? "OK" : "FAIL"} — ${(dns.stdout || dns.stderr || "").trim().split("\n")[0]}`); ... L144: "--connect-timeout", "10", L145: "https://registry.npmjs.org/", L146: ], { encoding: "utf-8", stdio: "pipe", timeout: 15_000 }); ... L151: function captureNpmDebugLog() { L152: const logsDir = resolve(process.env.HOME ?? "/root", ".npm/_logs"); L153: if (!existsSync(logsDir))
Critical
Same File Env Network Execution

A single source file combines environment access, network access, and code or shell execution with blocking evidence.

dist/index.jsView on unpkg · L137
1#!/usr/bin/env node L2: import { execFileSync, spawn, spawnSync } from "node:child_process"; L3: import { existsSync, mkdirSync, writeFileSync, cpSync, readFileSync, rmSync, readdirSync, appendFileSync, openSync, closeSync, chmodSync, statSync, realpathSync, accessSync, consta... ... L9: import { buildHeartbeatCronBlock, mergeHeartbeatBlock } from "./cron-registration.js"; L10: import { validateTierFlag, validateEntitlementBase64, applyTierToAccountConfig, entitlementPath } from "./tier-flag.js"; L11: import { parseOsRelease, isUbuntuLike as isUbuntuLikePure, parseAptCacheCandidate, decideAptResolution, } from "./apt-resolve.js"; ... L47: } L48: const INSTALL_DIR = resolve(process.env.HOME ?? "/root", BRAND.installDir); L49: const PERSIST_DIR = resolve(process.env.HOME ?? "/root", BRAND.configDir); ... L103: ` ${BRAND.productName} Install Log — ${new Date().toISOString()}`, L104: ` Node ${process.version} | ${process.platform} ${process.arch}`, L105: "=".repeat(64),
Critical
Download Execute

Source downloads or fetches remote code and executes it.

dist/index.jsView on unpkg · L1
1Trigger-reachable chain: manifest.bin -> dist/index.js L1: #!/usr/bin/env node L2: import { execFileSync, spawn, spawnSync } from "node:child_process"; L3: import { existsSync, mkdirSync, writeFileSync, cpSync, readFileSync, rmSync, readdirSync, appendFileSync, openSync, closeSync, chmodSync, statSync, realpathSync, accessSync, consta... ... L9: import { buildHeartbeatCronBlock, mergeHeartbeatBlock } from "./cron-registration.js"; L10: import { validateTierFlag, validateEntitlementBase64, applyTierToAccountConfig, entitlementPath } from "./tier-flag.js"; L11: import { parseOsRelease, isUbuntuLike as isUbuntuLikePure, parseAptCacheCandidate, decideAptResolution, } from "./apt-resolve.js"; ... L47: } L48: const INSTALL_DIR = resolve(process.env.HOME ?? "/root", BRAND.installDir); L49: const PERSIST_DIR = resolve(process.env.HOME ?? "/root", BRAND.configDir); ... L103: ` ${BRAND.productName} Install Log — ${new Date().toISOString()}`, L104: ` Node ${process.version} | ${process.platform} ${process.arch}`, L105: "=".repeat(64),
Critical
Trigger Reachable Dangerous Capability

A package entrypoint or install-time lifecycle script reaches a source file with blocking dangerous behavior.

dist/index.jsView on unpkg · L1
1#!/usr/bin/env node L2: import { execFileSync, spawn, spawnSync } from "node:child_process"; L3: import { existsSync, mkdirSync, writeFileSync, cpSync, readFileSync, rmSync, readdirSync, appendFileSync, openSync, closeSync, chmodSync, statSync, realpathSync, accessSync, consta...
High
Child Process

Package source references child process execution.

dist/index.jsView on unpkg · L1
532// Fetch + dearmor the signing key, write to /etc/apt/trusted.gpg.d/. Pipe L533: // composition runs through bash -c so the curl|gpg pipeline is one L534: // privileged command rather than two separate sudo escalations.
High
Shell

Package source references shell execution.

dist/index.jsView on unpkg · L532
1#!/usr/bin/env node L2: import { execFileSync, spawn, spawnSync } from "node:child_process"; L3: import { existsSync, mkdirSync, writeFileSync, cpSync, readFileSync, rmSync, readdirSync, appendFileSync, openSync, closeSync, chmodSync, statSync, realpathSync, accessSync, consta... ... L9: import { buildHeartbeatCronBlock, mergeHeartbeatBlock } from "./cron-registration.js"; L10: import { validateTierFlag, validateEntitlementBase64, applyTierToAccountConfig, entitlementPath } from "./tier-flag.js"; L11: import { parseOsRelease, isUbuntuLike as isUbuntuLikePure, parseAptCacheCandidate, decideAptResolution, } from "./apt-resolve.js"; ... L47: } L48: const INSTALL_DIR = resolve(process.env.HOME ?? "/root", BRAND.installDir); L49: const PERSIST_DIR = resolve(process.env.HOME ?? "/root", BRAND.configDir); ... L103: ` ${BRAND.productName} Install Log — ${new Date().toISOString()}`, L104: ` Node ${process.version} | ${process.platform} ${process.arch}`, L105: "=".repeat(64),
High
Sandbox Evasion Gated Capability

Source gates dangerous network, credential, or execution behavior behind CI, host, platform, time, or geo fingerprint checks.

dist/index.jsView on unpkg · L1
1Cross-file remote execution chain: dist/index.js spawns payload/platform/scripts/wifi-provision-server/server.js; helper contains network access plus dynamic code execution. L1: #!/usr/bin/env node L2: import { execFileSync, spawn, spawnSync } from "node:child_process"; L3: import { existsSync, mkdirSync, writeFileSync, cpSync, readFileSync, rmSync, readdirSync, appendFileSync, openSync, closeSync, chmodSync, statSync, realpathSync, accessSync, consta... ... L9: import { buildHeartbeatCronBlock, mergeHeartbeatBlock } from "./cron-registration.js"; L10: import { validateTierFlag, validateEntitlementBase64, applyTierToAccountConfig, entitlementPath } from "./tier-flag.js"; L11: import { parseOsRelease, isUbuntuLike as isUbuntuLikePure, parseAptCacheCandidate, decideAptResolution, } from "./apt-resolve.js"; ... L47: } L48: const INSTALL_DIR = resolve(process.env.HOME ?? "/root", BRAND.installDir); L49: const PERSIST_DIR = resolve(process.env.HOME ?? "/root", BRAND.configDir); ... L103: ` ${BRAND.productName} Install Log — ${new Date().toISOString()}`, L104: ` Node ${process.version} | ${process.platform} ${process.arch}`, L105: "=".repeat(64),
High
Cross File Remote Execution Context

Source spawns a local helper that also contains network and dynamic execution context; review data flow before blocking.

dist/index.jsView on unpkg · L1
280function canSudo() { L281: const result = spawnSync("sudo", ["-n", "true"], { stdio: "pipe", timeout: 5_000 }); L282: return result.status === 0; ... L284: /** True when the npm global prefix's node_modules dir is writable by the current L285: * user (nvm/Homebrew installs) — meaning `npm install -g` needs no sudo. */ L286: function npm[redacted]() {
High
Runtime Package Install

Package source invokes a package manager install command at runtime.

dist/index.jsView on unpkg · L280
1#!/usr/bin/env node L2: import { execFileSync, spawn, spawnSync } from "node:child_process"; L3: import { existsSync, mkdirSync, writeFileSync, cpSync, readFileSync, rmSync, readdirSync, appendFileSync, openSync, closeSync, chmodSync, statSync, realpathSync, accessSync, consta... ... L9: import { buildHeartbeatCronBlock, mergeHeartbeatBlock } from "./cron-registration.js"; L10: import { validateTierFlag, validateEntitlementBase64, applyTierToAccountConfig, entitlementPath } from "./tier-flag.js"; L11: import { parseOsRelease, isUbuntuLike as isUbuntuLikePure, parseAptCacheCandidate, decideAptResolution, } from "./apt-resolve.js"; ... L47: } L48: const INSTALL_DIR = resolve(process.env.HOME ?? "/root", BRAND.installDir); L49: const PERSIST_DIR = resolve(process.env.HOME ?? "/root", BRAND.configDir); ... L103: ` ${BRAND.productName} Install Log — ${new Date().toISOString()}`, L104: ` Node ${process.version} | ${process.platform} ${process.arch}`, L105: "=".repeat(64),
Medium
Install Persistence

Source writes installer persistence such as shell profile or service configuration.

dist/index.jsView on unpkg · L1
payload/platform/plugins/prompt-optimiser/skills/prompt-optimiser/__tests__/restatement-ladder.test.shView file
path = payload/platform/plugins/prompt-optimiser/skills/prompt-optimiser/__tests__/restatement-ladder.test.sh kind = payload_in_excluded_dir sizeBytes = 936 magicHex = [redacted]
High
Payload In Excluded Dir

Package hides binary, compressed, or executable-looking payloads in test/fixture/hidden paths.

payload/platform/plugins/prompt-optimiser/skills/prompt-optimiser/__tests__/restatement-ladder.test.shView on unpkg
path = payload/platform/plugins/prompt-optimiser/skills/prompt-optimiser/__tests__/restatement-ladder.test.sh kind = build_helper sizeBytes = 936 magicHex = [redacted]
Medium
Ships Build Helper

Package ships non-JavaScript build or shell helper files.

payload/platform/plugins/prompt-optimiser/skills/prompt-optimiser/__tests__/restatement-ladder.test.shView on unpkg
payload/server/public/assets/cormorant-latin-ext-500-normal-AH9qog1s.woff2View file
path = [redacted]-latin-ext-500-normal-AH9qog1s.woff2 kind = high_entropy_blob sizeBytes = 19620 magicHex = [redacted]
High
Ships High Entropy Blob

Package ships high-entropy non-source blobs.

payload/server/public/assets/cormorant-latin-ext-500-normal-AH9qog1s.woff2View on unpkg
payload/platform/lib/graph-mcp/dist/index.jsView file
matchType = normalized_sha256 matchedPackage = @rubytech/create-sitedesk-code@0.1.378 matchedPath = payload/platform/lib/graph-mcp/dist/index.js matchedIdentity = npm:[redacted]:0.1.378 similarity = 1.000 summary = normalized source hash matched finalized malicious source
High
Known Malware Source Similarity

Source file is highly similar to a previously finalized malicious package; route for source-aware review.

payload/platform/lib/graph-mcp/dist/index.jsView on unpkg
payload/platform/plugins/admin/mcp/dist/index.jsView file
matchType = normalized_sha256 matchedPackage = @rubytech/create-sitedesk-code@0.1.386 matchedPath = [redacted].js matchedIdentity = npm:[redacted]:0.1.386 similarity = 1.000 summary = normalized source hash matched finalized malicious source
High
Known Malware Source Similarity

Source file is highly similar to a previously finalized malicious package; route for source-aware review.

payload/platform/plugins/admin/mcp/dist/index.jsView on unpkg
payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.jsView file
matchType = normalized_sha256 matchedPackage = @rubytech/create-sitedesk-code@0.1.378 matchedPath = [redacted].js matchedIdentity = npm:[redacted]:0.1.378 similarity = 1.000 summary = normalized source hash matched finalized malicious source
High
Known Malware Source Similarity

Source file is highly similar to a previously finalized malicious package; route for source-aware review.

payload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.jsView on unpkg
payload/platform/lib/anthropic-key/dist/index.jsView file
matchType = normalized_sha256 matchedPackage = @rubytech/create-sitedesk-code@0.1.378 matchedPath = payload/platform/lib/anthropic-key/dist/index.js matchedIdentity = npm:[redacted]:0.1.378 similarity = 1.000 summary = normalized source hash matched finalized malicious source
High
Known Malware Source Similarity

Source file is highly similar to a previously finalized malicious package; route for source-aware review.

payload/platform/lib/anthropic-key/dist/index.jsView on unpkg
payload/platform/plugins/admin/lib/mcp-spawn-tee/index.jsView file
matchType = normalized_sha256 matchedPackage = @rubytech/create-sitedesk-code@0.1.378 matchedPath = [redacted]-spawn-tee/index.js matchedIdentity = npm:[redacted]:0.1.378 similarity = 1.000 summary = normalized source hash matched finalized malicious source
High
Known Malware Source Similarity

Source file is highly similar to a previously finalized malicious package; route for source-aware review.

payload/platform/plugins/admin/lib/mcp-spawn-tee/index.jsView on unpkg
payload/platform/plugins/email/mcp/dist/__tests__/email-delete.test.jsView file
52patternName = generic_password severity = medium line = 52 matchedText = credenti..." },
Medium
Secret Pattern

Hardcoded password in payload/platform/plugins/email/mcp/dist/__tests__/email-delete.test.js

payload/platform/plugins/email/mcp/dist/__tests__/email-delete.test.jsView on unpkg · L52
payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.jsView file
28patternName = generic_password severity = medium line = 28 matchedText = password...nt",
Medium
Secret Pattern

Hardcoded password in payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js

payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.jsView on unpkg · L28
43patternName = generic_password severity = medium line = 43 matchedText = password...nt",
Medium
Secret Pattern

Hardcoded password in payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js

payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.jsView on unpkg · L43
57patternName = generic_password severity = medium line = 57 matchedText = password...nt",
Medium
Secret Pattern

Hardcoded password in payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js

payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.jsView on unpkg · L57
127patternName = generic_password severity = medium line = 127 matchedText = email: "...0*",
Medium
Secret Pattern

Hardcoded password in payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js

payload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.jsView on unpkg · L127
payload/platform/lib/task-secrets/src/__tests__/redact-secrets.test.tsView file
73patternName = generic_password severity = medium line = 73 matchedText = { passwo...' },
Medium
Secret Pattern

Hardcoded password in payload/platform/lib/task-secrets/src/__tests__/redact-secrets.test.ts

payload/platform/lib/task-secrets/src/__tests__/redact-secrets.test.tsView on unpkg · L73

Findings

3 Critical12 High14 Medium9 Low
CriticalSame File Env Network Executiondist/index.js
CriticalDownload Executedist/index.js
CriticalTrigger Reachable Dangerous Capabilitydist/index.js
HighChild Processdist/index.js
HighShelldist/index.js
HighSandbox Evasion Gated Capabilitydist/index.js
HighCross File Remote Execution Contextdist/index.js
HighRuntime Package Installdist/index.js
HighShips High Entropy Blobpayload/server/public/assets/cormorant-latin-ext-500-normal-AH9qog1s.woff2
HighPayload In Excluded Dirpayload/platform/plugins/prompt-optimiser/skills/prompt-optimiser/__tests__/restatement-ladder.test.sh
HighKnown Malware Source Similaritypayload/platform/lib/graph-mcp/dist/index.js
HighKnown Malware Source Similaritypayload/platform/plugins/admin/mcp/dist/index.js
HighKnown Malware Source Similaritypayload/platform/plugins/cloudflare/mcp/dist/lib/cloudflared.js
HighKnown Malware Source Similaritypayload/platform/lib/anthropic-key/dist/index.js
HighKnown Malware Source Similaritypayload/platform/plugins/admin/lib/mcp-spawn-tee/index.js
MediumSecret Patternpayload/platform/scripts/smoke-boot-services.sh
MediumDynamic Require
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencedist/index.js
MediumProtestware
MediumShips Build Helperpayload/platform/plugins/prompt-optimiser/skills/prompt-optimiser/__tests__/restatement-ladder.test.sh
MediumStructural Risk Force Deep Review
MediumSecret Patternpayload/platform/plugins/email/mcp/dist/__tests__/email-delete.test.js
MediumSecret Patternpayload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js
MediumSecret Patternpayload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js
MediumSecret Patternpayload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js
MediumSecret Patternpayload/platform/plugins/email/mcp/dist/__tests__/email-setup.test.js
MediumSecret Patternpayload/platform/lib/task-secrets/src/__tests__/redact-secrets.test.ts
LowNon Install Lifecycle Scripts
LowScripts Present
LowEval
LowFilesystem
LowObfuscated
LowHigh Entropy Strings
LowTelemetry
LowUrl Strings
LowNo License