Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 48 additions & 2 deletions skills/ai-security/model-supply-chain/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ phase: [build, review, operate]
frameworks: [OWASP-LLM03-2025, SLSA-v1.0, MITRE-ATLAS]
difficulty: advanced
time_estimate: "45-90min"
version: "1.0.0"
version: "1.0.1"
author: unitoneai
license: MIT
allowed-tools: Read, Grep, Glob
Expand Down Expand Up @@ -131,6 +131,30 @@ Glob: **/config.json
| No model card or provenance documentation available | Medium |
| Checksums verified but against values stored in the same repository as the model (self-referential) | Medium |

#### Adapter Composition Evidence Gate

When LoRA, QLoRA, PEFT, prompt adapters, or other adapter/plugin weights are deployed, assess the deployed unit as the complete composition. A signed adapter alone is not enough: model behavior depends on the base model revision, tokenizer/config, quantization, target modules, merge order, runtime framework, and safety evaluation performed after composition.

**Required adapter composition gates:**

| Gate | Required evidence | Fail if |
|---|---|---|
| `MSC-COMP-01` | Composition manifest identifies the deployed unit and binds base model source, revision, checksum, license, and model card to each adapter source, revision, checksum, license, training summary, and adapter card. | Base model is `latest`, adapter metadata is missing, or the adapter is reviewed without the deployed base model. |
| `MSC-COMP-02` | Tokenizer, processor, config, special tokens, chat template, generation config, framework versions, and runtime loader versions are pinned with revisions or checksums. | Tokenizer/config can drift independently from the base or adapter, or framework versions are omitted. |
| `MSC-COMP-03` | Merge/load parameters are recorded: LoRA/QLoRA/PEFT type, rank, alpha, target modules, adapter weights path, quantization bits/scheme/calibration, merge order, merge script, and tool version. | The same adapter could be loaded into different modules, quantization modes, or merge orders with no auditable record. |
| `MSC-COMP-04` | Approved compatibility constraints list allowed base-adapter-tokenizer-quantization combinations and disallowed pairs, including model family, architecture, context length, and license constraints. | Any adapter can be hot-loaded into any base model, or architecture/license incompatibilities are not enforced. |
| `MSC-COMP-05` | Base and adapter trust evidence comes from signatures, attestations, registry digests, or independently computed trusted checksums that are not self-referential to the same compromised source. | Checksums are only copied from the same registry/repo as the artifact, or no independent trust root exists. |
| `MSC-COMP-06` | The composed bundle has a signed manifest and reproducible merge/load job showing immutable inputs, builder identity, environment, script version, and output digest. | Production serves a manually assembled or mutable composition that cannot be rebuilt from recorded inputs. |
| `MSC-COMP-07` | Safety, regression, domain, jailbreak, and output-difference evaluations run on the composed deployed unit, not only on the base model or standalone adapter. | Evidence only covers standard benchmarks, base-model tests, or adapter-only metadata. |
| `MSC-COMP-08` | Promotion binds deployment to the signed composition and includes rollback bundle, canary/monitoring plan, owner approval, and reconstruction evidence. | Rollback points to an unrelated base model, or the deployed composition cannot be reconstructed. |

**Status and severity guidance:**

- Mark adapter deployments as `Not Evaluable` when the deployed composition cannot be reconstructed from immutable manifest inputs.
- Treat missing composition binding as **High** severity for production or safety-sensitive deployments, even when individual adapter files are signed.
- Cap confidence at **Low** when safety evaluation is not performed on the exact base-adapter-tokenizer-runtime combination.
- Escalate to **Critical** if an untrusted adapter can be hot-loaded into a privileged production model path without compatibility checks, approval, or rollback.

---

### Step 2 -- Training Data Lineage
Expand Down Expand Up @@ -382,10 +406,29 @@ Assess whether architectural and procedural controls exist to detect model backd
|---|---|---|---|---|---|
| [name] | [source] | [format] | [Yes/No] | [Yes/No] | [Complete/Partial/Missing] |

## Adapter Composition Inventory

| Composition ID | Base Model | Adapter(s) | Tokenizer/Config | Quantization/Merge Order | Signatures/Attestations | Safety Eval | Rollback Bundle | Status |
|---|---|---|---|---|---|---|---|---|
| [composition] | [source/revision/checksum] | [source/revision/checksum] | [pinned/missing] | [recorded/missing] | [verified/missing/self-referential] | [composed/base-only/missing] | [available/missing] | [Pass/Fail/Not Evaluable] |

## Adapter Composition Gate Results

| Gate | Evidence Reviewed | Status | Risk |
|---|---|---|---|
| `MSC-COMP-01` | [composition manifest base/adapter binding] | [Pass/Fail/Not Evaluable] | [risk] |
| `MSC-COMP-02` | [tokenizer/config/runtime pinning] | [Pass/Fail/Not Evaluable] | [risk] |
| `MSC-COMP-03` | [merge/load/quantization parameters] | [Pass/Fail/Not Evaluable] | [risk] |
| `MSC-COMP-04` | [compatibility constraints and disallowed pairs] | [Pass/Fail/Not Evaluable] | [risk] |
| `MSC-COMP-05` | [signatures, attestations, or trusted checksums] | [Pass/Fail/Not Evaluable] | [risk] |
| `MSC-COMP-06` | [signed composition manifest and reproducible job] | [Pass/Fail/Not Evaluable] | [risk] |
| `MSC-COMP-07` | [composed-unit safety/regression evidence] | [Pass/Fail/Not Evaluable] | [risk] |
| `MSC-COMP-08` | [deployment binding, rollback, monitoring, reconstruction] | [Pass/Fail/Not Evaluable] | [risk] |

## Findings

### Finding [N]: [Title]
- **Category:** [Provenance | Training Data | Fine-Tuning Pipeline | Inference Dependency | Model Card | Backdoor Detection]
- **Category:** [Provenance | Adapter Composition | Training Data | Fine-Tuning Pipeline | Inference Dependency | Model Card | Backdoor Detection]
- **Severity:** [Critical | High | Medium | Low | Informational]
- **OWASP LLM Category:** LLM03:2025 -- Supply Chain Vulnerabilities
- **MITRE ATLAS Technique:** [technique ID and name]
Expand All @@ -401,6 +444,7 @@ Assess whether architectural and procedural controls exist to detect model backd
| Domain | Current State | Target State | Gap Severity |
|---|---|---|---|
| Model provenance | [description] | [recommendation] | [severity] |
| Adapter composition | [description] | [recommendation] | [severity] |
| Training data lineage | [description] | [recommendation] | [severity] |
| Fine-tuning pipeline | [description] | [recommendation] | [severity] |
| Inference dependencies | [description] | [recommendation] | [severity] |
Expand Down Expand Up @@ -441,6 +485,8 @@ Assess whether architectural and procedural controls exist to detect model backd

5. **Evaluating models only on benchmarks.** Standard benchmarks measure general capability, not supply chain integrity. A backdoored model will perform normally on benchmarks by design. Behavioral differential testing with curated, domain-specific test sets that probe for targeted manipulation is required to surface backdoors.

6. **Treating a signed adapter as safe outside its composition.** LoRA, QLoRA, and PEFT adapters materially change model behavior only after they are loaded or merged with a specific base model, tokenizer/config, quantization mode, framework version, and merge order. A valid adapter signature does not prove that the deployed composition is approved, compatible, reproducible, safe, or rollback-ready.

---

## References
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
{
"fixture": "signed_adapter_composition_manifest_and_safety_eval",
"skill": "model-supply-chain",
"description": "Benign fixture for a production LoRA composition with pinned base, adapter, tokenizer, quantization, signed bundle provenance, composed-unit safety evaluation, and rollback evidence.",
"deployment": {
"composition_id": "clinical-summary-v4-lora-20260609",
"environment": "production",
"owner": "ml-platform",
"serving_stack": "text-generation-inference",
"promotion_ticket": "MLPROMO-4821"
},
"composition_manifest": {
"manifest_id": "composition-manifest-clinical-summary-v4",
"manifest_version": "2026.06.09",
"signed": true,
"signature": {
"type": "sigstore",
"issuer": "internal-fulcio",
"bundle_ref": "sigstore-bundle-composition-clinical-v4"
},
"base_model": {
"source": "internal-registry/acme-clinical-llm",
"revision": "rev-clinical-base-2026-05-30",
"checksum": "sha256-example-base-clinical-20260609",
"license": "Apache-2.0",
"model_card": "model-cards/acme-clinical-llm-v4.md",
"attestation": "slsa-attestation-base-clinical-v4"
},
"adapters": [
{
"name": "clinical-summarization-lora",
"source": "internal-registry/adapters/clinical-summarization-lora",
"revision": "rev-adapter-2026-06-01",
"checksum": "sha256-example-adapter-clinical-20260609",
"license": "Apache-2.0",
"adapter_card": "adapter-cards/clinical-summarization-lora.md",
"training_summary": "training-summaries/clinical-summarization-lora-2026-06-01.md",
"attestation": "slsa-attestation-adapter-clinical-v2"
}
],
"tokenizer_and_config": {
"tokenizer_source": "internal-registry/acme-clinical-tokenizer",
"tokenizer_revision": "rev-tokenizer-2026-05-30",
"tokenizer_checksum": "sha256-example-tokenizer-clinical-20260609",
"special_tokens_revision": "rev-special-tokens-2026-05-30",
"chat_template_revision": "rev-chat-template-2026-05-30",
"generation_config_revision": "rev-generation-config-2026-06-02",
"framework_versions": {
"transformers": "4.52.1",
"peft": "0.15.2",
"bitsandbytes": "0.45.5",
"torch": "2.7.0"
}
},
"merge_and_runtime": {
"adapter_type": "LoRA",
"rank": 16,
"alpha": 32,
"target_modules": [
"q_proj",
"k_proj",
"v_proj",
"o_proj"
],
"adapter_weights_path": "registry://adapters/clinical-summarization-lora/rev-adapter-2026-06-01",
"quantization": {
"mode": "QLoRA",
"bits": 4,
"scheme": "nf4",
"calibration_dataset": "clinical-calibration-snapshot-2026-05"
},
"merge_order": [
"base-model",
"clinical-summarization-lora"
],
"merge_script": "tools/model_build/merge_lora.py",
"merge_script_version": "rev-merge-tool-2026-06-03",
"loader_policy": "hot-load-disabled-after-signed-bundle-build"
},
"compatibility_constraints": {
"approved_pairs": [
"acme-clinical-llm@rev-clinical-base-2026-05-30 + clinical-summarization-lora@rev-adapter-2026-06-01"
],
"disallowed_pairs": [
"public-chat-base@latest + clinical-summarization-lora",
"acme-clinical-llm@rev-clinical-base-2026-05-30 + finance-sentiment-lora"
],
"model_family": "acme-clinical",
"architecture": "decoder-only-transformer",
"context_length": 8192,
"license_check": "passed"
}
},
"reproducible_build": {
"builder_identity": "github-actions-oidc:model-bundle-builder",
"job_id": "model-bundle-build-20260609-0421",
"immutable_inputs": true,
"output_bundle_digest": "sha256-example-composed-bundle-clinical-20260609",
"rebuild_verification": "matched-output-digest",
"registry_digest": "registry-digest-composed-clinical-v4"
},
"safety_evaluation": {
"evaluated_artifact": "clinical-summary-v4-lora-20260609",
"matches_deployed_composition": true,
"standard_benchmarks": "passed",
"domain_regression_suite": "passed",
"safety_probe_suite": "passed",
"jailbreak_regression": "passed",
"known_good_output_diff": "within-approved-threshold",
"approval": "safety-review-accepted-2026-06-08"
},
"deployment_controls": {
"deployment_binding": "serving-config pins composition-manifest-clinical-summary-v4",
"canary_plan": "5-percent-for-24-hours-with-safety-alerts",
"monitoring": "output-drift-and-policy-violation-alerts-enabled",
"rollback_bundle": "clinical-summary-v3-signed-rollback-bundle",
"reconstruction_test": "passed"
},
"expected_gate_results": [
{
"gate": "MSC-COMP-01",
"status": "Pass",
"evidence": "Manifest binds deployed composition to pinned base and adapter metadata, checksums, licenses, model card, adapter card, and training summary."
},
{
"gate": "MSC-COMP-02",
"status": "Pass",
"evidence": "Tokenizer, special tokens, chat template, generation config, and framework versions are pinned."
},
{
"gate": "MSC-COMP-03",
"status": "Pass",
"evidence": "LoRA rank, alpha, target modules, quantization, merge order, adapter path, merge script, and tool version are recorded."
},
{
"gate": "MSC-COMP-04",
"status": "Pass",
"evidence": "Approved and disallowed composition pairs enforce base-adapter-tokenizer-quantization compatibility."
},
{
"gate": "MSC-COMP-05",
"status": "Pass",
"evidence": "Base, adapter, and composed bundle have signatures, attestations, registry digests, and trusted checksums."
},
{
"gate": "MSC-COMP-06",
"status": "Pass",
"evidence": "Signed manifest and reproducible merge job show immutable inputs, builder identity, and matched output digest."
},
{
"gate": "MSC-COMP-07",
"status": "Pass",
"evidence": "Safety and regression evaluation ran on the exact composed deployed unit."
},
{
"gate": "MSC-COMP-08",
"status": "Pass",
"evidence": "Deployment binds to the signed composition and includes canary monitoring, rollback bundle, and reconstruction test."
}
],
"expected_assessment": {
"overall_status": "Pass",
"risk_rating": "Low",
"confidence": "High",
"finding": "No adapter composition provenance finding expected."
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
{
"fixture": "unbound_lora_adapter_hotload_without_composition_manifest",
"skill": "model-supply-chain",
"description": "Vulnerable fixture for a signed LoRA adapter hot-loaded into an unpinned base model with missing tokenizer, merge, compatibility, safety, signed bundle, and rollback evidence.",
"deployment": {
"composition_id": "support-bot-prod-lora-latest",
"environment": "production",
"owner": "customer-support",
"serving_stack": "custom-transformers-service",
"promotion_ticket": "none"
},
"observed_configuration": {
"base_model": {
"source": "public-registry/example-chat-base",
"revision": "latest",
"checksum": null,
"license": "unknown",
"model_card": "missing"
},
"adapter": {
"name": "support-tone-lora",
"source": "public-registry/community/support-tone-lora",
"revision": "main",
"checksum": "checksum-copied-from-same-public-registry",
"license": "unknown",
"adapter_card": "missing",
"training_summary": "missing",
"signature": "adapter-file-signature-only"
},
"loader": {
"code_path": "app/model_loader.py",
"behavior": "hot-loads ADAPTER_NAME from environment at service start",
"allowed_adapter_names": "*",
"composition_manifest": "missing",
"runtime_pin": "requirements allow compatible updates"
},
"tokenizer_and_config": {
"tokenizer_revision": "not-recorded",
"special_tokens_revision": "not-recorded",
"chat_template_revision": "not-recorded",
"generation_config_revision": "not-recorded",
"framework_versions": "not-captured"
},
"merge_and_runtime": {
"adapter_type": "LoRA",
"rank": "unknown",
"alpha": "unknown",
"target_modules": "unknown",
"quantization": "runtime default",
"merge_order": "implicit load order",
"merge_script": "not-versioned",
"tool_version": "not-recorded"
},
"compatibility_constraints": {
"approved_pairs": "missing",
"disallowed_pairs": "missing",
"architecture_check": "missing",
"license_check": "missing"
}
},
"trust_and_build_evidence": {
"base_model_signature": "missing",
"adapter_trust_root": "self-referential-public-registry-checksum",
"composition_signature": "missing",
"composition_bundle_digest": "missing",
"reproducible_merge_job": "missing",
"builder_identity": "unknown",
"immutable_inputs": false
},
"safety_evaluation": {
"evaluated_artifact": "base-model-only",
"standard_benchmarks": "passed",
"domain_regression_suite": "missing",
"safety_probe_suite": "missing",
"jailbreak_regression": "missing",
"known_good_output_diff": "missing",
"matches_deployed_composition": false
},
"deployment_controls": {
"deployment_binding": "service reads base and adapter names from environment",
"canary_plan": "missing",
"monitoring": "generic latency and error rate only",
"rollback_bundle": "base-model-latest",
"reconstruction_test": "not-possible"
},
"expected_gate_results": [
{
"gate": "MSC-COMP-01",
"status": "Fail",
"evidence": "No composition manifest; base is latest and adapter card, training summary, license, and trusted checksum are missing."
},
{
"gate": "MSC-COMP-02",
"status": "Fail",
"evidence": "Tokenizer, special tokens, chat template, generation config, and framework versions are not pinned."
},
{
"gate": "MSC-COMP-03",
"status": "Fail",
"evidence": "Rank, alpha, target modules, quantization, merge order, merge script, and tool version are undocumented."
},
{
"gate": "MSC-COMP-04",
"status": "Fail",
"evidence": "No approved or disallowed compatibility pairs; any adapter can be hot-loaded by environment variable."
},
{
"gate": "MSC-COMP-05",
"status": "Fail",
"evidence": "Adapter checksum is self-referential to the same public registry and base model has no signature."
},
{
"gate": "MSC-COMP-06",
"status": "Fail",
"evidence": "No signed composed bundle, immutable input list, builder identity, or reproducible merge job."
},
{
"gate": "MSC-COMP-07",
"status": "Fail",
"evidence": "Safety evidence covers standard benchmarks and the base model only, not the deployed composition."
},
{
"gate": "MSC-COMP-08",
"status": "Not Evaluable",
"evidence": "Rollback points to a mutable base-model latest alias and the deployed composition cannot be reconstructed."
}
],
"expected_assessment": {
"overall_status": "Fail",
"risk_rating": "High",
"confidence": "Low",
"finding": "Production adapter composition is not provenance-bound, safely evaluated, or rollback-ready."
}
}