{"id":50988301,"url":"https://github.com/hellodword/paranoid","last_synced_at":"2026-06-19T22:31:33.862Z","repository":{"id":353587704,"uuid":"1219868751","full_name":"hellodword/paranoid","owner":"hellodword","description":"Safer defaults for the LLM agent ecosystem.","archived":false,"fork":false,"pushed_at":"2026-04-24T14:11:12.000Z","size":66,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-24T16:17:24.392Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hellodword.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-24T09:52:45.000Z","updated_at":"2026-04-24T14:11:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/hellodword/paranoid","commit_stats":null,"previous_names":["hellodword/paranoid"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/hellodword/paranoid","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellodword%2Fparanoid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellodword%2Fparanoid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellodword%2Fparanoid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellodword%2Fparanoid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hellodword","download_url":"https://codeload.github.com/hellodword/paranoid/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellodword%2Fparanoid/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34550858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-19T02:00:06.005Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-19T22:31:33.795Z","updated_at":"2026-06-19T22:31:33.857Z","avatar_url":"https://github.com/hellodword.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# paranoid\n\n## Why this exists\n\nThe current LLM agent ecosystem makes me uneasy. Too much of it relies on unsafe defaults, and some of those defaults have become widely accepted as normal.\n\nA simple example: the official documentation for many popular MCP tools recommends running commands like `npx -y foo@latest`. That may be convenient, but it also means executing whatever happens to be published as `latest` at that moment. For security-sensitive workflows, especially those involving agents, this is not a tradeoff I am comfortable with. At the same time, solutions like [toolhive](https://github.com/stacklok/toolhive) feel too heavyweight for my use case, for reasons I may explain in the future.\n\nI looked into whether `npm` or `npx` could lock both the package version and the package hash in a single command. As far as I can tell, they cannot. I found a workaround.\n\nThis is only one small part of a much broader concern I have about the agent tooling ecosystem. I plan to keep documenting issues, mitigations, and safer patterns as I continue digging.\n\n## Threat Model\n\n### Trust assumption\n\nWhen I choose to use an MCP server, I am making an explicit trust decision about a specific version of that software. I assume that version has already been reviewed to a level I consider acceptable, whether that review was performed by a trusted organization or by me directly.\n\n### Security objective\n\nMy goal is not to eliminate all software risk. My goal is to prevent silent drift from a reviewed version to newly published code through `latest`, floating version ranges, or any other implicit resolution behavior. I want upgrades to happen only when I choose them.\n\n### Accepted risk\n\nI explicitly accept the possibility that a pinned and previously reviewed version may still contain vulnerabilities, design flaws, or audit misses. Locking a version does not make it safe. It only preserves the review boundary I intended to trust.\n\n### Upgrade policy\n\nEvery version change is treated as a new trust decision. In practice, that means every upgrade should be accompanied by a fresh audit, review, or other deliberate approval step before the new version is allowed to run.\n\n### Non-goals\n\nThis project does not certify that a locked version is secure. It does not replace sandboxing, provenance verification, or broader supply-chain controls. It is specifically intended to make upgrades explicit and reviewable, not to solve every security problem in the MCP ecosystem.\n\n## npm / npx workaround\n\n1. Add an audited package:\n\n```shell\nnpm run add-cli \"@upstash/context7-mcp@2.1.8\"\n```\n\n2. Replace `npx` with a repo-local `npm run` entry:\n\nOriginal:\n\n```toml\n[mcp_servers.context7]\ncommand = \"npx\"\nargs = [\n  \"-y\",\n  \"@upstash/context7-mcp\"\n]\n\n[mcp_servers.playwright]\ncommand = \"npx\"\nargs = [\n  \"-y\",\n  \"@playwright/mcp\",\n  \"--cdp-endpoint\", \"http://1.2.3.4:9222\"\n]\n```\n\nNow:\n\n```toml\n[mcp_servers.context7]\ncommand = \"npm\"\nargs = [\n  \"-C\", \"/path/to/paranoid\",\n  \"run\", \"--silent\",\n  \"@upstash/context7-mcp\"\n]\n\n[mcp_servers.playwright]\ncommand = \"npm\"\nargs = [\n  \"-C\", \"/path/to/paranoid\",\n  \"run\", \"--silent\",\n  \"@playwright/mcp\",\n  \"--\",\n  \"--cdp-endpoint\", \"http://1.2.3.4:9222\"\n]\n```\n\n## uv / uvx workaround\n\nThis repo also includes a `uvx` replacement based on `pyproject.toml` and `uv.lock`.\nThe lockfile remains the source of truth, but Python tools are installed into a repo-local\nvendor directory instead of `.venv`. That avoids copied-venv breakage when the whole directory\nis moved to a different path.\n\n1. Add an audited Python CLI package with an exact pin:\n\n```shell\nuv --directory /path/to/paranoid run --no-project python scripts/add_uv_cli.py mcp-server-time==2026.1.26\n```\n\n2. Build or refresh the vendored tool directory:\n\n```shell\nuv --directory /path/to/paranoid run --no-project python scripts/sync_uv_tools.py\n```\n\n3. Replace `uvx ...` with `uv --directory ... run --no-project --offline python scripts/run_uv_tool.py ...`:\n\nOriginal:\n\n```toml\n[mcp_servers.mcp-server-time]\ncommand = \"uvx\"\nargs = [\n  \"mcp-server-time\"\n]\n```\n\nNow:\n\n```toml\n[mcp_servers.mcp-server-time]\ncommand = \"uv\"\nargs = [\n  \"--directory\", \"/path/to/paranoid\",\n  \"run\",\n  \"--no-project\",\n  \"--offline\",\n  \"python\",\n  \"scripts/run_uv_tool.py\",\n  \"mcp-server-time\"\n]\n```\n\nIf the package name and executable name differ, add the package name but run the executable name.\nFor example, add `httpie==3.2.4`, then run `http`:\n\n```shell\nuv --directory /path/to/paranoid run --no-project --offline python scripts/run_uv_tool.py http --version\n```\n\n`scripts/add_uv_cli.py` only accepts exact pins in the form `package==version`.\nThat is intentional. Allowing floating specs such as `package`, `\u003e=1.0`, or `@latest`\nwould defeat the point of this repository.\n\nThe repo-local `.uv-tools` directory is the runnable artifact. Copying `repo + .uv-tools`\nto a new path is enough to keep commands working. If you also copy `.uv-cache`, then the target\nenvironment can rebuild `.uv-tools` offline:\n\n```shell\nuv --directory /path/to/paranoid run --no-project --offline python scripts/sync_uv_tools.py --offline\n```\n\nThe vendored artifacts are platform and Python-version specific. This repo pins Python `3.13`\nvia `.python-version`, and expects the target environment to provide a compatible interpreter.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhellodword%2Fparanoid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhellodword%2Fparanoid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhellodword%2Fparanoid/lists"}