Repository navigation
Description
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.1only), with a documented opt-in for host access. - Redis requires a password (
requirepass) supplied via an environment variable, andREDIS_URLincludes it. - The Postgres password is not the default
postgres; a startup check fails closed on a placeholder/default credential. -
docs/DEPLOY.mddocuments 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 .andmypy agentkitclean. - Docstrings updated where behaviour changed;
docs/PROGRESS.mdupdated (status, PR link, commit count, notes). - A new ADR in
docs/DECISIONS.mdif 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
getdownandcode commentedon Oct 20, 2026
Audit index (18 separate issues, fix one by one)
Each issue is self-contained: current code, reproduction, pass cases, suggested branch and PR title. Reference the relevant one with
Fixes #NNin your PR.