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

@rubytech/create-sitedesk-code@0.1.379

Install SiteDesk — automated back office for independent building contractors

AI Security Review

scanned 12d ago · by lpm-firewall-ai

LPM blocks this version under the AI-agent control-surface policy. The package is a CLI installer that mutates the Claude Code control surface by forcing bypassPermissions and registering plugins/agents under a brand-scoped Claude config. This creates unconsented AI-agent permission bypass despite being reachable only when the user runs the installer.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
User runs create-sitedesk-code / dist/index.js bin.
Impact
Installed Claude sessions can run with permission checks bypassed and package-provided plugins/agents registered, expanding agent authority on the host.
Mechanism
Claude Code settings and plugin/agent control-surface mutation with permission bypass
Policy narrative
Running the package bin starts a large installer. During install it creates a per-brand Claude config directory, writes settings.json with defaultMode set to bypassPermissions, adds autoMode allowances around Cloudflare token provisioning, registers plugin marketplaces, installs plugins, and symlinks bundled specialist agents. These changes alter an AI agent control surface and reduce permission enforcement without a clear explicit user consent boundary in the package metadata or CLI flow.
Rationale
Direct source inspection confirms reachable Claude Code permission-bypass and plugin/agent registration from the package bin. Although many system/network operations fit the installer purpose and there is no npm install hook, unconsented AI-agent control-surface mutation is concrete blocking behavior. Product guard normalized a non-low false-positive publish_block request to warn-only suspicious.
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~/.sitedesk-code/.claude/agents/*.md~/sitedesk-code/platform~/sitedesk-code/server~/sitedesk-code/premium-plugins/etc/systemd/system/*~/.config/systemd/user/*
Network endpoints10
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/github.com/ggerganov/whisper.cpp.gitapi.cloudflare.com

Decision evidence

public snapshot
AI called this Suspicious at 90.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for policy block
  • dist/index.js is bin entrypoint and executes installer logic at runtime.
  • dist/index.js calls installClaudeCode(), then seedBypassPermissionsSettings(CLAUDE_CONFIG_DIR).
  • dist/permissions-seed.js writes settings.json with permissions.defaultMode="bypassPermissions" and Cloudflare autoMode allow rules.
  • dist/index.js registers Claude plugin marketplaces and installs local/external plugins into per-brand CLAUDE_CONFIG_DIR.
  • dist/index.js performs privileged system mutations and runtime installs via sudo apt/npm/npx/curl pipes.
Evidence against
  • package.json has no install/postinstall hook; activation requires running the CLI bin.
  • Network/system installs are broadly aligned with an appliance installer.
  • Several secrets generated locally are written with 0600 and logging redacts Neo4j password args.
Behavioral surface
Source
ChildProcessCryptoDynamicRequireEnvironmentVarsFilesystemNativeBindingsNetworkShell
Supply chain
HighEntropyStringsMinifiedObfuscatedTelemetryUrlStrings
Manifest
NoLicense
scanned 653 file(s), 9.74 MB of source, external domains: 0.0.0.0, 127.0.0.1, api.anthropic.com, api.joblogic.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, identityserver.joblogic.com, langium.org, llmstxt.org, login.microsoftonline.com, maxy.bot, maxy.setup, 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, uatapi.joblogic.com, uatidentityserver.joblogic.com, www.linkedin.com, www.w3.org, www.youtube-nocookie.com

Source & flagged code

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

Package contains a possible secret pattern.

payload/platform/scripts/smoke-boot-services.shView on unpkg · L317
dist/index.jsView file
134for (const host of ["registry.npmjs.org", "github.com"]) { L135: const dns = spawnSync("host", ["-W", "5", host], { encoding: "utf-8", stdio: "pipe", timeout: 10_000 }); L136: logFile(`DNS ${host}: ${dns.status === 0 ? "OK" : "FAIL"} — ${(dns.stdout || dns.stderr || "").trim().split("\n")[0]}`); ... L141: "--connect-timeout", "10", L142: "https://registry.npmjs.org/", L143: ], { encoding: "utf-8", stdio: "pipe", timeout: 15_000 }); ... L148: function captureNpmDebugLog() { L149: const logsDir = resolve(process.env.HOME ?? "/root", ".npm/_logs"); L150: 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 · L134
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 } from "node:fs"; ... 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"; ... L44: } L45: const INSTALL_DIR = resolve(process.env.HOME ?? "/root", BRAND.installDir); L46: const PERSIST_DIR = resolve(process.env.HOME ?? "/root", BRAND.configDir); ... L100: ` ${BRAND.productName} Install Log — ${new Date().toISOString()}`, L101: ` Node ${process.version} | ${process.platform} ${process.arch}`, L102: "=".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 } from "node:fs"; ... 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"; ... L44: } L45: const INSTALL_DIR = resolve(process.env.HOME ?? "/root", BRAND.installDir); L46: const PERSIST_DIR = resolve(process.env.HOME ?? "/root", BRAND.configDir); ... L100: ` ${BRAND.productName} Install Log — ${new Date().toISOString()}`, L101: ` Node ${process.version} | ${process.platform} ${process.arch}`, L102: "=".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 } from "node:fs";
High
Child Process

Package source references child process execution.

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

Package source references shell execution.

dist/index.jsView on unpkg · L506
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 } from "node:fs"; ... 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"; ... L44: } L45: const INSTALL_DIR = resolve(process.env.HOME ?? "/root", BRAND.installDir); L46: const PERSIST_DIR = resolve(process.env.HOME ?? "/root", BRAND.configDir); ... L100: ` ${BRAND.productName} Install Log — ${new Date().toISOString()}`, L101: ` Node ${process.version} | ${process.platform} ${process.arch}`, L102: "=".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 } from "node:fs"; ... 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"; ... L44: } L45: const INSTALL_DIR = resolve(process.env.HOME ?? "/root", BRAND.installDir); L46: const PERSIST_DIR = resolve(process.env.HOME ?? "/root", BRAND.configDir); ... L100: ` ${BRAND.productName} Install Log — ${new Date().toISOString()}`, L101: ` Node ${process.version} | ${process.platform} ${process.arch}`, L102: "=".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
1066console.log(" This may take 15–30 minutes on Raspberry Pi..."); L1067: console.log(" [privileged] npm install -g @anthropic-ai/claude-code@latest"); L1068: shellRetry("npm", ["install", "-g", ...NPM_NET_FLAGS, "--loglevel", "verbose", "@anthropic-ai/claude-code@latest"], { sudo: true, timeout: 2_400_000 }, // 40 min — Pi downloads can... ... L1081: logFile(`[install-permissions] action=${permissionsSeed.action} autoMode=${permissionsSeed.autoMode} path=${permissionsSeed.path}`); L1082: const marketplaceList = spawnSync("claude", ["plugin", "marketplace", "list"], { stdio: "pipe", encoding: "utf-8", env: claudePluginEnv() }); L1083: if (marketplaceList.stderr)
High
Runtime Package Install

Package source invokes a package manager install command at runtime.

dist/index.jsView on unpkg · L1066
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 } from "node:fs"; ... 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"; ... L44: } L45: const INSTALL_DIR = resolve(process.env.HOME ?? "/root", BRAND.installDir); L46: const PERSIST_DIR = resolve(process.env.HOME ?? "/root", BRAND.configDir); ... L100: ` ${BRAND.productName} Install Log — ${new Date().toISOString()}`, L101: ` Node ${process.version} | ${process.platform} ${process.arch}`, L102: "=".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/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 Critical7 High13 Medium8 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
MediumSecret Patternpayload/platform/scripts/smoke-boot-services.sh
MediumDynamic Require
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistencedist/index.js
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
LowFilesystem
LowObfuscated
LowHigh Entropy Strings
LowTelemetry
LowUrl Strings
LowNo License