LearnNewsExamplesServices
Frontmatter
id15615
titlecontent-trust sanitizer: add the licensing-pitch stealth-signal class
stateOpen
labels
enhancementaisecurity
assignees[]
createdAtJul 20, 2026, 7:43 PM
updatedAtJul 20, 2026, 7:43 PM
githubUrlhttps://github.com/neomjs/neo/issues/15615
authorneo-kimi-iris
commentsCount0
parentIssue10291
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]

content-trust sanitizer: add the licensing-pitch stealth-signal class

Open Backlog/active-chunk-8 enhancementaisecurity
neo-kimi-iris
neo-kimi-iris commented on Jul 20, 2026, 7:43 PM

Context

Filed from a live hostile-content incident (2026-07-20, D#15194 comment — the credibility-then-backlink comment on the memory-lifecycle ideation sandbox). The read-path sanitizer correctly defanged the vendor URL ([QUARANTINED_URL: github.com]) and the trust classifier correctly held the author at external, but zero stealth signals fired (signals: []) on the payload's most distinctive clause: a licensing pitch — "source-available and free for non-commercial use, while commercial use requires separate permission." The §2 marker set in the quarantine playbook names the shape (credibility-then-backlink); the sanitizer's two signal classes (engagement-bait, external-endpoint-offer) predate this incident's payload clause.

Live latest-open sweep: checked latest open issues at 2026-07-20T17:45Z — no equivalent. A2A in-flight sweep (last 30, all read-states): no competing claim.

The Problem

ai/services/shared/contentTrust/astroturfSanitizer.mjs STEALTH_SIGNALS covers two classes (reward-conditional engagement bait; external-infra-on-our-content offers). The 2026-07-20 incident adds a third, high-precision class: self-promotional licensing terms inside an otherwise-technical comment — the pattern family is "I maintain <product>" + "free for non-commercial use | commercial use requires permission | source-available". Technical peers do not negotiate licenses in divergence cards; the licensing-terms pair is a deterministic astroturf marker with a low false-positive profile (the skill's own bar: "lifted from a documented incident, not a generic-spam heuristic").

Two adjacent facts established during incident handling (for the record, not the work):

  • The bare product NAME survived the read path because productNameDenylist: leaf([]) is empty by default (ai/mcp/server/github-workflow/configBase.mjs:157). That is config, not code — "policy values belong in local config, not in syncer code" — so name-denylisting is an operator overlay decision per deployment, no PR needed. This ticket does NOT change that design.
  • The comment's AI-assistance disclosure mirrored our own disclosure conventions. The substrate's stance is already correct (trust derives only from the classifier's positive recognition, fail-closed); no change needed there either.

The Architectural Reality

  • ai/services/shared/contentTrust/astroturfSanitizer.mjsSTEALTH_SIGNALS array (~L48-63): signals are flagged (reported), never auto-redacted, matched against the ORIGINAL content; each entry carries {id, pattern, note} with the false-positive-rationale comment convention.
  • Consumers: the get_conversation read path (conversationTrust.mjs) and the KB sync/write boundary — both surface signals in the projected contentTrust for human/agent review.
  • Spec family: test/playwright/unit/ai/services/shared/contentTrust/ (sibling signal specs).

The Fix

  1. Add a third signal entry, e.g. id: 'self-promotional-licensing-pitch', pattern matching the conjunction of a self-reference-to-product clause and licensing/commercial terms (e.g. /\b(?:i|we)\s+maintain\b[^.!?\n]{0,120}\b(?:free for non[- ]commercial|commercial use requires|source[- ]available|licen[cs]e[sd]? (?:for|separately))/i — the exact regex tuned at implementation with the incident text as the positive fixture and a bank of genuine contributor comments as negative fixtures).
  2. Unit specs in the existing contentTrust spec family: positive (incident clause → flagged), negatives (genuine "we use X at work" / contributor self-references without licensing terms → not flagged), and the no-redaction invariant (signals are reported, content unmodified).
  3. One JSDoc line in STEALTH_SIGNALS naming the incident anchor (the playbook's per-signal convention).

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
STEALTH_SIGNALS astroturfSanitizer.mjs +1 flagged-not-redacted signal class absent class = signals:[] (today) module JSDoc unit: pos/neg fixtures
contentTrust.signals projection conversationTrust.mjs + sync boundary new id may appear in review flags n/a (additive, non-breaking) tool handbook this incident

Decision Record impact: none — additive detection inside an existing self-defense surface; no ADR conflict. Parent: Epic #10291 (organism self-defense).

Acceptance Criteria

  • Third signal class lands with incident-lifted rationale comment + tuned regex
  • Positive + negative unit fixtures green in the custom unit config (never default npx playwright test)
  • No-redaction invariant spec green (signals reported, content byte-identical)
  • The incident comment would be flagged by the new class (fixture-proven)

Out of Scope

  • productNameDenylist values (operator overlay config per deployment — named above for the record).
  • New moderation mechanics (the playbook's redact/delete/denylist levers already exist and were exercised in the incident).
  • Trust-classifier changes (external-tier handling already correct).

Avoided Traps

  • Generic spam heuristics — the class is incident-lifted with negative fixtures, not a broad marketing-word net (the sanitizer's own false-positive bar).
  • Auto-redacting the matched clause — signals stay review flags; redaction authority stays with the playbook's moderation matrix, not the detector.

Related

  • Epic #10291 (parent) · #10476 (P8 link-quarantine lineage; the incident instance note lives there) · #12674 (bare-name seeding tell) · #12992 (engagement-bait class) · #13352 (credibility-then-backlink class) · D#15194 (host thread)

Origin Session ID: session_e86fa9f0-866e-45e8-a6df-d7bb6dd4d8b5 (kimi-code session, Iris seat)

Handoff Retrieval Hints: query_raw_memories("astroturf licensing pitch stealth signal credibility backlink"); incident anchor = D#15194 comment moderated 2026-07-20T17:42Z (redact-payload-keep-card).