Agentic Covenants

Detect (DE) · Supply chain

Supply chain at the client side layer

deterministic · Outside the model's reasoning

If this concern is breached, how do we know?

What this cell does

MCP allowlist violation events; tool-description hash mismatch alerting; lockfile diff in CI logs centralized; pre-commit dependency scan results.

Artifacts (3)

ci-lockfile-diff.ymlview on GitHub
# ABOUTME: Workflow step shipping truncated lockfile diff to SIEM on every PR. Add to lockfile-integrity.yml.
# ABOUTME: Diff is truncated to first 200 lines so a huge PR does not flood the SIEM payload; full diff is in CI artifacts.
- name: Ship lockfile diff to SIEM
  if: always() && github.event_name == 'pull_request'
  env:
    SIEM_TOKEN: ${{ secrets.SIEM_TOKEN }}
    SIEM_URL: ${{ vars.SIEM_URL }}
  run: |
    DIFF=$(git diff origin/${{ github.base_ref }} -- \
      package-lock.json requirements.txt requirements*.txt \
      Pipfile.lock poetry.lock go.sum Cargo.lock 2>/dev/null \
      | head -200)
    if [[ -n "$DIFF" ]]; then
      DIFF_JSON=$(printf '%s' "$DIFF" | jq -R -s .)
      curl -sS -X POST "$SIEM_URL/agent-sentinel-ci/_doc" \
        -H "Authorization: Bearer $SIEM_TOKEN" \
        -H "Content-Type: application/json" \
        -d "{
          \"event\": \"lockfile_diff\",
          \"repo\": \"${{ github.repository }}\",
          \"pr\": ${{ github.event.pull_request.number }},
          \"actor\": \"${{ github.actor }}\",
          \"diff\": $DIFF_JSON,
          \"ts\": \"$(date -Iseconds)\"
        }"
    fi
mcp-launch-emit.shview on GitHub
#!/usr/bin/env bash
# ABOUTME: Snippet that the mcp-launch wrapper sources to emit a structured per-connection event with status and hash.
# ABOUTME: Source from controls/supply-chain/client-side/mcp-launch immediately after the hash check.

emit_mcp_connect() {
  # Args:
  #   $1 = server name
  #   $2 = status (ok | hash_mismatch | not_in_allowlist | signature_failed)
  #   $3 = actual sha256 (or "" if not computed)
  local name="$1" status="$2" sha="${3:-}"

  local event
  event="$(jq -n \
    --arg server "$name" \
    --arg status "$status" \
    --arg sha "$sha" \
    --arg ts "$(date -Iseconds)" \
    '{event: "mcp_connect", server: $server, status: $status, hash: $sha, ts: $ts}')"
  logger -t agent-sentinel -p user.info "$event"
}

# Usage in mcp-launch:
#
#   . /etc/agents/hooks/mcp-launch-emit.sh
#
#   if [[ -z "$EXPECTED_SHA" || ... ]]; then
#     emit_mcp_connect "$SERVER_NAME" "not_in_allowlist" ""
#     exit 2
#   fi
#   if [[ "$ACTUAL_SHA" != "$EXPECTED_SHA" ]]; then
#     emit_mcp_connect "$SERVER_NAME" "hash_mismatch" "$ACTUAL_SHA"
#     exit 2
#   fi
#   emit_mcp_connect "$SERVER_NAME" "ok" "$ACTUAL_SHA"
tool-desc-mismatch-emit.pyview on GitHub
# ABOUTME: Patch fragment for mcp-verify-tools.py that emits a structured event when the tool-description hash mismatches.
# ABOUTME: This is the rug-pull alert. Add the import + call inside the existing mismatch branch.

import json
import syslog


def _emit_tool_desc_mismatch(server_name: str, expected_hash: str, actual_hash: str) -> None:
    """Emit a structured rug-pull event to local syslog tagged agent-sentinel.

    Call this from `mcp-verify-tools.py` inside the `if expected and actual != expected:`
    branch, before `sys.exit(2)`.
    """
    syslog.openlog("agent-sentinel")
    syslog.syslog(
        syslog.LOG_WARNING,
        json.dumps(
            {
                "event": "mcp_tool_desc_mismatch",
                "server": server_name,
                "expected_hash": expected_hash,
                "actual_hash": actual_hash,
            }
        ),
    )


# Patch fragment to apply in mcp-verify-tools.py:
#
#     if expected and actual != expected:
#         _emit_tool_desc_mismatch(server_name, expected, actual)
#         print(f"BLOCKED: {server_name} tool descriptions changed", file=sys.stderr)
#         ...

Cell notes

Sentinels, Supply chain / Client-side

Control. mcp-launch wrapper logs every connection attempt with status (ok | hash_mismatch | not_in_allowlist). Tool-description hash mismatch alerts on rug-pull. Lockfile diff in CI shipped to SIEM. Pre-commit dependency scan results centralized.

Strength. Deterministic when emit happens. Failure modes: MCP wrapper logs only successful connections (failures and rejections are the interesting events); lockfile diff log includes the entire diff for huge PRs (truncate to first 200 lines); tool-description hash mismatch suppressed on legitimate update (the mismatch is the alert; reapproval is a separate workflow).

Tooling

Files in this directory

  • - mcp-launch-emit.sh, append-only snippet that the mcp-launch wrapper sources to emit a structured per-connection event including status and hash.
  • - tool-desc-mismatch-emit.py, patch fragment for mcp-verify-tools.py that emits a structured event on hash mismatch (the rug-pull alert).
  • - ci-lockfile-diff.yml, workflow extension that ships the truncated lockfile diff to SIEM on every PR that touches a lockfile.

Verification


# 1. MCP allowlist violation logged
mcp-launch unknown-server || true
journalctl -t agent-sentinel --since "1 minute ago" | grep mcp_connect
# expected: status: not_in_allowlist event

# 2. Tool-description mismatch logged
# Modify a tool description in a running MCP server's source; restart.
journalctl -t agent-sentinel | grep mcp_tool_desc_mismatch

# 3. Lockfile diff in SIEM
# Open a PR with a lockfile change; check SIEM for the lockfile_diff event.

Common mistakes

  • - MCP wrapper logs only successful connections. The interesting events are failures and rejections.
  • - Lockfile diff log includes the entire diff for huge PRs. Truncate to first 200 lines.
  • - Tool-description hash mismatch suppressed on legitimate update. The mismatch is the alert; reapproval is a separate workflow.

Citation

NIST CSF 2.0 DE.CM-09, ID.RA-09. OWASP MCP08, MCP09.

Primary failure modes

Documented, not hypothetical. A control whose bypass is undocumented is worse than no control, because somebody trusted it.

  • MCP wrapper logs only successful connections (failures are interesting events)
  • lockfile diff log includes full diff for huge PRs (truncate)
  • tool-description hash mismatch suppressed on legitimate update

Crosswalk

NIST CSF 2 0DE.CM-09, ID.RA-09
OWASP MCPMCP08, MCP09