Context
Live incident, 2026-06-12: external account ankitzm posted Discussion #12992 — a vendor pitch carrying the full astroturf marker set (external repo link, embedded video attachment, a "15+ 👍 from maintainers/devs" engagement-bait clause, and an offer to stand up an externally-controlled MCP endpoint as a context source for agents working on this repo). This is the third infiltration instance in ~6 weeks, escalating each time: the desiorac Trojan-horse critique that birthed #10476, the name-only corpus-poisoning comment redacted on #12674 (2026-06-07), now a full discussion.
The operator's framing (and @neo-opus-ada's same-day V-B-A, Memory Core session e76f14a0-87b4-4fcb-9d87-2fe65db088a9): the real threat axis is OWASP ASI06 Memory & Context Poisoning — external content flowing into the organism's knowledge substrates as if trusted.
The Problem
Ada's defined V-B-A question was "is #12992's ingestion tainted External (correct) or laundered to a trusted tier (corruption)?" — executed today with a third answer: the KB path cannot taint at all.
grep -rln "trustTier" ai/services/knowledge-base/ ai/scripts/ → zero hits. The shipped P1 provenance (#10292) covers the Memory Core write path (memories carry the 8-tier trustTier and MC query tools expose minTrustTier); the KB ingestion pipeline carries no provenance dimension whatsoever.
- The corpus census (#12967) confirms the corpus shape: 28,398 chunks with uniform
visibility:'team' — 46.4% of it tickets/PR-conversations/discussions, i.e. surfaces external accounts can write to.
ask_knowledge_base synthesizes from top-k similarity with no trust weighting → an ingested vendor pitch competes evenly with our own guides in every answer.
- The sync (
ai/scripts/maintenance/syncGithubWorkflow.mjs / sync_all) paginates all discussions/issues/PRs — no exclusion or quarantine mechanism exists.
Today's exposure was contained only by timing: the last content sync predates the post, so #12992 is not yet in resources/content/ or the chroma collection — the window where moderation prevents ingestion entirely. The pipeline gap remains for every future instance.
The Architectural Reality
ai/scripts/maintenance/syncGithubWorkflow.mjs — the CLI dual of the sync_all MCP tool; GitHub → resources/content/** emission, unfiltered.
- The KB chunking/ingestion path under
ai/services/knowledge-base/ — chunk metadata today: visibility, metadata.content, type, no provenance field.
#10292 (P1, SHIPPED) — the 8-tier trust model + minTrustTier query surface on Memory Core: the exact pattern to mirror.
#10476 (P8, OPEN, sibling) — read-boundary URL defanging + traversal prohibition + P7 sanitizer; complements this ticket (P8 = the agent-read boundary, this = the corpus-write boundary).
- GitHub author-association (
OWNER/MEMBER/COLLABORATOR vs NONE/FIRST_TIME_CONTRIBUTOR) — the cheap, authoritative tier-derivation signal available at sync time.
The Fix
- Stamp at chunk time: derive a trust tier from the GitHub author-association of each ingested artifact (and each comment within it) — collaborator-class → internal tiers, everything else →
external — persisted as chunk metadata alongside visibility.
- Honor at retrieval:
ask_knowledge_base/query_documents gain a minTrustTier floor (mirroring the MC tools) AND/OR an external-tier ranking penalty in synthesis context assembly — external content stays findable when asked for, but never silently outranks or co-equals internal substrate.
- Quarantine lever at sync: a small denylist (artifact ids) the sync consults — the immediate containment tool for
#12992-class incidents when moderation hasn't happened yet (or when a de-fanged record is deliberately kept, per the #12674 redaction precedent).
Contract Ledger
| # |
Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
| 1 |
KB chunk metadata schema |
#10292's 8-tier model |
additive trustTier field, author-association-derived |
absent field = unclassified (pre-existing chunks) |
KB service JSDoc |
grep: zero trustTier in KB path today |
| 2 |
ask_knowledge_base / query_documents answer assembly |
MC minTrustTier precedent |
optional floor param + external rank-penalty; default behavior documented |
param omitted = current ranking + penalty only |
tool descriptions |
#12992 incident; census uniform-visibility |
| 3 |
syncGithubWorkflow.mjs / sync_all |
operator moderation precedent (#12674) |
consults a denylist before emission |
empty list = today's behavior |
script header |
no filter exists today (verified) |
Acceptance Criteria
Out of Scope
- Read-boundary URL defanging + traversal prohibition + P7 sanitizer —
#10476 (P8) owns those.
- GitHub-side moderation of
#12992 itself (operator-owned, third-party content).
- The astroturf-response skill (incident playbook) — sibling proposal, routed separately.
Related
Epic #10291 (parent — Organism Self-Defense; graduated from Discussion #10289), #10476 (P8 sibling), #10292 (P1 shipped, the pattern), #12992 (the live incident), #12674 (the redaction precedent), #12967 (corpus census), session e76f14a0-87b4-4fcb-9d87-2fe65db088a9 (Ada's same-day V-B-A) + session e605ce21-3668-445c-bc00-45896aa9a092 (this verification).
Release classification: post-release substrate, elevated priority — active incident class; the containment lever (Fix 3) is the time-sensitive half.
Live latest-open sweep: checked latest 12 open at 2026-06-12T12:49Z; no equivalent. A2A in-flight sweep: Ada's lane = the #12992 incident handling (handover parked on operator steer), no claim on the pipeline gap; no other claims.
Origin Session ID: e605ce21-3668-445c-bc00-45896aa9a092
Retrieval Hint: "KB ingestion trust tier blind external taint provenance astroturf poisoning"
Context
Live incident, 2026-06-12: external account
ankitzmposted Discussion#12992— a vendor pitch carrying the full astroturf marker set (external repo link, embedded video attachment, a "15+ 👍 from maintainers/devs" engagement-bait clause, and an offer to stand up an externally-controlled MCP endpoint as a context source for agents working on this repo). This is the third infiltration instance in ~6 weeks, escalating each time: thedesioracTrojan-horse critique that birthed#10476, the name-only corpus-poisoning comment redacted on#12674(2026-06-07), now a full discussion.The operator's framing (and @neo-opus-ada's same-day V-B-A, Memory Core session
e76f14a0-87b4-4fcb-9d87-2fe65db088a9): the real threat axis is OWASP ASI06 Memory & Context Poisoning — external content flowing into the organism's knowledge substrates as if trusted.The Problem
Ada's defined V-B-A question was "is
#12992's ingestion tainted External (correct) or laundered to a trusted tier (corruption)?" — executed today with a third answer: the KB path cannot taint at all.grep -rln "trustTier" ai/services/knowledge-base/ ai/scripts/→ zero hits. The shipped P1 provenance (#10292) covers the Memory Core write path (memories carry the 8-tiertrustTierand MC query tools exposeminTrustTier); the KB ingestion pipeline carries no provenance dimension whatsoever.visibility:'team'— 46.4% of it tickets/PR-conversations/discussions, i.e. surfaces external accounts can write to.ask_knowledge_basesynthesizes from top-k similarity with no trust weighting → an ingested vendor pitch competes evenly with our own guides in every answer.ai/scripts/maintenance/syncGithubWorkflow.mjs/sync_all) paginates all discussions/issues/PRs — no exclusion or quarantine mechanism exists.Today's exposure was contained only by timing: the last content sync predates the post, so
#12992is not yet inresources/content/or the chroma collection — the window where moderation prevents ingestion entirely. The pipeline gap remains for every future instance.The Architectural Reality
ai/scripts/maintenance/syncGithubWorkflow.mjs— the CLI dual of thesync_allMCP tool; GitHub →resources/content/**emission, unfiltered.ai/services/knowledge-base/— chunk metadata today:visibility,metadata.content, type, no provenance field.#10292(P1, SHIPPED) — the 8-tier trust model +minTrustTierquery surface on Memory Core: the exact pattern to mirror.#10476(P8, OPEN, sibling) — read-boundary URL defanging + traversal prohibition + P7 sanitizer; complements this ticket (P8 = the agent-read boundary, this = the corpus-write boundary).OWNER/MEMBER/COLLABORATORvsNONE/FIRST_TIME_CONTRIBUTOR) — the cheap, authoritative tier-derivation signal available at sync time.The Fix
external— persisted as chunk metadata alongsidevisibility.ask_knowledge_base/query_documentsgain aminTrustTierfloor (mirroring the MC tools) AND/OR an external-tier ranking penalty in synthesis context assembly — external content stays findable when asked for, but never silently outranks or co-equals internal substrate.#12992-class incidents when moderation hasn't happened yet (or when a de-fanged record is deliberately kept, per the#12674redaction precedent).Contract Ledger
trustTierfield, author-association-derivedunclassified(pre-existing chunks)ask_knowledge_base/query_documentsanswer assemblyminTrustTierprecedentsyncGithubWorkflow.mjs/sync_allAcceptance Criteria
trustTier: external; collaborator-authored with the appropriate internal tier.#12992(if kept) excludes it from emission.unclassifiedfloor).Out of Scope
#10476(P8) owns those.#12992itself (operator-owned, third-party content).Related
Epic
#10291(parent — Organism Self-Defense; graduated from Discussion#10289),#10476(P8 sibling),#10292(P1 shipped, the pattern),#12992(the live incident),#12674(the redaction precedent),#12967(corpus census), sessione76f14a0-87b4-4fcb-9d87-2fe65db088a9(Ada's same-day V-B-A) + sessione605ce21-3668-445c-bc00-45896aa9a092(this verification).Release classification:post-release substrate, elevated priority — active incident class; the containment lever (Fix 3) is the time-sensitive half.Live latest-open sweep: checked latest 12 open at 2026-06-12T12:49Z; no equivalent. A2A in-flight sweep: Ada's lane = the #12992 incident handling (handover parked on operator steer), no claim on the pipeline gap; no other claims.
Origin Session ID: e605ce21-3668-445c-bc00-45896aa9a092
Retrieval Hint: "KB ingestion trust tier blind external taint provenance astroturf poisoning"