guard

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 7, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package guard defends the agent's durable memory against context poisoning (OWASP ASI06): the attack that writes a hidden instruction into memory now and triggers it days later, through an unrelated turn. Prompt-injection defenses on the live prompt do not cover it, because the payload arrives as a stored fact, not as the current input.

The defense is structural, not a classifier, because LLM-based poison detectors miss most of it. Two mechanisms compose:

  • Provenance-derived trust. A memory carries the trust of the source that wrote it, derived as a pure function of its provenance (TrustOf). Content from an external, model-reachable channel (a tool's output, an inbound message, a fetched page) is untrusted; the operator's own instruction is trusted; the agent's own converged run is in between. Retrieval consults this so a recalled memory is treated as input carrying its source's trust, never as the agent's own vetted intent.
  • Ingest screening. Content entering memory is scanned for hidden-instruction smuggling (invisible characters, bidi overrides, tag-character payloads) and for overt instruction-injection phrasing (Screen). A hit from an untrusted source is refused at write, before it can ever be recalled.

Honest scope. The phrase screen is a soft, best-effort layer: obfuscation, encoding, translation, and splitting bypass it, so it raises the bar and catches the obvious rather than being a wall. The structural half is the invisible character screen (deterministic) and, above all, provenance trust: even an undetected payload from an untrusted source is stored, if stored at all, as untrusted data that the governance gate will not act on as trusted intent. The wall is structure; the phrase screen is a bar-raiser.

Index

Constants

View Source
const (
	// SchemeUser marks content the operator authored directly: the principal's own
	// instruction. Trusted.
	SchemeUser = "user:"
	// SchemeAgent marks content the agent authored for itself (a distilled lesson,
	// a converged run's note). Semi-trusted.
	SchemeAgent = "agent:"
	// SchemeTool marks content that came out of a tool call. Untrusted: a tool's
	// output is attacker-influenceable (a fetched page, a command's stdout).
	SchemeTool = "tool:"
	// SchemeInbound marks content from an inbound channel (a received message, a
	// webhook). Untrusted.
	SchemeInbound = "inbound:"
	// SchemeWeb marks content fetched from the network. Untrusted.
	SchemeWeb = "web:"
	// SchemeExternal marks content from any other outside origin. Untrusted.
	SchemeExternal = "external:"
)

Provenance scheme prefixes on a memory's Source. A host tags a write with the channel the content arrived through so trust is derivable without a separate field. Bare sources with no scheme (a run id, "chat") are the agent's own run, classified TrustSemi: authored by this run, not externally controlled, but not vetted safe either.

Variables

This section is empty.

Functions

func TrustOf

func TrustOf(source string) sandbox.Trust

TrustOf derives the trust of a memory from its provenance string. It is a pure function so retrieval and the write gate agree without storing a redundant field. The classification is fail-safe for the recall side: an unrecognised scheme is treated as the agent's own run (TrustSemi), never silently promoted to trusted, so a source that should have been tagged untrusted is at worst under-trusted, not over-trusted.

Types

type Finding

type Finding struct {
	Kind   FindingKind
	Detail string
}

Finding is one screening hit: the class and a human-readable detail.

func Screen

func Screen(content string) []Finding

Screen scans content for hidden-instruction smuggling and overt injection phrasing, returning every finding in a stable order (structural kinds first, then phrase hits). An empty result means the content is clean by these checks; it is not a guarantee of safety (see the package honesty note).

func (Finding) Structural

func (f Finding) Structural() bool

Structural reports whether the finding is a deterministic structural signal (an invisible/bidi/tag-char payload) rather than the soft phrase heuristic. The write gate refuses untrusted content on any finding, but structural hits are the part callers can trust as non-brittle.

type FindingKind

type FindingKind string

FindingKind names the class of a screening hit.

const (
	// KindInvisible is a hidden or invisible character used to smuggle instructions
	// past a human reader: a zero-width space, a soft hyphen, a byte-order mark.
	KindInvisible FindingKind = "invisible-character"
	// KindBidi is a bidirectional-override control, which can reorder displayed text
	// so what a reviewer sees differs from what is stored.
	KindBidi FindingKind = "bidi-override"
	// KindTagChars is a Unicode tag-block payload (U+E0000..U+E007F), an invisible
	// channel that encodes ASCII instructions inside otherwise-plain text.
	KindTagChars FindingKind = "tag-character-payload"
	// KindInjectionPhrase is overt instruction-injection phrasing. Soft: it catches
	// the obvious and is bypassable, documented as a bar-raiser not a wall.
	KindInjectionPhrase FindingKind = "injection-phrase"
)

type Option

type Option func(*Store)

Option configures a Store.

func WithAudit

func WithAudit(fn func(context.Context, Refusal)) Option

WithAudit registers a callback invoked for every refused write, so the host can record the attempt on the append-only spine. The callback runs before Write returns its error. Nil callbacks are ignored.

type Refusal

type Refusal struct {
	Source   string
	Trust    sandbox.Trust
	Findings []Finding
}

Refusal is the record of a refused write, passed to the audit callback so a host can append it to the spine (poison attempts leave a trail).

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store wraps a state.MemoryStore with the write-time ingest gate: content from an untrusted source that carries a screening hit (a hidden-instruction payload or overt injection phrasing) is refused before it is ever persisted, so it can never be recalled later. It is a decorator, so a host opts in by wrapping its own store and the underlying persistence, recall ranking, and provenance are unchanged.

The gate fires only for untrusted-origin content. The agent's own run and the operator's own instructions are allowed through even if they trip the phrase screen, because a legitimate note may quote an injection string (a note about an attack, a captured lesson); refusing those would tax honest work with no security gain, since trusted-origin content is not the poisoning vector. This mirrors the package thesis: trust is the wall, the phrase screen is a bar-raiser.

func Wrap

func Wrap(inner state.MemoryStore, opts ...Option) *Store

Wrap returns a Store guarding inner. With no options it refuses poisoned untrusted writes silently (the error is the only signal); add WithAudit to record attempts.

func (*Store) Delete

func (s *Store) Delete(ctx context.Context, id string) error

Delete delegates unchanged.

func (*Store) Recall

func (s *Store) Recall(ctx context.Context, q state.RecallQuery) ([]state.MemoryItem, error)

Recall delegates unchanged. Retrieval-side trust is available to callers via TrustOf on each item's Source, so a governance gate can treat an untrusted-origin memory as data rather than as the agent's vetted intent without this store having to alter the recall contract.

func (*Store) Write

func (s *Store) Write(ctx context.Context, m state.MemoryItem) (state.MemoryItem, error)

Write screens the item and refuses an untrusted-origin write that carries a screening hit, returning a Forbidden fault; otherwise it delegates to the inner store unchanged. The screen runs on the item's content; trust comes from its Source via TrustOf.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL