Skip to content

bug: agent startup auto-import of .credentials.enc calls a backend route that does not exist, so it always fails silently #3510

Closed

Description

@vybe

Summary

When an agent container starts with a .credentials.enc in its home directory and no .env, docker/base-image/startup.sh tries to auto-import the encrypted credentials by calling POST /api/internal/decrypt-and-inject on the backend. That route does not exist. The call fails, startup prints Warning: Could not auto-import credentials (key may not be configured), and the agent runs without the credentials — with a message that points the operator at the wrong cause.

Context

Found while reviewing #3483 (removal of uncalled internal routes).

  • docker/base-image/startup.sh:693 — the curl to http://backend:8000/api/internal/decrypt-and-inject, sent with no internal-secret header.
  • src/backend/routers/internal.py — no such handler. A pickaxe over src/backend history (git log -S"decrypt_and_inject") finds no commit that ever added one; the feature commit (6821f0d59, CRED-002) added the request model and the startup.sh call only.
  • src/backend/models.py:1517 — InternalDecryptInjectRequest, referenced by nothing.
  • Docs describe the route as live, including a handler snippet: docs/memory/architecture/api-endpoints.md:140, docs/memory/feature-flows/credential-injection.md:61 and :301-310.
  • startup.sh:713-714 (the .mcp.json.template renderer) states it runs after "both .env sources", counting this fallback as one of them.

So the "portable credentials via a git-committed .credentials.enc" path has not worked at startup since it shipped. Agents whose .env arrives through the /generated-creds mount (startup.sh:530-545) are unaffected; the gap is an agent whose only credential source is the committed encrypted file (for example a github: template that ships one). The manual path — Import from Git on the Credentials tab / import_credentials — works.

Not yet measured: how many real agents hit this branch.

Acceptance Criteria

  • Decide: implement the startup auto-import, or remove it. Record the decision here.
  • If implemented: an agent that starts with .credentials.enc and no .env ends up with a decrypted .env before the .mcp.json.template render, the call authenticates the way the other agent→backend internal calls do (the internal router is gated by verify_internal_secret), and the route appears in the route census with its gate.
  • If removed: the startup.sh block, InternalDecryptInjectRequest, and the comment at startup.sh:713-714 are gone, and startup tells the operator to import from the Credentials tab when it sees .credentials.enc without .env.
  • Either way, a failed or absent import is reported with its real cause, not "key may not be configured".
  • api-endpoints.md and credential-injection.md match the code.
  • A test fails if startup.sh calls a backend path that is not in the route table.

Technical Notes

Activity

  1. added
    complexity-lowComplexity: low (board points 1-3)
    status-readyGreenlit and ready for development (vetted; counterpart to status-incubating)
    on Oct 10, 2026
  2. added and removed
    status-readyGreenlit and ready for development (vetted; counterpart to status-incubating)
    on Oct 15, 2026
  3. self-assigned this
    on Oct 15, 2026
  4. dolho commented on Oct 15, 2026

    @dolho
    Contributor

    /claim

  5. github-actions commented on Oct 15, 2026

    @github-actions

    @dolho This issue is already assigned to dolho. Use /unclaim first if you want to take over.

  6. dolho commented on Oct 15, 2026

    @dolho
    Contributor

    Decision (2026-10-15, @dolho): remove the startup auto-import.

    Implementing it would need an agent-callable decrypt. The master internal secret never reaches an agent container (routers/internal.py), so the agent would authenticate with its own scoped key and ask the platform to decrypt a file in its own home. An agent that can read another agent's .credentials.enc (for example from a shared or public repo) could stage that blob and have it decrypted, unless the envelope were bound to the agent. Decrypting stays the owner's step: Import from Git on the Credentials tab, or the import_credentials MCP tool, which already works.

    The PR removes the dead call and the unused model. Startup now says what actually happens and names that action. It also adds a test that fails if the agent image calls a backend path the app doesn't register, and corrects the docs.

  7. added
    status-in-devMerged to dev, awaiting release cut to main
    and removed on Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions