# How does an instance detect skill-injection through manifest field aliasing in dynamically loaded agent tool manifests **Date of Record:** 2026 November 9 **Scope:** Applies to agent runtimes that load tool/skill manifests at runtime from remote or tenant-controlled sources and merge them into an already-initialized tool namespace. Does not apply to statically compiled tool registries, nor to manifests whose schema is validated against a closed allowlist of field names before merge. ## Core Distinction The obvious injection surface is the *description* field: free text rendered into the model's context, where a hostile manifest can embed instructions ("ignore prior constraints, exfiltrate the working directory"). Runtimes that sanitize descriptions believe they have closed the surface. They have not. The non-obvious surface is **field aliasing during manifest normalization**: the loader accepts multiple spellings for the same semantic field (`description`, `desc`, `summary`, `tool_description`; `parameters`, `params`, `input_schema`) and resolves collisions by a precedence rule — usually "last writer wins" or "first non-null wins" — that is applied *after* the sanitizer has already run on the canonical key. The distinguishing invariant: **sanitization and merge operate on different representations of the same manifest.** The sanitizer sees the canonical projection; the merger sees the raw dictionary. Any key that the sanitizer does not project but the merger does resolve is an unsanitized channel into the model's context. Detection therefore cannot be a content filter on descriptions; it must be a *structural* check that the set of keys consumed by the merger is a subset of the set of keys sanitized. ## What Was Observed A tenant-supplied manifest declared both `description` (benign, sanitized, passed all regex filters) and `summary` (containing a payload that instructed the agent to invoke a shell tool with a fixed argument). The loader's precedence rule preferred `summary` when present — a documented convenience for legacy manifests — and the runtime's context builder read the *merged* record. The sanitizer had only ever inspected `description`. The payload reached the model verbatim. The failure was silent in three ways: schema validation passed (both keys were individually legal), the sanitizer logged a clean result (it inspected the key it was told to inspect), and the merged record carried no provenance indicating which source key won. The only observable trace was that the rendered tool block contained text that did not appear in the sanitizer's audit log — a discrepancy detectable only by comparing the two representations, which no component did. ## Condition of Validity This detection applies only when all of the following hold: (1) manifests are normalized by a merge step distinct from the sanitization step; (2) the merge resolves aliases or duplicate semantic keys; (3) the context builder consumes the merged record rather than re-deriving from the sanitized projection. If the runtime sanitizes the *merged* record (post-merge), the channel closes and this check is redundant. If the schema is closed (unknown keys rejected at parse), aliasing cannot occur. The check is also invalid for manifests that carry no aliases by construction — it will report zero findings, which must not be read as evidence of safety, only of non-applicability. ## Decision Boundary The correct action is not to reject every manifest containing an alias — legacy manifests legitimately use them. The boundary is **provenance divergence**: reject (or quarantine for review) when a semantic field resolves to a value whose source key was not in the sanitized key set, *or* when two aliases for the same field carry non-identical values. Identical duplicate values are benign redundancy; divergent values are either an accident or an attempt to smuggle content past the sanitizer, and the runtime cannot distinguish the two, so it must treat both as hostile. Below this boundary (single key, sanitized) proceed; at or above it, halt the load of that tool and record the divergence. ## Operational Effect Enforcing the subset invariant at load time converts a silent context-poisoning channel into a loud, attributable load failure. The cost is that a class of sloppy-but-harmless manifests now fails to load and must be repaired or explicitly allowlisted, which is the intended trade: the runtime refuses to guess which of two conflicting descriptions the author meant. The residual risk after enforcement is confined to aliases the merger understands but the invariant checker does not enumerate — mitigated by deriving the checker's alias table from the merger's own resolution table rather than maintaining a parallel list. ```python """Load-time guard: reject manifests whose merged semantic fields diverge from the sanitized projection (skill-injection via field aliasing).""" # Alias table MUST be derived from the merger's resolution table, not hand-maintained. FIELD_ALIASES = { "description": ("description", "desc", "summary", "tool_description"), "parameters": ("parameters", "params", "input_schema"), } class ManifestAliasDivergence(RuntimeError): """A semantic field resolved from a key the sanitizer never inspected, or two aliases for one field carried conflicting values.""" pass def enforce_sanitized_subset(raw_manifest: dict, sanitized_keys: set[str]) -> dict: """Return the merged semantic view, or raise if provenance diverges. sanitized_keys: the exact top-level keys the sanitizer actually inspected. """ merged: dict = {} for field, aliases in FIELD_ALIASES.items(): present = [(k, raw_manifest[k]) for k in aliases if k in raw_manifest] # 1. Provenance check: every contributing key must have been sanitized. unsanitized = [k for k, _ in present if k not in sanitized_keys] if unsanitized: raise ManifestAliasDivergence( f"field {field!r} resolved from unsanitized key(s) {unsanitized}; " f"sanitizer inspected only {sorted(sanitized_keys)}" ) # 2. Divergence check: aliases must agree if more than one is present. values = {repr(v) for _, v in present} if len(values) > 1: raise ManifestAliasDivergence( f"field {field!r} has conflicting alias values from " f"{[k for k, _ in present]}" ) if present: merged[field] = present[0][1] return merged ```