Skip to content

Safe-prefix cache treats REDACT and REVIEW as verified clean #116

Description

@chirag-gamer

Description

ScanCache.should_advance_prefix() returns True for Action.REDACT (when advance_prefix_on_redact=True, the default) and unconditionally for Action.REVIEW. A safe-prefix entry is documented and modeled as a verified-clean prefix (SafePrefixState docstring: "Verified-clean prefix"), but REDACT and REVIEW are non-ALLOW findings.

When the safe prefix advances after REDACT or REVIEW, a later append-only scan of the same document_id can scan only the tail/overlap window and return ALLOW, omitting the earlier flagged content from the resulting findings and redacted output.

Affected version/commit

  • unplug-ai==0.6.0 (PyPI latest)
  • dev branch at commit 7a8be76
  • Python 3.14.2, Windows 11

Violated invariant

A safe-prefix cache entry may be created only after Action.ALLOW.

SafePrefixState is described as "Verified-clean prefix" but is populated after REDACT/REVIEW results.

Minimal reproduction

Unit-level (should_advance_prefix):

from unplug.api.enums import Action
from unplug.core.runtime.cache import ScanCache

# REDACT advances with default config (should not)
assert ScanCache.should_advance_prefix(Action.REDACT, advance_on_redact=True) is True  # BUG

# REVIEW advances unconditionally (should not)
assert ScanCache.should_advance_prefix(Action.REVIEW, advance_on_redact=False) is True  # BUG

Cache-flow regression (Guard-level, using a controlled fake pipeline stub that returns REDACT):

  1. Scan part1 → REDACT result → safe prefix recorded for entire document
  2. Append benign text to same document_id
  3. Second scan starts after the cached prefix (suffix-only)
  4. Pipeline returns ALLOW for suffix → verdict downgraded from REDACT to ALLOW
  5. With cache disabled, the full-document scan returns REDACT

Result: Cached scan returns ALLOW, non-cached scan returns REDACT.

Expected vs actual behavior

Action Expected should_advance_prefix Actual
ALLOW True True
BLOCK False False
REDACT False True (when advance_on_redact=True)
REVIEW False True (always)
ABSTAIN False False

Scope/impact

  • Requires cache enabled (default: True)
  • Requires same document_id across scans (append-only pattern)
  • Requires scanner producing REDACT or REVIEW (not BLOCK) for the initial content
  • The 256-char overlap window from PR Fix safe-prefix cache boundary bypass #87 does not preserve a prior REDACT/REVIEW finding located outside that window

Distinction from #82/#87

Issue #82 / PR #87 fixed a different bypass: injection patterns split across the cache boundary. That fix added a 256-character overlap and source/policy-scoped keys. This issue is about non-ALLOW results being treated as verified-clean prefixes, which is orthogonal to the boundary-overlap fix.

Acceptance criteria

  • Only Action.ALLOW can advance the safe prefix
  • REDACT, REVIEW, BLOCK, and ABSTAIN do not create/update safe-prefix state
  • An append after REDACT/REVIEW full-scans (or matches the cache-disabled verdict)
  • ALLOW prefix overlap behavior remains covered
  • Regression tests pass

Related

  • sdk/src/unplug/core/runtime/cache.pyshould_advance_prefix() (line 146)
  • sdk/src/unplug/guard.py_run_input_with_cache() (line 596)
  • sdk/src/unplug/config/cache.pyCacheConfig.advance_prefix_on_redact (line 18)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions