thingery@0.2.0
CAUTION· install onlyPublisher claims: "Thingery is the open item database and MCP server for AI agents to list, find, and trade second-hand goods. Agents publish listings with photos and category attributes, search via hybrid semantic/keyword filters, and connect to the hosted instance or self-host with Postgres + pgvector (npx thingery over stdio)." Observed in sandbox: no network, touches nothing outside the project, writes no memory.
Coverage
Nothing executable in the bundle ran; the trace covers the install step only.- Tested
- every file read, file written and host contacted by what ran
- Not tested
- use of the skill by an agent
What this means for the label: Caution here covers what ran. The server's tools were not exercised with a real credential, so nothing about their behavior is asserted; the credential summary below says what to do with that.
Before you give it your token
- It will ask for
ADMIN_API_KEYDATABASE_URLEASYPOST_WEBHOOK_SECRETEMBED_API_KEYLLM_API_KEYOAUTH_ACCESS_TTL_SOAUTH_DCR_HOURLY_LIMITOAUTH_DISABLEDOAUTH_REFRESH_TTL_SOPENAI_APPS_CHALLENGE_TOKENROUTINE_WEBHOOK_TOKENSELLER_API_KEYSESSION_SECRETSTRIPE_SECRET_KEYSTRIPE_WEBHOOK_SECRETTHINGERY_API_KEYConfiguration, not credentials: ADMIN_KEY, B_KEY, DEMO_SELLER_KEY, EMBED_API_URL, EMBED_MODEL, FRAMES_DIR, LLM_API_URL, LLM_BYO_ALLOW_LOCAL_ENDPOINTS, LLM_BYO_ALLOWED_MODELS, LLM_MODEL, O_KEY, OUT, PROBE_KEY, PUBLIC_BASE_URL, S_KEY, THINGERY_MCP_URL, TRANSPORT, UPLOADS_DIR- Where it talks to
- thingery.dev (its own)Also easypost.com, z.ai, soldstack.dev — not the publisher's domain; check what for before connecting.
- What the honeypot saw
- no credential files read · no network
- What we could not test
- use of the skill by an agent
Connect it with a scoped credential, under the guard, and read the third-party hosts first. The code names easypost.com, z.ai, soldstack.dev as well as its own vendor. The guard injects ADMIN_API_KEY, DATABASE_URL, EASYPOST_WEBHOOK_SECRET, EMBED_API_KEY, LLM_API_KEY, OAUTH_ACCESS_TTL_S, OAUTH_DCR_HOURLY_LIMIT, OAUTH_DISABLED, OAUTH_REFRESH_TTL_S, OPENAI_APPS_CHALLENGE_TOKEN, ROUTINE_WEBHOOK_TOKEN, SELLER_API_KEY, SESSION_SECRET, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, THINGERY_API_KEY only into requests to thingery.dev (and its subdomains) and refuses the rest.
Never paste a credential into a chat, a ticket or a report, including ours. How the guard holds it.
Is [email protected] safe to install?
KillerSkills ran it in the KillerSkills honeypot sandbox (1 scenario; nothing executable in the bundle ran; the trace covers the install step only) on 2026-11-13 and scored it 78/100 (Caution). It is not known to be malicious, but it has behaviour or code a security policy should decide on before install. Notable findings: Access to sensitive file paths; Access to sensitive file paths; Access to sensitive file paths. Summary: no network, touches nothing outside the project, writes no memory.
Behavior trace
Honeypot run · 0 s · 1 scenarios · 0 deviationsStatic findings
/** env name, kept in one place for .env.example / compose / docs alignment. */Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.subprocess.run(["ffmpeg", "-y", "-r", str(FPS), "-i", os.path.join(FRAMES_DIR, "f%05d.png"),Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.* (revoked grants kill their tokens) — no fallback chain, no second query.Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.mkdir -p "$STATE_DIR" && chmod 700 "$STATE_DIR"Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts./** OAUTH_DISABLED kill switch (spec THI-11 §4.4): read per call so it can beFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.// everywhere. HMAC-SHA256(body, "") is computable by anyone, and .env filesFix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.logs, or PR descriptions. Use `.env.example` placeholders only.Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.3. **Credentials never enter the repo.** No tokens, no `.env` files, no secrets in code,Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.d.text((W//2, 470), "same flow self-hosted: npx thingery · MCP: thingery.dev/mcp",Fix: Pin versions and sources; vendor anything fetched at install time.res.status(429).json({ error: "Too many uploads — try again later." });Fix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.* A2): 0 is a MEANINGFUL value — LABEL_DAILY_BUDGET_CENTS=0 is the spend killFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.if (oauthDisabled()) return { seller: null, failure: "invalid_token" }; // kill switch (§4.4)Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.console.log("[config] Stripe payments not configured — order tools answer payments_not_configured (kill switch)");Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.// LABEL_DAILY_BUDGET_CENTS (default €200; 0 = kill switch), derived fromFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.res.status(405).json({ error: "Method not allowed. Use POST with JSON-RPC. Stateles HTTP transport." });Fix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.res.status(400).json({ error: "Empty upload — send the image bytes as the request body." });Fix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.// controls”): 0 = kill switch — every purchase is refused while tracker-onlyFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.// The client is null when Stripe is unconfigured (config.ts kill switch) —Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.* TRANSPORT=stdio — local MCP server over stdin/stdout, for `npx thingery` andFix: Pin versions and sources; vendor anything fetched at install time.// OAUTH_DISABLED kill switch (spec §4.4): no OAuth route is mounted at all —Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell./** Singleton Stripe client; null when STRIPE_SECRET_KEY is unset (kill switch). */Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.// Mount BEFORE the global express.json() (index.ts) — signatures are computedFix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.console.log("[config] Admin dispute route disabled (ADMIN_API_KEY unset or shorter than 32 chars)");Fix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.* The Dockerfile writes a `build-info.json` next to the compiled outputFix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.res.status(400).json({ error: `Send images as an array of up to ${MAX_IMAGES_PER_ITEM} photo references.` });Fix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.labelDailyBudgetCents: number; // 20000 ≈ €200/day platform-wide; 0 = kill switch (A2)Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.res.status(429).json({ error: "Too many uploads — try again later." });Fix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.// Stripe payments (the kill switch: STRIPE_SECRET_KEY absent → order toolsFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.res.status(400).json({ error: "Send the image bytes as the raw request body with an image Content-Type." });Fix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.// --- refresh (§3.3): single-flight, compare-and-swap, terminal-error kill ---Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.// escaping as unhandled rejections that kill the process (Express 4 does notFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.Cost to the agent
Tokens estimated at four characters each. Skills load their instruction text when triggered; the figure is what that costs.
Known vulnerabilities
Vulnerability advisories (OSV) cover npm and PyPI packages; this registry has no advisory database.
What would make this Verified
2 points to 80 · weights: behavior 45%, static 25%, prompt 15%, publisher 15%- Unclaimed publisher≈ +8 on the totalClaim thingery: a verified publisher gets +50 on publisher trust. It is free and usually instant with GitHub sign-in.
- Access to sensitive file paths≈ +4 on the totalStop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
- Python subprocess execution detected≈ +2 on the totalBuild commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.
- Process kill command≈ +2 on the totalBuild commands from fixed arguments; do not interpolate untrusted strings into a shell.
- File permission modification command≈ +2 on the totalRequest the narrowest permission that works; replace wildcards with the exact paths or hosts.
- npx invocation of non-well-known package≈ +2 on the totalPin versions and sources; vendor anything fetched at install time.