AID-D-004.004: Model Source & Namespace Drift Detection

Version 1.20261015 · Actionable sub-technique

A set of high-signal detective controls that monitor for symptoms of a model namespace reuse attack or supply chain policy failure. This technique focuses on detecting lifecycle changes in external model repositories (e.g., deletions, redirects) during the curation process and on identifying unexpected network traffic from production systems to public model hubs at runtime.

Pillars: infra, app

Lifecycle: validation, operation

Scope boundary

Owns high-signal findings for external model-repository lifecycle and namespace changes during curation, plus unexpected production traffic to public model hubs. It does not perform broad enterprise AI-service inventory discovery.

AID-M-001.004: AID-D-004.004 detects model-source or namespace drift and production contact with public model hubs; AID-M-001.004 discovers broad use of externally hosted AI services and embedded SaaS AI across enterprise telemetry. A model supply-chain drift signal is narrower than enterprise-wide shadow-AI service discovery.

Implementation guidance

AID-D-004.004-G001

Alert on 404 or 3xx status codes when validating external model URLs during CI curation.
CI namespace-state probe

Probe only model references from a signed, provider-allowlisted dependency inventory. Do not follow redirects: a redirect is itself evidence of namespace movement. Bind the result to DNS, TLS, provider, namespace, revision, and URL evidence, and revalidate the immutable revision at the separate promotion gate to address time-of-check/time-of-use.

from __future__ import annotations

# File: detection/model_reference_probe.py

import hashlib
from urllib.parse import urlsplit

import httpx


def probe_model_reference(reference: dict, policy: dict) -> dict:
    required_reference = {
        "reference_id", "provider", "namespace", "revision", "url",
    }
    if set(reference) != required_reference:
        raise ValueError("model reference schema mismatch")
    host = urlsplit(reference["url"]).hostname
    provider = policy["providers"].get(reference["provider"])
    if (
        host is None
        or provider is None
        or host not in provider["allowed_hosts"]
        or not reference["revision"]
    ):
        raise ValueError("reference is outside signed provider policy")
    headers = {
        "Accept": "application/octet-stream",
        "Range": "bytes=0-0",
        "User-Agent": "aidefend-model-reference-probe/1",
    }
    try:
        with httpx.Client(
            follow_redirects=False,
            timeout=httpx.Timeout(
                float(policy["read_timeout_seconds"]),
                connect=float(policy["connect_timeout_seconds"]),
            ),
            verify=True,
        ) as client:
            with client.stream("GET", reference["url"], headers=headers) as response:
                status = int(response.status_code)
                location = response.headers.get("location")
        finding_reasons = []
        if 300 <= status < 400:
            finding_reasons.append("namespace_redirect")
        if status == 404:
            finding_reasons.append("namespace_not_found")
        if status not in set(provider["accepted_status_codes"]):
            finding_reasons.append("unexpected_status")
        return {
            "schema_version": "aidefend.model_reference_probe.v1",
            "control_status": "PASS",
            "finding_status": "FINDING" if finding_reasons else "NO_FINDING",
            "reference_id": reference["reference_id"],
            "provider": reference["provider"],
            "namespace": reference["namespace"],
            "revision": reference["revision"],
            "url_sha256": hashlib.sha256(reference["url"].encode()).hexdigest(),
            "status_code": status,
            "redirect_location_sha256": (
                hashlib.sha256(location.encode()).hexdigest() if location else None
            ),
            "finding_reasons": sorted(set(finding_reasons)),
            "policy_version": policy["policy_version"],
        }
    except (httpx.HTTPError, OSError) as exc:
        return {
            "control_status": "ERROR",
            "finding_status": "UNKNOWN",
            "reference_id": reference["reference_id"],
            "reason": type(exc).__name__,
            "policy_version": policy["policy_version"],
        }

Verification: Replay stable, 404, single-hop and chained redirect, unauthorized, rate-limited, TLS failure, DNS failure, disallowed host, missing revision, timeout, and provider-error fixtures through a controlled test server. Confirm redirect bodies are never followed or trusted.

Action: Probe every signed external reference during curation and emit namespace-state findings without mutating the reference. The promotion or deployment control must separately resolve and verify the immutable revision again.

AID-D-004.004-G002

Monitor for runtime DNS queries or egress traffic from production pods to public model hubs.
Concept:

If your hardening policies are correctly implemented, your production AI services should have no reason to ever contact a public model hub like `huggingface.co`. Any attempt to do so is a high-confidence indicator of a misconfiguration, a policy bypass, or malicious code that has slipped through the supply chain.

Note: For the `fd.sip.name` field to be effective, the environment must allow Falco to perform or receive DNS resolutions. If this is not feasible, an alternative is to monitor DNS logs directly or use a CNI-level tool like Cilium Hubble.

Implement a Runtime Egress Detection Rule

This safer Falco pattern explicitly checks for connection events and uses Falco's documented field for resolved domain names.

# File: falco_rules/ai_egress_violation.yaml
- rule: Prod AI Pod Egress to Public Model Hub
  desc: Egress from prod AI namespaces to public model hubs (HF domains)
  condition: >
    evt.type=connect and fd.l4proto in (tcp, udp) and
    k8s.ns.name in (ai-prod, ai-inference) and
    fd.sip.name in (huggingface.co, hf.co)
  output: >
    Disallowed egress to public model hub (ns=%k8s.ns.name pod=%k8s.pod.name
    user=%user.name cmd=%proc.cmdline dst=%fd.name)
  priority: CRITICAL
  tags: [network, supply_chain, aidefend]
Verify safely

Store inputs, results, and readback receipts in append-only or WORM storage outside monitored identities. An independent verifier must query DNS, network-flow, proxy, and workload inventories independently, replay approved and disallowed canary destinations, reconcile every expected workload and event ID, read the evidence back, verify signatures and digests, and compare the canonical result digest.

Open-source tools

Commercial / hosted tools

Threat mappings

MITRE ATLAS

MAESTRO

OWASP LLM Top 10 2026

OWASP ML Top 10 2023

OWASP Top 10 for Agentic Applications 2026

NIST Adversarial Machine Learning 2025

Cisco Integrated AI Security and Safety Framework

Google Secure AI Framework 2.0 - Risks

Databricks AI Security Framework 3.0

AID-D-004.004: Model Source & Namespace Drift Detection | AIDEFEND

Loading interactive view…

A Practical Knowledge Base for AI Security Defenses

Version