Skip to main content

ADR-005: Malicious Supply Chain Detection for Third-Party Skills and Plugins

Status: Proposed Date: 2026-02-18 Deciders: CODITECT Architecture Team Source Research: ClawGuard AI Agent Security Ecosystem Evaluation (2026-02-18)


Context

During the ClawGuard AI Agent Security Ecosystem evaluation on 2026-02-18, a trojanized fork of a legitimate repository was encountered and identified before any code was executed:

Finding: lauty1505/clawguard — A trojanized fork of JaydenBeard/clawguard. The fork contained an injected binary named Software-tannin.zip embedded in the repository. The README was rewritten with social-engineering language to encourage users to download and execute the binary. This is a classic fork-and-trojanize supply chain attack pattern targeting developers who search for security tooling by name.

Action taken: Repository removed from submodules. Never pushed, never executed.

This incident is not an outlier. Fork-and-trojanize is a documented, growing attack vector in the open-source ecosystem:

  • The attacker identifies a legitimate, useful tool.
  • They fork it to a new account.
  • They inject malicious code (binary, script, or modified source).
  • They optimize the forked repository to appear in search results for the tool's name.
  • Developers who find the fork via search (not the canonical repository) clone and execute the malicious version.

The ClawGuard ecosystem is an especially attractive target because:

  1. Security tooling is trusted implicitly. A tool named "ClawGuard" is expected to run with security-related permissions and access to agent state.
  2. Developers evaluating security tools are specifically looking for new repositories, making search-based discovery the primary attack vector.
  3. The trojanized repository was found during a structured evaluation with explicit provenance checking. In a less rigorous workflow, it might have been cloned and tested.

CODITECT's platform involves:

  • 97 submodules with a mix of CODITECT-owned and third-party repositories.
  • A pattern of evaluating and integrating new third-party tools (analyze-new-artifacts/ workflow).
  • Tenant-installable skills (skills/ — 445 components) and a future plugin ecosystem.
  • Agent execution with tool calls that can read files, execute shell commands, and access credentials.

A single trojanized skill or plugin installed into the CODITECT runtime has immediate access to all of these. The attack surface is real and the stakes are high.

The question is: how should CODITECT systematically detect and prevent malicious supply chain components from being integrated, and how should this be enforced as an automated gate rather than a manual review process?


Decision

Implement automated supply chain verification as a mandatory gate for all third-party skill and plugin integrations, combining three complementary mechanisms:

  1. Binary artifact scanning — Detect injected executables, archives, and unexpected binary files in source repositories.
  2. Provenance verification — Validate that submodule URLs, npm packages, and PyPI packages point to expected canonical sources.
  3. Trust registry — Maintain a CODITECT-managed list of approved third-party repositories with pinned commit hashes and expected file checksums.

Mechanism 1: Binary Artifact Scanning

All repositories added to submodules/, all npm packages installed into skills, and all PyPI packages in skill venvs are scanned for:

  • Unexpected binary file types: .exe, .dll, .so, .dylib, .zip, .tar.gz, .gz, .pkg, .dmg, .msi, .deb, .rpm — any binary that is not explicitly declared in the repository's manifest.
  • Files not matching declared content: A file named README.md that is binary, or a .py file with non-UTF-8 content.
  • Hidden files: Files with names beginning with . that are not standard dotfiles (.gitignore, .env.example, etc.).

Detection is implemented in scripts/security/supply-chain-scanner.py, invoked automatically:

  • When git submodule add is executed (pre-commit hook).
  • When npm install or pip install is run in a skill directory (post-install hook).
  • As a scheduled scan of all existing submodules (daily, via scripts/security/scheduled-supply-chain-audit.py).

A binary artifact detection produces a SUPPLY_CHAIN_VIOLATION event and blocks the integration (always fail-closed for supply chain violations — no configurable fail-open).

Mechanism 2: Provenance Verification

Before a third-party repository is added as a submodule:

  1. The remote URL is checked against the CODITECT allow-list of trusted domains (github.com/coditect-ai/, pre-approved third-party organizations).
  2. The repository's commit history is checked: forks of known-good repositories that have fewer than a configurable minimum history depth (min_commit_count: 10) are flagged as potentially suspicious (new forks often have shallow histories).
  3. The adding developer must explicitly confirm that they have verified:
    • The repository is the canonical upstream (not a fork).
    • The repository owner is a recognized organization or individual.
    • The commit being pinned has been reviewed.

This confirmation is recorded in config/security/submodule-attestations.yaml:

# config/security/submodule-attestations.yaml
attestations:
- submodule: submodules/core/coditect-core
url: https://github.com/coditect-ai/coditect-core.git
attested_by: hal@az1.ai
attested_at: "2026-02-18T00:00:00Z"
commit: abc123def456
notes: "Canonical CODITECT core framework."

- submodule: submodules/agent-labs/
url: https://github.com/brainqub3/agent-labs.git
attested_by: hal@az1.ai
attested_at: "2026-02-16T00:00:00Z"
commit: def789abc012
notes: "Third-party, read-only reference. NEVER push upstream."
never_push: true

Any submodule without an attestation entry blocks the repository from being included in CI and triggers an alert.

Mechanism 3: Trust Registry

The config/security/trust-registry.yaml file maintains a curated list of approved third-party components with pinned versions and expected checksums:

# config/security/trust-registry.yaml
version: "1.0.0"
updated: "2026-02-18"

trusted_npm_packages:
- name: "@yourclaw/clawguardian"
version: "0.2.2"
registry: "https://registry.npmjs.org"
sha512: "sha512-<expected-checksum>"
approved_by: hal@az1.ai
approved_at: "2026-02-18T00:00:00Z"
notes: "ClawGuardian hook plugin, reference implementation for security patterns."

trusted_pypi_packages:
- name: "fastapi"
version_range: ">=0.109.0,<1.0.0"
registry: "https://pypi.org"
approved_by: hal@az1.ai
approved_at: "2026-02-18T00:00:00Z"

untrusted_repositories:
- url: "https://github.com/lauty1505/clawguard"
reason: "Trojanized fork of JaydenBeard/clawguard. Contains injected binary Software-tannin.zip."
detected_at: "2026-02-18T00:00:00Z"
detected_by: research-agent
action: BLOCKED

The untrusted_repositories section serves as a threat intelligence list. Any attempt to add a URL from this list as a submodule is automatically blocked, regardless of context.

Post-Incident Retrospective Entry

The lauty1505/clawguard incident is immediately recorded in the trust registry (above) and in org.db as a permanent learning:

# Recorded in org.db as an error_solution
{
"category": "supply_chain_security",
"problem": "Trojanized fork encountered during security tool evaluation.",
"solution": "Binary artifact scanner + provenance verification + trust registry prevent recurrence.",
"evidence": "lauty1505/clawguard — Software-tannin.zip binary injected. Detected by provenance check before clone.",
"date": "2026-02-18"
}

Consequences

Positive

  • Automated detection prevents human error: The lauty1505/clawguard trojan was caught in a structured evaluation. A developer under time pressure might have missed it. Automated scanning eliminates this dependency on human vigilance.
  • Defense-in-depth: Three independent mechanisms (binary scanning, provenance verification, trust registry) must all be bypassed simultaneously for a malicious component to be integrated. Any single mechanism catching an issue blocks the integration.
  • Institutional memory: The untrusted_repositories trust registry creates a permanent, searchable record of known-malicious repositories that persists across team members and sessions.
  • Audit trail: Submodule attestations in submodule-attestations.yaml provide a verifiable record of who reviewed and approved each third-party integration.
  • The ClawGuard ecosystem itself proves the value: The trojan was found while researching security tooling for AI agents. This recursive irony validates that supply chain attacks specifically target security-conscious workflows.

Negative

  • Attestation overhead: Every new third-party submodule addition now requires an explicit attestation step. This adds friction to integration workflows. Mitigation: the attestation template is auto-generated by a helper script (scripts/security/attest-submodule.py), reducing manual effort to filling in three fields.
  • Trust registry maintenance: The trusted packages list requires ongoing maintenance as package versions are updated. An outdated trust registry can false-positive on legitimate version upgrades. Mitigation: version range expressions (not pinned versions) are supported for packages with active upgrade cycles.
  • Binary false positives: Legitimate repositories sometimes include pre-compiled assets (WebAssembly .wasm files, compiled assets in dist/). The scanner must maintain a configurable allow-list of expected binary types per repository. This adds calibration effort.
  • No protection against source-level injection: Binary scanning does not detect malicious code written in interpreted languages (Python, JavaScript) that does not use binary artifacts. Source-level analysis would require static analysis tooling (a future enhancement). The current ADR focuses on the most common attack pattern (injected binaries and archives).

Neutral

  • CODITECT's existing git push safety rules (NEVER PUSH TO NON-CODITECT REPOSITORIES) already prevent accidental upstream push of third-party submodules. ADR-005 adds complementary inbound protection (what we pull in) to the existing outbound protection (what we push out).

Alternatives Considered

Alternative A: Manual Review Only

Approach: Require human review of all third-party integrations. No automated scanning. Document a review checklist.

Rejected because:

  • The lauty1505/clawguard incident demonstrates that even structured, deliberate evaluations can encounter malicious repositories. Checklist-based manual review is subject to human error, time pressure, and fatigue.
  • As the CODITECT ecosystem grows (97 submodules today, more planned), manual review of every integration does not scale.
  • Manual review produces no persistent audit record unless explicitly documented every time.

Alternative B: Automated Scanning Only (No Trust Registry)

Approach: Run binary artifact scanning on all integrations but maintain no trust registry or attestation records.

Rejected because:

  • Binary scanning detects binary artifacts but not source-level malice or provenance fraud (a legitimate-looking repository with a malicious npm package dependency).
  • Without a trust registry, there is no institutional memory. The lauty1505/clawguard URL could be proposed as a submodule in a future session with no record of why it was previously rejected.
  • Attestations provide the human oversight layer that automated scanning cannot replace for novel attack patterns.

Alternative C: Vendor Lock-In via Approved Vendor List Only

Approach: Allow only pre-approved vendors. All third-party integrations must come from a fixed list of approved organizations (e.g., only github.com/coditect-ai/).

Rejected because:

  • CODITECT legitimately integrates third-party open-source components (agent-browser, pdf tools, research tooling). A strict vendor whitelist would block all of these.
  • The trust registry and attestation model provides equivalent assurance (each integration explicitly approved) without the operational inflexibility of an approved vendor list.

Alternative D: Sandboxed Execution Environment

Approach: Run all third-party skills and plugins in a sandboxed execution environment (containerized, network-isolated) so that even malicious code cannot affect the host system.

Not selected as primary (appropriate as a future enhancement):

  • Sandboxing is complementary to supply chain verification, not a replacement. A sandbox prevents damage from executing malicious code, but does not prevent the malicious code from being present in the codebase or from operating within the sandbox's allowed capabilities.
  • Container sandboxing adds significant operational complexity and latency to skill execution.
  • Noted as a future enhancement, particularly for the planned third-party plugin ecosystem.

Implementation Notes

  • Scanner: scripts/security/supply-chain-scanner.py — invoked by pre-commit hook and scheduled audit.
  • Attestation tool: scripts/security/attest-submodule.py — generates and validates attestation entries.
  • Trust registry SSOT: config/security/trust-registry.yaml
  • Attestation SSOT: config/security/submodule-attestations.yaml
  • Threat intelligence store: untrusted_repositories section of trust registry + org.db error_solutions table.
  • CI gate: Supply chain scan runs in CI pipeline before any skill or submodule is merged to main.
  • Expected binary allowlist: Per-repository configuration in config/security/binary-allowlist.yaml (e.g., submodules/core/json-viewer may contain pre-compiled .js bundles).
  • Incident from this evaluation: lauty1505/clawguard is immediately added to untrusted_repositories as the first entry.

References

  • Malicious repository finding: analyze-new-artifacts/clawguard-ai-agent-security/artifacts/research-context.jsonsecurity_findings.malicious_repo_detected
  • Git push safety: CLAUDE.md — "NEVER PUSH TO NON-CODITECT REPOSITORIES" directives
  • Existing submodule safety: .gitmodules + scripts/sync-all-submodules.sh
  • org.db schema: docs/reference/database/DATABASE-SCHEMA.mderror_solutions table
  • Related ADRs: ADR-001 (Security Layer Architecture), ADR-002 (Pattern Library Format), ADR-003 (Fail Behavior)
  • Future: Sandboxed plugin execution (planned, not yet an ADR)