registry  /  @tianshu-ai/tianshu  /  0.4.28

@tianshu-ai/tianshu@0.4.28

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 by source inspection. Dangerous primitives are explicit AI-agent platform features activated by user commands or plugin setup, with visible sandbox/network/file boundaries.

Static reason
One or more suspicious static signals were detected.; previous stored version diff introduced dangerous source
Trigger
User runs tianshu commands, enables plugins, or uses agent tools.
Impact
No evidence of unconsented install-time execution, credential harvesting, exfiltration, persistence, or AI-agent control-surface mutation.
Mechanism
Package-aligned CLI, sandbox, web fetch, setup, and WeChat channel functionality.
Rationale
Static source inspection shows an AI agent platform with explicit user-invoked sandbox, web-fetch, service setup, and messaging capabilities; the scanner findings map to documented functionality rather than covert behavior. No lifecycle hook, import-time payload, credential harvesting, or unconsented persistence/exfiltration path was confirmed.
Evidence
package.jsonbin/tianshu.mjsplugins/web-search/dist/tools/web-fetch.jsplugins/openshell/dist/runner/openshell-runner.jsplugins/openshell/dist/runner/gateway-manager.jspackages/server/dist/setup/start-server.jspackages/server/dist/setup/launchd.jspackages/server/dist/setup/service.jsplugins/wechat/dist/ilink-media.js

Decision evidence

public snapshot
AI called this Clean at 87.0% confidence as Benign with low false-positive risk.
Evidence for block
    Evidence against
    • package.json has no install/postinstall hook; prepublishOnly only runs before publishing.
    • bin/tianshu.mjs is a minimal CLI shim importing packages/server/dist/cli.js.
    • plugins/web-search/dist/tools/web-fetch.js explicitly blocks localhost, private ranges, link-local, and metadata hosts before fetch and after redirect.
    • plugins/openshell/dist/runner/openshell-runner.js provides user-invoked sandbox exec/file sync with path traversal checks, not install-time execution.
    • packages/server/dist/setup/start-server.js/launchd.js write .env and launchd plist only through setup/start flows with prompts/status handling.
    • plugins/wechat/dist/ilink-media.js uploads user-supplied media to WeChat/iLink endpoints as channel functionality.
    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/openshell/dist/runner/openshell-runner.jsView file
    matchType = previous_version_dangerous_delta matchedPackage = @tianshu-ai/tianshu@0.4.27 matchedIdentity = npm:QHRpYW5zaHUtYWkvdGlhbnNodQ:0.4.27 similarity = 0.983 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/openshell/dist/runner/openshell-runner.jsView on unpkg

    Findings

    1 Critical1 High7 Medium7 Low
    CriticalPrevious Version Dangerous Deltaplugins/openshell/dist/runner/openshell-runner.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