Skip to content

fix(agent-server): remove the unreachable /api/credentials/update endpoint (#2008) - #2014

Open
dolho wants to merge 1 commit into
devfrom
fix/2008-remove-dead-credentials-update
Open

fix(agent-server): remove the unreachable /api/credentials/update endpoint (#2008)#2014
dolho wants to merge 1 commit into
devfrom
fix/2008-remove-dead-credentials-update

Conversation

@dolho

@dolho dolho commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

POST /api/credentials/update had no callers. I re-verified the issue's claim across src/, docker/, scripts/, config/, the .claude submodule and the populated src/backend/enterprise submodule: the only hits are the definition itself and the files.py comment pointing at it.

Meanwhile its docstring said "called by the Trinity backend", routers/files.py named it as the sanctioned alternative to raw .mcp.json editing — with both direct-edit blocks resting on that one sentence — and architecture.md listed it as a live endpoint. The documented escape hatch for configuring MCP servers did not exist.

It was also the one path that would substitute a credential value into command: a whole-text str.replace over .mcp.json.template, with no validate_mcp_config anywhere on it. That is the RCE-by-config class #590 closed — inert only because nothing called it, while the security comment above actively invited someone to call it.

Decision: delete

This is the branch the issue anticipated ("if that one is fixed by rendering at creation in the backend, this endpoint should be deleted rather than revived"), reached by a slightly different route: #2007 / PR #2013 puts the .mcp.json.template renderer where the files actually are — in the container at startup, env-only, validated per server, refusing rather than blanking. Reviving this endpoint would mean a second renderer with weaker rules on the same file.

Deleted: the route, and its now-unused CredentialUpdateRequest model — a dangling model is how a deleted route quietly comes back.

References corrected to name paths that exist

File Was Now
agent_server/routers/files.py "the platform-internal /api/credentials/update flow" the template (#2007) + the validated POST /api/agents/{name}/credentials/inject (#598)
docs/memory/architecture.md listed as a live agent endpoint removed
docs/testing/API_TEST_REQUIREMENTS.md REQ-AS-CRED-001 removed
docs/diagrams/03-agent-container.md POST /api/credentials/update /api/credentials/inject
docs/diagrams/09-agent-lifecycle-states.md claimed inject_assigned_credentials posts there /api/credentials/inject — which is what credential_encryption.py:375 actually calls
docs/planning/TARGET_ARCHITECTURE.md:297 listed it under "keep" repointed

Left alone deliberately: docs/archive/**, docs/security-reports/**, and the 2026-06 meta-analysis — point-in-time records that were true when written. TARGET_ARCHITECTURE.md:315 also mentions it, in a historical sentence explaining why #1089 added a different endpoint in June; rewriting that would be rewriting the record rather than fixing a pointer.

Acceptance criteria

AC Status
Endpoint removed, or reachable and validated removed
files.py:181-186 describes a path that exists done
architecture.md:331 matches reality done
If retained: validated, ${...} in command refused n/a — not retained
A test that fails if ${VAR} can reach command through this path expressed as: the path is gone (AST-checked, not substring), its model is gone, the whole-text replace renderer is gone, and no live doc sends anyone back to it

Test plan

  • tests/unit/test_2008_dead_credentials_update.py — 7 tests; all 7 fail on dev and pass here (verified by stashing the change)
  • Route absence checked by AST, not substring — the corrected files.py comment and the test file itself both still contain the string, so a grep-shaped assertion would be self-defeating
  • 661 adjacent tests green (-k "credential or agent_server or reload_token or 1089 or files")

Merge order

⚠️ Merge after #2010 (issue #1999). That PR modifies update_credentials, which this PR deletes. If #2010 lands first, this branch needs a rebase whose conflict resolution is mechanically "keep the deletion" — the function is gone either way. Merging this first would silently drop #2010's sync_process_env wiring on that endpoint, so please keep the order.

Closes #2008

…point (#2008)

The endpoint had no callers anywhere — backend, MCP server, startup.sh,
frontend and the enterprise submodule all verified. Its docstring claimed the
backend called it; `routers/files.py` named it as the *sanctioned* alternative
to raw `.mcp.json` editing, with both direct-edit blocks resting on that one
sentence; and architecture.md listed it as a live agent endpoint. The
documented escape hatch for configuring MCP servers did not exist.

It was also the one path that would substitute a credential value into
`command` — a whole-text `str.replace` over `.mcp.json.template` with no
`validate_mcp_config` anywhere on it. That is the RCE-by-config class #590
closed, inert only because nothing called it, while the security comment above
invited someone to.

Deleted rather than revived, which is the branch the issue anticipated: #2007
put the `.mcp.json.template` renderer where the files actually are — in the
container at startup, `env`-only, validated per server. Reviving this would
have meant a second renderer with weaker rules.

The references it left behind are corrected to name paths that exist:
`files.py` now points at the template and at the validated
`POST /api/agents/{name}/credentials/inject`; architecture.md, the API test
requirements, and both diagrams drop or repoint it. Historical records
(`docs/archive/**`, `docs/security-reports/**`, the 2026-06 meta-analysis) are
left alone — they were true when written.

Closes #2008

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

⚠️ Nightly unit-suite check skipped — merge conflict against dev.

Resolve by running git merge dev locally and pushing the result. The next nightly run will re-test once the conflict is gone.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant