github TypeScript re-analysis due

oddbit/shrtnr

github

A no-BS, self-hosted URL shortener, AI first with MCP server built in, running on Cloudflare Workers, edge-native, and ridiculously easy to deploy

maintainer
oddbit
license
Apache-2.0
first seen
2026-06-11
last seen
2026-08-28
releases · 30d
8
short id

Drift inferred · capture-to-capture

No drift recorded — single capability capture; advisories appear once its surface changes.

capabilities 37 tools
transport stdio · http counts 37 tools · 0 res · 0 prompts permission surface via code analysis

tools

  • add_custom_slug
  • add_link_to_bundle
  • archive_bundle
  • compare_links
  • create_bundle
  • create_link
  • delete_bundle
  • delete_link
  • disable_link
  • disable_slug
  • enable_link
  • enable_slug
  • get_bundle
  • get_bundle_analytics
  • get_clicks_by_country
  • get_clicks_by_device
  • get_clicks_by_referrer
  • get_dashboard_stats
  • get_link
  • get_link_analytics
  • get_link_breakdown
  • get_link_qr
  • get_link_timeline
  • get_total_clicks
  • get_trending_links
  • health
  • list_bundle_links
  • list_bundles
  • list_bundles_for_link
  • list_links
  • list_links_by_owner
  • remove_link_from_bundle
  • remove_slug
  • search_links
  • unarchive_bundle
  • update_bundle
  • update_link
skills & danger signals github-tarball
prompt-surface shipped agent-instruction files + hidden-content / dangerous-code findings — quoted from the analyzed source

analyzed commit ff96eb4 · analyzer v33 · 2w ago

skills & prompt files 1

danger signals2

code evidence vnpm-v1.1.2 · github-tarball
evidence-backed findings quoted directly from the published source artifact — not inferred

code files: 246

filesystem 3

  • fs oddbit-shrtnr-ff96eb4/browser-extensions/build.mjs :16 import { promises as fs } from "node:fs";
  • fs (weak) oddbit-shrtnr-ff96eb4/browser-extensions/scripts/generate-icons.mjs :10 import { promises as fs } from "node:fs";
  • fs (weak) oddbit-shrtnr-ff96eb4/browser-extensions/scripts/verify-build.mjs :8 import { promises as fs } from "node:fs";

shell / exec 2

  • shell oddbit-shrtnr-ff96eb4/browser-extensions/build.mjs :19 import { spawn } from "node:child_process";
  • shell (weak) oddbit-shrtnr-ff96eb4/browser-extensions/scripts/generate-icons.mjs :13 import { spawn } from "node:child_process";

network 26

  • net (weak) oddbit-shrtnr-ff96eb4/sdk/typescript/tests/client.test.ts :29 // streaming: the failure mode a rejected fetch() promise cannot reproduce.
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/admin/widgets/cache-invalidation.test.ts :16 return worker.fetch(new Request("https://x.test" + path, init), env as never, {
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/admin/widgets/route.test.ts :16 return worker.fetch(new Request("https://x.test" + path), env as any, {
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/api-keys.test.ts :50 const res = await SELF.fetch(
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/api-links.test.ts :49 const res = await SELF.fetch(
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/api-misc.test.ts :31 const res = await SELF.fetch(unauthed("/"));
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/breakdown-pagination.test.ts :29 const res = await SELF.fetch(new Request("https://shrtnr.test/_/admin/api/keys", {
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/bundles-api.test.ts :60 const res = await SELF.fetch(authed("owner@x", "/_/admin/api/bundles", {
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/mcp.test.ts :37 const res = await SELF.fetch(
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/openapi.test.ts :17 const res = await SELF.fetch(
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/public-api-range.test.ts :19 const res = await SELF.fetch(new Request("https://shrtnr.test/_/admin/api/keys", {
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/handler/redirect-kv.test.ts :30 const res = await SELF.fetch(req("cached"));
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/integration/bundle-aggregation.test.ts :63 const res = await SELF.fetch(
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/integration/expiration-flow.test.ts :47 const res = await SELF.fetch(req(slug));
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/integration/mcp-create-and-redirect.test.ts :66 const res = await SELF.fetch(
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/integration/redirect-flow.test.ts :60 const redirectRes = await SELF.fetch(
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/page/bundle-detail-page.test.ts :49 const res = await SELF.fetch(req(`/_/admin/bundles/${bundle.id}`));
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/page/bundles-page.test.ts :24 const res = await SELF.fetch(req("/_/admin/bundles"));
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/page/keys-page.test.ts :40 const res = await SELF.fetch(authed("/_/admin/keys"));
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/page/link-detail-page.test.ts :23 const res = await SELF.fetch(req(`/_/admin/links/${link.id}`));
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/page/links-page.test.ts :26 const res = await SELF.fetch(req("/_/admin/links"));
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/page/settings-page.test.ts :14 const res = await SELF.fetch(req("/_/admin/settings"));
  • net (weak) oddbit-shrtnr-ff96eb4/src/__tests__/service/tracking-service.test.ts :30 const res = await SELF.fetch(
  • net oddbit-shrtnr-ff96eb4/src/client.ts :84 return fetch(API + path, opts).then(function(res) {
  • net oddbit-shrtnr-ff96eb4/src/index.tsx :117 // confuse fetch() callers expecting JSON.
  • net oddbit-shrtnr-ff96eb4/src/title-fetch.ts :10 const res = await fetch(url, {

secrets 1

  • secrets (weak) oddbit-shrtnr-ff96eb4/sdk/typescript/tests/e2e/e2e.test.ts :17 const API_KEY = process.env.SHRTNR_TEST_API_KEY;

tool registrations 37

  • health oddbit-shrtnr-ff96eb4/src/mcp/server.ts :155
  • list_links oddbit-shrtnr-ff96eb4/src/mcp/server.ts :169
  • get_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :189
  • create_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :210
  • update_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :257
  • disable_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :277
  • enable_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :294
  • add_custom_slug oddbit-shrtnr-ff96eb4/src/mcp/server.ts :311
  • disable_slug oddbit-shrtnr-ff96eb4/src/mcp/server.ts :329
  • enable_slug oddbit-shrtnr-ff96eb4/src/mcp/server.ts :348
  • remove_slug oddbit-shrtnr-ff96eb4/src/mcp/server.ts :367
  • get_link_analytics oddbit-shrtnr-ff96eb4/src/mcp/server.ts :386
  • search_links oddbit-shrtnr-ff96eb4/src/mcp/server.ts :407
  • list_links_by_owner oddbit-shrtnr-ff96eb4/src/mcp/server.ts :436
  • get_link_qr oddbit-shrtnr-ff96eb4/src/mcp/server.ts :464
  • get_trending_links oddbit-shrtnr-ff96eb4/src/mcp/server.ts :515
  • get_dashboard_stats oddbit-shrtnr-ff96eb4/src/mcp/server.ts :535
  • get_link_timeline oddbit-shrtnr-ff96eb4/src/mcp/server.ts :554
  • get_clicks_by_country oddbit-shrtnr-ff96eb4/src/mcp/server.ts :575
  • get_clicks_by_referrer oddbit-shrtnr-ff96eb4/src/mcp/server.ts :595
  • get_clicks_by_device oddbit-shrtnr-ff96eb4/src/mcp/server.ts :615
  • compare_links oddbit-shrtnr-ff96eb4/src/mcp/server.ts :639
  • get_link_breakdown oddbit-shrtnr-ff96eb4/src/mcp/server.ts :659
  • get_total_clicks oddbit-shrtnr-ff96eb4/src/mcp/server.ts :681
  • delete_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :700
  • list_bundles oddbit-shrtnr-ff96eb4/src/mcp/server.ts :722
  • get_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :749
  • create_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :769
  • update_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :795
  • archive_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :816
  • unarchive_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :834
  • delete_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :852
  • add_link_to_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :870
  • remove_link_from_bundle oddbit-shrtnr-ff96eb4/src/mcp/server.ts :889
  • list_bundle_links oddbit-shrtnr-ff96eb4/src/mcp/server.ts :908
  • list_bundles_for_link oddbit-shrtnr-ff96eb4/src/mcp/server.ts :925
  • get_bundle_analytics oddbit-shrtnr-ff96eb4/src/mcp/server.ts :942

install hooks 1

  • prepublishOnly oddbit-shrtnr-ff96eb4/sdk/typescript/package.json :28 npm run build

declared dependencies 15

  • @modelcontextprotocol/sdk@1.29.0
  • @cloudflare/workers-oauth-provider@^0.8.2
  • @hono/zod-openapi@^1.5.1
  • agents@^0.19.0
  • hono@^4.12.32
  • jose@^6.2.4
  • zod@^4.4.3
  • @cloudflare/vitest-pool-workers@^0.18.8
  • @cloudflare/workers-types@^5.20260728.1
  • @vitest/runner@^4.1.10
  • @vitest/snapshot@^4.1.10
  • tsx@^4.23.1
  • typescript@^6.0.3
  • vitest@^4.1.10
  • wrangler@^4.114.0

clipboard 2

  • navigator.clipboard oddbit-shrtnr-ff96eb4/browser-extensions/src/clipboard.ts :5 if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) {
  • navigator.clipboard oddbit-shrtnr-ff96eb4/browser-extensions/tests/setup.ts :148 return globalThis.navigator.clipboard as unknown as { writeText: ReturnType<typeof vi.fn> };

perm:untrusted 1

  • untrusted oddbit-shrtnr-ff96eb4/src/client.ts :84 return fetch(API + path, opts).then(function(res) {