Skip to content

AUDIT-18 — Low / Deployment — Compose publishes Postgres and Redis with weak credentials #75

Closed

Description

@getdownandcode

Summary

Severity: Low / Deployment
Area: Deployment
Affected files: docker-compose.yml:9-11, :23-28
Suggested branch: chore/harden-compose-ports
Suggested PR title: chore(deploy): harden Postgres and Redis exposure in compose

This is finding AUDIT-18 of 18 from a consolidated audit of agentkit/. It is deliberately self-contained so it can be fixed on its own branch with its own PR.

Related findings: Related: AUDIT-01 (dedicated DB role), AUDIT-12 (compose settings).


AUDIT-18 — Low / Deployment — Compose publishes Postgres and Redis with weak credentials

File — docker-compose.yml:9-11 and :23-28

    environment:
      POSTGRES_USER: ${POSTGRES_USER:-postgres}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
      POSTGRES_DB: ${POSTGRES_DB:-agentkit}
    ports:
      - "5432:5432"
  redis:
    image: redis:7-alpine
    container_name: agentkit-redis
    restart: unless-stopped
    ports:
      - "6379:6379"

Why this is a bug

The database is published on the host with the default postgres/postgres credentials, and Redis is published with no authentication at all. Everything the system stores — run goals, final answers, session conversation history, rate-limit counters — is reachable by anything that can reach those host ports. This is the standard "works on a laptop, unsafe on a shared host / CI runner / VPS" exposure.

Pass cases

  • Postgres and Redis are not published to the host by default (or are published on 127.0.0.1 only), with a documented opt-in for host access.
  • Redis requires a password (requirepass) supplied via an environment variable, and REDIS_URL includes it.
  • The Postgres password is not the default postgres; a startup check fails closed on a placeholder/default credential.
  • docs/DEPLOY.md documents the hardened configuration and the "don't expose these ports" guidance.

Appendix — How the findings were reproduced

All reproductions were run against the current main with the project's virtualenv (Python 3.12+, pydantic 2.13.5, sqlalchemy 2.1.1, google-genai 2.25.0, openai 3.19.2).

# AUDIT-01 / AUDIT-02 — SQL validation bypasses
python -c "from agentkit.tools.builtin.sql_readonly import validate_sql_query, _apply_row_limit; \
  print(validate_sql_query(\"SELECT pg_read_file('/etc/passwd')\")); \
  print(_apply_row_limit('SELECT * FROM runs LIMIT ALL', 50))"

# AUDIT-04 — thought_signature persistence
python -c "from agentkit.llm.base import Message; from agentkit.tools.models import ToolCall; \
  print(Message(role='assistant', tool_calls=[ToolCall(id='1', name='t', arguments={}, \
  thought_signature=b'\xff\xfe\x00\x81')]).model_dump(mode='json'))"   # UnicodeDecodeError

# AUDIT-05 / AUDIT-06 — Gemini adapter (stubbed provider)
#   two parallel function_call parts  -> two 'user' contents, one function_response each,
#                                        FunctionResponse.id=None, provider ids discarded
#   Part(text='SECRET CHAIN OF THOUGHT', thought=True) -> LLMResponse.text == that text

# AUDIT-07 — blocked Gemini response
#   prompt_feedback.block_reason='SAFETY' + empty parts -> LLMResponse(text='', tool_calls=[])

# AUDIT-08 / AUDIT-09 — API behaviour with a failing store (FastAPI TestClient)
#   create_run raises  -> POST /runs => 200 {"status": "succeeded"}   (no DB row)
#   update_run raises  -> POST /runs => 200 {"status": "running"}      (stale forever)

# AUDIT-11 — truncation orphan
python -c "from agentkit.memory.redis_store import RedisMemoryStore; \
  print(RedisMemoryStore.truncate_messages(msgs, 4))"   # -> [system, tool(c1), assistant(c2), tool(c2)]

# AUDIT-13 — dropped $defs
python -c "from agentkit.tools.schema import create_tool_schema; \
  print(create_tool_schema(my_enum_tool)[0].parameters)"  # -> {'$ref': '#/$defs/Mode'} with no $defs

Baseline state: pytest → all tests pass (tests/real/* skipped without AGENTKIT_REAL_INFRA=1); ruff check ., ruff format --check ., mypy agentkit clean at the time of writing. Any fix for this issue must keep the suite green and add the regression tests listed under each item's pass cases.

Definition of done (per AGENTS.md)

  • New/updated unit and integration tests covering the pass cases above, all passing (pytest).
  • ruff check ., ruff format --check . and mypy agentkit clean.
  • Docstrings updated where behaviour changed; docs/PROGRESS.md updated (status, PR link, commit count, notes).
  • A new ADR in docs/DECISIONS.md if an architectural decision was made.
  • Branch pushed and PR opened (never commit directly to main).

Baseline at the time of writing: pytest is green on main (all tests pass; tests/real/* skipped unless AGENTKIT_REAL_INFRA=1).

Activity

  1. added
    bugSomething isn't working
    securitySecurity vulnerability or hardening item
    on Oct 20, 2026
  2. getdownandcode commented on Oct 20, 2026

    @getdownandcode
    OwnerAuthor

    Audit index (18 separate issues, fix one by one)

    ID Issue Severity
    AUDIT-01 #58 Critical
    AUDIT-02 #59 Critical
    AUDIT-03 #60 High
    AUDIT-04 #61 High
    AUDIT-05 #62 High
    AUDIT-06 #63 High/Medium
    AUDIT-07 #64 Medium-High
    AUDIT-08 #65 Medium-High
    AUDIT-09 #66 Medium-High
    AUDIT-10 #67 Medium-High
    AUDIT-11 #68 Medium
    AUDIT-12 #69 Medium
    AUDIT-13 #70 Medium
    AUDIT-14 #71 Medium
    AUDIT-15 #72 Medium
    AUDIT-16 #73 Medium
    AUDIT-17 #74 Low
    AUDIT-18 #75 Low/Deployment

    Each issue is self-contained: current code, reproduction, pass cases, suggested branch and PR title. Reference the relevant one with Fixes #NN in your PR.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecuritySecurity vulnerability or hardening item

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions