registry  /  @tianshu-ai/tianshu  /  0.4.30

@tianshu-ai/tianshu@0.4.30

An open AI agent platform with a sidecar browser. Built in public.

AI Security Review

scanned 4d ago · by lpm-firewall-ai

No confirmed malicious attack surface was found. Network, shell, file, and launchd behavior are aligned with an AI agent platform, web search, sandbox runner, setup command, and WeChat integration, and are user/runtime invoked rather than install-time hidden execution.

Static reason
One or more suspicious static signals were detected.; previous stored version diff introduced dangerous source
Trigger
explicit CLI/plugin/runtime use
Impact
no confirmed credential theft, exfiltration, persistence abuse, or install-time execution
Mechanism
package-aligned agent platform capabilities
Rationale
Static inspection found powerful but expected functionality for this package: CLI service setup, sandboxed agent execution, web fetch/search, and WeChat media upload. The scanner-reported metadata endpoint string is part of an SSRF blocklist, and persistence/file/network operations are explicit user or plugin workflows, not covert lifecycle behavior.
Evidence
package.jsonbin/tianshu.mjsplugins/web-search/dist/tools/web-fetch.jsplugins/web-search/dist/tools/providers.jsplugins/workboard/dist/worker/opencode-worker.jspackages/server/dist/setup/start-server.jspackages/server/dist/setup/launchd.jsplugins/wechat/dist/ilink-api.jsplugins/wechat/dist/ilink-media.js.env~/Library/LaunchAgents/ai.tianshu.*.plist~/Library/Logs/tianshu/*.logopencode/<taskId>/opencode.jsonopencode/<taskId>/.prompt.txtopencode/<taskId>/opencode-transcript.jsonl
Network endpoints4
search.parallel.ai/mcpmcp.exa.ai/mcpilinkai.weixin.qq.comnovac2c.cdn.weixin.qq.com/c2c

Decision evidence

public snapshot
AI called this Clean at 84.0% confidence as Benign with low false-positive risk.
Evidence for block
    Evidence against
    • package.json has no install/postinstall hooks; prepublishOnly is publish-time build only.
    • bin/tianshu.mjs only resolves packages/server/dist/cli.js relative to the package and imports main().
    • plugins/web-search/dist/tools/web-fetch.js implements user-requested HTTP fetch and blocks localhost, private ranges, link-local, and metadata hosts before redirects.
    • plugins/workboard/dist/worker/opencode-worker.js runs opencode only for a workboard task inside the configured shell sandbox with a per-task proxy token that is revoked in finally.
    • packages/server/dist/setup/start-server.js and setup/launchd.js write .env/plist only during explicit setup/start flows with prompts or service commands.
    • plugins/wechat/dist/ilink-media.js reads a caller-supplied file path and uploads encrypted media to Tencent iLink/CDN as part of the WeChat plugin workflow.
    Behavioral surface
    Source
    ChildProcessCryptoDynamicRequireEnvironmentVarsFilesystemNativeBindingsNetworkShellWebSocket
    Supply chain
    HighEntropyStringsMinifiedObfuscatedProtestwareUrlStrings
    Manifest
    WildcardDependency
    scanned 333 file(s), 8.16 MB of source, external domains: 127.0.0.1, api.anthropic.com, api.openai.com, dashscope.aliyuncs.com, example.com, generativelanguage.googleapis.com, github.com, host.docker.internal, host.openshell.internal, ilinkai.weixin.qq.com, mcp.exa.ai, novac2c.cdn.weixin.qq.com, opencode.ai, raw.githubusercontent.com, react.dev, reactrouter.com, registry.npmjs.org, search.parallel.ai, www.apple.com, www.docker.com, www.w3.org

    Source & flagged code

    5 flagged · loading source
    bin/tianshu.mjsView file
    29L30: const { main } = await import(distEntry); L31: const code = await main(process.argv.slice(2));
    Medium
    Dynamic Require

    Package source references dynamic require/import behavior.

    bin/tianshu.mjsView on unpkg · L29
    plugins/wechat/dist/ilink-media.jsView file
    18// L19: // The CDN URL itself is `https://novac2c.cdn.weixin.qq.com/c2c` L20: // (platform constant, matches what Tencent's plugin hard-codes). ... L76: }); L77: const resp = JSON.parse(raw); L78: if (resp.ret && resp.ret !== 0) { ... L92: headers: { "Content-Type": "application/octet-stream" }, L93: body: new Uint8Array(opts.ciphertext), L94: });
    Low
    Weak Crypto

    Package source references weak cryptographic algorithms.

    plugins/wechat/dist/ilink-media.jsView on unpkg · L18
    packages/server/dist/setup/start-server.jsView file
    21import fs from "node:fs"; L22: import net from "node:net"; L23: import os from "node:os"; ... L36: // typically run `tianshu setup` from their home dir, so L37: // process.cwd() won't be the repo. Walk up from this module's L38: // location until we hit a package.json named L39: // '@tianshu-ai/tianshu' (or run out of parents). ... L50: ? path.join(repoRoot, ".env") L51: : path.join(process.env.TIANSHU_HOME ?? L52: path.join(process.env.HOME ?? "", ".tianshu"), ".env")); ... L137: if (!r.ok) { L138: p.log.error(`launchctl kickstart failed: ${r.stderr ?? "(unknown)"}`);
    Medium
    Install Persistence

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

    packages/server/dist/setup/start-server.jsView on unpkg · L21
    plugins/web-search/dist/tools/web-fetch.jsView file
    1// `web_fetch(url, extractMode?, maxChars?)`. L2: // ... L14: // L15: // SSRF: we block private / loopback / link-local / metadata hosts L16: // before fetching AND re-check after redirects, so an agent can't ... L93: const ctype = res.headers.get("content-type") ?? ""; L94: const body = await res.text(); L95: let out; ... L110: text, L111: data: { L112: url,
    High
    Cloud Metadata Access

    Source reaches cloud instance metadata or link-local credential endpoints.

    plugins/web-search/dist/tools/web-fetch.jsView on unpkg · L1
    plugins/workboard/dist/worker/opencode-worker.jsView file
    matchType = previous_version_dangerous_delta matchedPackage = @tianshu-ai/tianshu@0.4.28 matchedIdentity = npm:QHRpYW5zaHUtYWkvdGlhbnNodQ:0.4.28 similarity = 0.992 summary = stored previous version shares package body but lacks this dangerous source file
    Critical
    Previous Version Dangerous Delta

    This package version adds a dangerous source file absent from the previous stored version.

    plugins/workboard/dist/worker/opencode-worker.jsView on unpkg

    Findings

    1 Critical1 High7 Medium7 Low
    CriticalPrevious Version Dangerous Deltaplugins/workboard/dist/worker/opencode-worker.js
    HighCloud Metadata Accessplugins/web-search/dist/tools/web-fetch.js
    MediumDynamic Requirebin/tianshu.mjs
    MediumNetwork
    MediumEnvironment Vars
    MediumInstall Persistencepackages/server/dist/setup/start-server.js
    MediumProtestware
    MediumStructural Risk Force Deep Review
    MediumWildcard Dependency
    LowNon Install Lifecycle Scripts
    LowScripts Present
    LowWeak Cryptoplugins/wechat/dist/ilink-media.js
    LowFilesystem
    LowObfuscated
    LowHigh Entropy Strings
    LowUrl Strings