Skip to content
FoundationMachines

False positives and Learnings

How Sebastion AI suppresses noisy findings — chat commands, AGENTS.md auto-detect, and operator overrides — with the security properties that keep suppression safe.

The #1 reason teams mute security bots is false positives. Sebastion treats false-positive suppression as a first-class feature so you can silence a noisy finding once, on the right path, and trust it stays silenced — without giving an attacker a primitive to silence real ones. This page covers what a Learning is, the three ways one gets created, and the security properties that keep the whole system defensible.

What a Learning is

A Learning is a per-installation suppression rule keyed by (rule_id, file_glob). When the audit pipeline produces a finding, Sebastion checks the active Learnings for your installation and drops any finding whose rule and path match.

interface Learning {
  rule_id: string;        // e.g. "py.print-statement", "osv.GHSA-…"
  file_glob: string;      // e.g. "bin/**", "lib/legacy/*.go"
  source: 'chat' | 'auto_detect' | 'manual';
  count: number;          // findings suppressed so far
  created_at: string;     // ISO timestamp
  last_seen_at: string | null;
}

You can view your installation's active Learnings on the dashboard at app.foundationmachines.ai/sebastion/learnings.

How Learnings get created

There are three entry points. All three write to the same per-installation store and all three are subject to the same security gates below.

1. @sebastionai ignore chat command

The primary path. Reply directly on one of Sebastion's inline review comments with any of these synonyms:

@sebastionai ignore
@sebastionai suppress
@sebastionai mute
@sebastionai silence

Optionally, add a free-text reason after the keyword — it's recorded in your tenant audit log:

@sebastionai ignore false positive in test fixtures
@sebastionai suppress legacy code we're rewriting
@sebastionai mute training data not real

Sebastion writes a Learning for that finding's (rule_id, file_path) and the next audit on that file skips that rule. Sebastion replies on the same thread to confirm.

The reason (if any) is recorded in the tenant event log only — not in the Learnings record itself. This preserves the "no free text in the suppression store" data-minimisation property (see below). Operators and support can recover the reason via the admin portal.

For this to take effect:

  • The commenter must have write permission on the repo. Bot accounts (GitHub App or type: Bot user) cannot create Learnings.
  • The reply must be on an inline Sebastion finding comment, not a top-level PR comment. Top-level comments can't tell which finding you mean — Sebastion will reply explaining how to retry on the inline comment.
  • The finding must be medium, low, or info severity. The chat path alone cannot suppress critical or high findings — see the security properties below.

The suppression takes effect on the next audit, not retroactively. The original finding stays visible in the PR review history.

2. Auto-detected suggest-model files

Sebastion auto-loads suppression markers from the four files that agentic coding tools already read for context:

  • AGENTS.md
  • CLAUDE.md
  • .cursorrules
  • .github/copilot-instructions.md

The grammar is one marker per line:

# sebastion: ignore <rule_id> in <file_glob>

For example, a top-level AGENTS.md containing:

# sebastion: ignore py.print-statement in bin/**
# sebastion: ignore js.console-log in scripts/*.js

…suppresses py.print-statement under bin/ and js.console-log directly under scripts/ for the whole repo.

Nested files scope to their directory. A bin/AGENTS.md with the same first line suppresses only py.print-statement inside bin/ (and below).

3. Operator-added (support / on-call)

If you need to suppress something that the other two paths can't handle, contact support. We add Learnings manually via an audited operator path, with the reason logged against your installation.

How to remove a Learning

  • For auto-detected Learnings, delete the marker line from the source file and open a fresh PR. The next audit re-loads from your base branch and the Learning disappears.
  • For chat-created Learnings, contact support with the rule id and glob. (A self-serve delete UI is planned for v2.)
  • For operator-added Learnings, contact support.

Security properties

Suppression is a trust-affecting feature: a Learning makes the bot silent on a class of finding forever. We designed it under an explicit threat model so it can't become a primitive for silencing real findings. The properties below are guarantees, not best efforts.

Base-branch trust boundary

Auto-detected markers (path 2 above) are read only from your PR's base branch, never from the PR head. This means a suppression marker in a PR has no effect until that PR is merged.

Why this matters: without this property, an attacker could open a PR that adds AGENTS.md containing # sebastion: ignore <some-critical-rule> in <their-attack-path>, and the audit on that same PR would silence the very finding the marker was added to hide. Reading only from the base branch forces every new suppression through the same review path your code changes already follow.

Severity floor

@sebastionai ignore chat commands (or the synonyms suppress, mute, silence) can suppress medium, low, and info severity findings only. critical and high findings require an operator-added Learning with an audit trail and an alert to the on-call engineer. This stops a compromised maintainer account from silently suppressing an RCE warning.

Strict rule and path grammar

  • rule_id must match ^[a-z0-9][a-z0-9._-]{0,127}$. No wildcards.
  • file_glob is ≤ 256 characters.
  • Bare wildcards (*, **, **/*, */*) are rejected. Suppressions must target a specific path. If you genuinely need to suppress a rule repo-wide, contact support — the operator path emits an alert so we know it happened.

Per-installation rate limits and caps

  • 20 new Learnings per hour, 100 per day per installation (chat path).
  • 500 active Learnings per installation. Beyond the cap, new suppressions require operator approval.
  • We alert our on-call if any installation hits 80% of cap, or creates more than 10 Learnings in 24 hours.

Audit trail

Every Learning create and delete writes a record to the tenant event log: the source (chat / auto_detect / manual), the rule id, the file glob, and the actor identity (commenter login or operator email). Available via the admin portal and on request via support.

Data minimisation

The Learnings store contains only rule_id, file_glob, source, count, created_at, and last_seen_at. No comment text. No file content. No personal data. Actor identity lives in the tenant event log under our standard retention and access controls — not in the Learnings store itself.

Installation lifecycle

When you uninstall Sebastion AI from your account, all Learnings associated with that installation are wiped within the same webhook that handles uninstall. Reinstalling later starts you with a clean slate.

  • .sebastionai.yml config — repo-level disable_rules and ignore_paths. Different from Learnings: config is a per-repo policy you commit; Learnings are a per-installation suppression store that chat commands and AGENTS.md write to.
  • Security tab — where to triage the same findings inside GitHub's native Code Scanning UI.