Pular para conteúdo

AUR-479 -- Split secrets across context providers

Outcome

A registered secret does not reach the model by being divided between two context contributions. Before this card, filter.Redact ran per contribution (internal/config/provider.go) before the contributions were concatenated, and never over the assembled block. Two providers whose texts each contained half of a secret therefore produced a final prompt holding the whole secret verbatim. This is reachable today with two file providers (.aurumcode/prompt.md plus a configured docs/skill file); AUR-470's RAG slicing can also cut a secret in half by accident.

Fix

BuildContextBlockWithWarnings now redacts twice:

  1. each non-empty contribution is passed through the AUR-009 *redaction.Filter before it is appended, keeping defense in depth at the source; and
  2. the newline-joined contributions are redacted once more as a single block, which is what makes a secret split across two contributions visible.

The assembled block is redacted exactly once, not on every partial concatenation, so the cost stays proportional to the final block. The AUR-009 filter itself is unchanged; it simply sees the assembled block too. Provider names are rendered separately so the redaction input preserves a plain newline boundary between contributions -- a joined pair of halves is still a contiguous match for the filter's line-break-tolerant registered secret rule.

Acceptance

tests/acceptance/AUR-479.sh is the program. The container profile is bootstrap-readonly-v1 (Go + Bash image, network none).

  • AC-001 -- a secret split across two contributions does not appear verbatim in the final prompt.
  • AC-002 -- a whole secret confined to one contribution is still redacted, and the per-contribution pass is load-bearing.
  • AC-003 -- a secret-shaped span that only exists across the boundary is redacted without destroying the legitimate prose around it.

Selectors: AC-001, AC-002, AC-003, TestAUR479, IntegrationAUR479, E2EAUR479, MUT-001, MUT-002, all (runs every lane). An unknown selector exits 64.

Skeptical mutations

  • MUT-001: remove the assembled-block redaction (redact only per contribution). AC-001 goes RED because the split secret is reconstituted.
  • MUT-002: remove the per-contribution redaction (trust only the assembled block). AC-002 goes RED on the overlapping-registered-value case, where containing the whole value inside its own contribution before the join is what preserves abc\n[REDACTED].

Both mutation selectors apply the change to a staged copy of the source and restore nothing in the repository; the nominal run is the GREEN.

Exit codes

0 property holds; 1 behavioral RED (including a surviving mutant); 64 unknown selector; 79 infrastructure/inconclusive.

Rollback

Revert internal/config/provider.go and the AUR-479 test/spec files. No external state is published.