Environment Variable Leak Conversation Audit
Alignment status: review. This report audits local Claude and Codex conversation history, related task records, and current repo artifacts to determine what workflow issues led to environment variables or credential-bearing values being exposed. No resolved secret values are reproduced here.
Table Of Contents
Verdict
Main finding: The environment-variable leak was not caused by one isolated accidental paste. It came from a workflow design that normalized direct database credentials as an operational prerequisite, then allowed validation output and documentation handoffs to carry resolved values into tracked files and conversations.
Confirmed incident: the repo records a tracked-file leak in docs/kanban-test-results.md. The cleanup commit is 72fdc1ad (fix: remove leaked Neon database credential from tracked file). I did not open the removed patch hunk because it could reveal the deleted credential. Supporting task history says the credential was scrubbed and the Neon password was rotated.
Primary cause: legacy kanban skills used a standalone direct-DB script that required POKETOWORK_DATABASE_URL for normal work. That design made a production database URL part of the agent workflow instead of keeping it behind an authenticated app-layer API. Later Phase 10 work migrated standard usage to poketo kanban and made the direct script fallback/admin-only.
Scope And Method
The scan included compact user histories and richer conversation transcripts because environment-variable exposure can happen in assistant messages, tool outputs, or generated docs rather than only in user prompts.
| Source | Records | Purpose | Notes |
|---|---|---|---|
~/.claude/history.jsonl | 10,061 lines | Compact Claude user prompts and pasted visible content | Used for user correction history and prompt themes. |
~/.claude/projects/**/*.jsonl | 678 files | Claude user, assistant, and tool-result transcripts | Skipped system, file snapshots, attachments, and title records for leak-pattern counts. |
~/.codex/history.jsonl | 1,988 lines | Compact Codex prompt history | Used for user prompt context. |
~/.codex/sessions/**/*.jsonl | 712 rollout files, 203,470 rollout lines, 735 metadata records | Codex rich session records, including assistant messages and tool outputs | Skipped identifiable system/developer/reasoning records. |
| Repo artifacts | Focused files and commits | Durable corroboration | Read task history, phase docs, current safe docs, and commit metadata. Did not print deleted credential patch content. |
The first-pass scanner found 13,314 raw secret-like candidates and 2,890 deduplicated candidate matches. Many were false positives such as code variables named key, token, or animation state. The report therefore relies on confirmed repo records, high-confidence credential shapes, and correction history rather than treating every candidate as a leak.
Confirmed Leak Chain
| Step | Evidence | What Happened | Cause |
|---|---|---|---|
| Direct-DB workflow became standard | Archived poketo-headless-auth-migration.md says active Claude/Codex kanban skills required POKETOWORK_DATABASE_URL and that operations went straight to Neon. |
Agent kanban work depended on a raw database URL rather than a scoped API token or app-layer auth. | Credential-bearing infrastructure was embedded in normal agent operations. |
| Validation docs used resolved setup syntax | docs/kanban-test-results.md tracked kanban validation and originally included an env export line. Current safe version now uses poketo auth login and POKETO_API_KEY. |
A resolved Neon credential was written to a tracked result file during validation documentation. | Documentation treated a live setup command as content to preserve, without a placeholder-only rule or secret scan gate. |
| Expert review caught it | tasks/history.md records: "Critical: database credential in tracked docs/kanban-test-results.md". |
The leak was identified as a critical review finding. | Detection happened after the file was tracked, not before staging or committing. |
| Credential was removed | Commit 72fdc1ad is titled fix: remove leaked Neon database credential from tracked file and changed docs/kanban-test-results.md. |
The tracked file was scrubbed. The removed patch content was intentionally not inspected in this audit. | Cleanup fixed the artifact but did not by itself remove the workflow that made the credential necessary. |
| Credential was rotated | docs/phases/phase-5.md says "Credential scrubbed from docs/kanban-test-results.md, Neon password rotated". |
The known exposed database password was rotated after removal. | Rotation was the right incident response, but prevention needed workflow changes. |
| Workflow was redesigned | tasks/phases/phase-10.md says no kanban skill requires POKETOWORK_DATABASE_URL for standard usage and that standard workflows use poketo kanban. |
Direct DB access was demoted to legacy fallback/admin-only. | The durable prevention was replacing raw DB access with an authenticated app-layer route. |
Recurring Patterns
| Pattern | Observed Count | What The Count Means | Interpretation |
|---|---|---|---|
POKETOWORK_DATABASE_URL mentions | 488 transcript records | Mostly April 2026 Codex session records, many repeated tool outputs or post-fix discussions. | The variable was a recurring workflow dependency and cleanup topic, not an incidental one-time string. |
| Candidate env assignments | 2,124 deduplicated candidates | Regex candidates across all transcripts; includes false positives and public/non-secret values. | Agent sessions often contain env-shaped syntax, so output channels need redaction rather than relying on manual judgment. |
| Candidate sensitive fields | 715 deduplicated candidates | Fields named token, secret, database URL, connection string, and related variants. | Many are examples, placeholders, or code identifiers, but the volume shows that secret-shaped text is common enough to require automated policy. |
| URL credentials | 44 deduplicated candidates | Connection strings or URLs with user/password structure; some are local/test placeholders. | This is the highest-risk shape and should be blocked from docs, final answers, and commits unless redacted. |
| Token prefix matches | 7 deduplicated candidates | Provider-token-shaped strings found in transcripts. | Low count but high severity; final answers and tracked files should fail closed on these patterns. |
| User warnings/corrections | At least 5 distinct compact prompts | Examples include "do not look at the .env.local value" and "did you read the secret? Did you leak them?" | The user had already established the boundary; the workflow needed to enforce it automatically. |
Evidence Matrix
| Claim | Evidence | Inference | Confidence | Decision Impact |
|---|---|---|---|---|
| The main confirmed leak was a tracked Neon database credential. | tasks/history.md names a critical database credential in docs/kanban-test-results.md; commit 72fdc1ad removed a leaked Neon credential from that tracked file. |
Repo history explicitly labels the incident and its cleanup boundary. | High | Do not treat this as only a chat-output problem. The prevention gate must cover docs and commits. |
| The leak was enabled by a direct-DB kanban architecture. | Archived headless-auth spec says standard kanban usage required POKETOWORK_DATABASE_URL, direct Neon writes, and local session config. |
When a raw production DB URL is a normal prerequisite, agents will naturally read, export, test, document, and mention it. | High | Keep direct DB scripts fallback/admin-only and make app-layer auth the default. |
| Documentation and final handoff paths lacked an enforced placeholder rule. | tasks/lessons.md now says to write placeholder syntax and never paste current secret values from env files, shell context, command output, or model-visible context. |
The lesson exists because a prior handoff copied a resolved value. It also names the missing behavior. | High | Implement a pre-commit/pre-final-answer secret scan for docs and handoffs. |
| Tool outputs were a recurring leak vector. | Transcript scan found high-confidence credential shapes mostly in function_call_output and related tool-output records; rg, installer, and validation outputs repeatedly surfaced env requirements. |
Even if a command is meant to validate, its output can become model-visible and then be copied into docs or final answers. | Medium-high | Run secret-aware wrappers or output filters around commands that can print env, dotenv, config, or connection strings. |
| The user had repeatedly clarified the secret boundary. | Compact history includes prompts on 2026-03-02, 2026-04-01, 2026-04-14, and 2026-05-03 warning not to inspect or leak env values. | The issue was not lack of user intent. It was lack of reliable enforcement under normal agent operations. | High | Standing instructions should be backed by automation, not memory. |
| Current standard kanban workflow is materially safer. | tasks/phases/phase-10.md says standard workflows use poketo kanban with poketo auth login or POKETO_API_KEY, and no kanban skill requires the DB URL for standard usage. |
The key architecture fix has already happened for the primary known incident path. | High | Remaining work should focus on regression gates and fallback/admin-only boundaries. |
Root Causes
1. Production credential as routine workflow input
The kanban workflow originally required POKETOWORK_DATABASE_URL for standard operations. That put a raw database credential into the same operational lane as board discovery, card creation, validation, and test documentation.
2. Direct script bypassed app-layer auth and scoping
The archived migration brief says the standalone script executed direct SQL via Neon and bypassed application permission checks. This made the DB URL both powerful and operationally necessary.
3. Validation artifacts copied live setup state
The validation results doc preserved how tests were run. Before cleanup, that included a resolved credential-bearing export instead of a placeholder. This is the direct tracked-file leak path.
4. Secret scanning happened after review, not before commit
The credential was caught by expert review and then removed. The evidence implies there was no reliable gate at the moment docs were written, staged, or committed.
5. Tool output was treated as safe source material
Session transcripts show commands like installers, search, test runners, and validation outputs repeatedly printing env names, setup instructions, and sometimes credential-shaped values. Tool output then became model-visible source material for summaries and docs.
6. User warnings were not converted into automatic controls
History contains direct user warnings about not reading .env.local values and not leaking secrets. Those warnings reduced ambiguity but did not create mechanical checks. The later lesson fixed the instruction layer; the remaining gap is enforcement.
Sanitized Examples
2026-03-02 user prompt: "woah, you should not be looking at environment variables, they're secret right"
2026-04-01 user prompt: "ok I've added the env vars. Remember they're meant to be secret, do not look at them."
2026-04-06 user prompt: "can you identify how many times secrets were leaked and what we can do to prevent this from happening in the future? Can you also inventory what needs to be rotated?"
2026-04-14 user prompt: "will the test leak any env vars?"
2026-05-03 user prompt: "did you read the secret? Did you leak them?"
Representative redacted leak shape found in history: DATABASE_URL=<redacted postgres URL with credentials>. Representative safe replacement now present in current docs: poketo auth login or export POKETO_API_KEY="pk_...". The report intentionally does not include old resolved values.
Recommendations
| Rank | Pattern | Recommendation Type | Suggested Owner Surface | Validation Expectation |
|---|---|---|---|---|
| 1 | Docs and handoffs can preserve resolved env values | Skill + standing instruction | ship, ship-end, exec, report-producing skills | Layer1 fixture fails when docs/final handoffs include URL credentials, provider tokens, or sensitive env assignments. |
| 2 | Tool output can become source material without redaction | Plugin/integration or wrapper | Command execution and transcript summarization paths | Focused smoke test runs a command emitting fake secrets and proves outputs are redacted before documentation or final answer use. |
| 3 | Fallback direct-DB scripts can drift back into default docs | Standing convention + regression test | poketowork-kanban pack | Test rejects active standard-use docs requiring POKETOWORK_DATABASE_URL or kanban.mjs. |
| 4 | Agents may inspect .env* when user only asked for required variable names | Skill behavior rule | All coding/debug/review skills | Fixture distinguishes reading .env.example from reading .env.local; real env reads require explicit approval and value redaction. |
| 5 | Secret detection is currently scattered across lessons and human review | Repository hygiene command | Validation scripts | Secret scan checks current tracked files plus staged diff before commit; deleted historical hunk inspection is avoided unless intentionally authorized. |
Recommended next command: $targeted-skill-builder secret-safe documentation and tool-output gate for ship/exec workflows. Likely owner surface: shared execution/shipping contracts plus validation scripts. Minimum validation: a layer1 contract test with fake secret fixtures and a focused command-output redaction smoke.
Highest Impact Automations
- Secret-safe docs/handoff gate. Before any report, test result, task doc, final answer, or commit, scan for URL credentials, sensitive env assignments, provider token prefixes, and password-like query params.
- Tool-output redaction filter. Treat command output as untrusted when it contains env/config/dotenv text. Redact before summarizing or writing it.
- Env-file access boundary. Default to
.env.example, schema validation code, or variable names. Reading live.envfiles should require explicit user intent and should never print values. - Direct-DB fallback quarantine. Keep
kanban.mjsfallback/admin-only, with active docs and skills usingpoketo kanban. - Historical leak handling rule. When a prior commit removed a credential, report commit/path metadata only. Do not run patch-view commands that could reprint deleted secret content unless the user explicitly asks for forensic history rewriting.
Assumptions And Gaps
Assumption: Conversation history and repo artifacts are sufficient to identify the main leak path. This is strong because task history and commit metadata explicitly name the tracked credential leak.
Gap: I did not inspect the deleted patch hunk from commit 72fdc1ad, so I cannot classify the exact credential string beyond what repo records state: a Neon database credential in docs/kanban-test-results.md. That omission is intentional to avoid re-disclosure.
Gap: The broad scanner counted candidate secret-shaped matches, not confirmed secrets. Counts should be used to prioritize guardrails, not to infer exact rotation inventory.
Residual risk: Git history may still contain the old value unless history was rewritten outside the observed artifacts. The evidence only proves scrub + rotation, not complete historical erasure.
Review Gates
Evidence Coverage
Is the evidence sufficient to treat the tracked kanban docs leak as the primary confirmed incident?
Assumptions And Confidence
How should this report treat candidate secret-like counts?
Recommended Path
Which remediation should be prioritized?
Proposed File Changes
Are the durable artifacts for this audit acceptable?
Post-Approval Route
After approval, how should this report route next work?
Compile Feedback And Answers
Use feedback YAML for concerns before answering all gates. Use final answers only when the report is ready for agent review.