# Extension Security Threat Model

Status: Active  
Primary bead: `bd-3jyg8`  
Last updated: 2026-02-14

## 1. Purpose and Scope

This threat model defines the security boundaries for the `pi_agent_rust` extension subsystem and related policy/risk controls.

Goals:
- Identify realistic attacker paths for install-time and runtime extension abuse.
- Map each threat to concrete controls in the Rust codebase.
- Define residual risk and ownership so follow-on hardening beads have explicit targets.

Relationship to adjacent docs:
- This document is the SEC-1.1 formal baseline for the extension ecosystem and connector abuse paths.
- `docs/extension-runtime-threat-model.md` remains a runtime-focused drill-down; where overlap exists, this document is authoritative for WS1 planning terminology and threat IDs.

In scope:
- Extension loading and compatibility scanning.
- Hostcall bridge (`pi.*`) and capability policy enforcement.
- Runtime risk controller and tamper-evident risk ledger.
- Capability decision persistence and prompt behavior.
- Secret exposure controls for environment variable access.
- Operator/incident observability generated by runtime security events.

Out of scope:
- Compromise of third-party provider accounts outside Pi runtime controls.
- Host kernel or hypervisor-level compromise.
- Physical access attacks and enterprise endpoint controls.

## 2. System Model

### 2.1 High-Level Security Topology

```text
Untrusted Extension JS/TS
        |
        |  (compat scanner + runtime bridge)
        v
QuickJS Runtime (PiJsRuntime)
        |
        | HostcallRequest {method, capability, params_hash}
        v
Shared Hostcall Dispatcher
        |
        +--> Capability Policy (allow / prompt / deny)
        |
        +--> Runtime Risk Controller (allow / harden / deny / terminate)
        |
        +--> Tool/Session/UI/Event connectors
        |
        v
Structured Logs + Risk Ledger + Persisted Decisions
```

### 2.1.1 Trust-Boundary Map (B1-B7)

```text
[B1] package source/manifest
      |
      v
Extension loader + compatibility scanner
      |
      v
[B2] QuickJS runtime ------ HostcallRequest ABI -----> [B3] Policy gate
                                                         |
                                                         v
                                               [B4] Runtime risk controller
                                                         |
                                                         v
                                            [B5] Connectors (tool/exec/http/session/ui/events)
                                                         |
                                                         v
                                          [B6] Structured logs + risk ledger + session evidence

[B7] User/operator prompt decisions <---- Permission store version-scoped grants
```

### 2.2 Security-Relevant Components (Code Anchors)

- Policy resolution and fail-closed profile fallback from config/env/CLI:
  `Config::resolve_extension_policy_with_metadata` in `src/config.rs`
- Shared hostcall dispatcher and policy gate:
  `dispatch_host_call_shared` in `src/extensions.rs`
- Runtime risk scoring, action selection, and evidence recording:
  `evaluate_runtime_risk` and `record_runtime_risk_outcome` in `src/extensions.rs`
- Hash-chained runtime risk ledger and replay/tamper checks:
  `runtime_risk_push_ledger` plus verify/replay helpers in `src/extensions.rs`
- JS hostcall capability derivation and canonical params hashing:
  `HostcallRequest::required_capability` and `HostcallRequest::params_hash` in `src/extensions_js.rs`
- Extension compatibility scanner (forbidden/flagged APIs):
  `CompatibilityScanner` in `src/extensions.rs`
- Environment variable blocklist for extension reads:
  `is_env_var_allowed` in `src/extensions_js.rs`
- Persisted capability decisions and version-scoped grants:
  `PermissionStore` in `src/permissions.rs`
- Agent wiring of resolved runtime risk config into extension manager:
  `AgentSession::enable_extensions_with_policy` in `src/agent.rs`

## 3. Security Objectives

Primary objectives:
- Prevent unauthorized capability use by untrusted extension code.
- Minimize blast radius for compromised or malicious extensions.
- Detect and respond deterministically to suspicious runtime behavior.
- Preserve forensic integrity (tamper-evident, replayable security evidence).
- Keep dangerous behavior opt-in and auditable, not implicit.

Secondary objectives:
- Preserve extension usability for benign workloads.
- Keep policy/risk decisions explainable for users and operators.

## 4. Assets and Impact Levels

| Asset | Description | Impact if compromised |
|---|---|---|
| Workspace file integrity/confidentiality | Source code, configs, generated artifacts | High |
| Local shell execution boundary | `exec` and tool-backed command execution | Critical |
| Secrets and credentials | API keys, tokens, credential env vars | Critical |
| Session and model interaction state | Conversation state, tool outputs, branch context | Medium/High |
| Policy/risk decision integrity | Security controls and evidence chain | High |
| User trust and operational continuity | Reliability and perceived safety | High |

### 4.1 Risk Quantification Bands

Impact bands:

| Band | Meaning |
|---|---|
| Medium | Localized effect, recoverable with routine intervention |
| High | Material compromise of workspace/security posture requiring coordinated response |
| Critical | Immediate security boundary failure (secrets or command boundary) with severe blast radius |

Likelihood bands:

| Band | Meaning |
|---|---|
| Rare | Requires unusual preconditions and multiple control failures |
| Unlikely | Feasible with skilled attacker but constrained by existing controls |
| Possible | Practical with realistic attacker capability and known abuse paths |
| Likely | Expected under active abuse without additional mitigations |

## 5. Trust Boundaries and Enforcement Points

| Boundary | Crossing | Primary assets at risk | Enforcement points | If violated |
|---|---|---|---|---|
| B1 | Untrusted extension source -> loader/scanner | Workspace integrity, runtime integrity | Compatibility scanner, manifest validation | Malicious code enters runtime undetected |
| B2 | QuickJS runtime -> hostcall bridge (`HostcallRequest`) | Capability model, dispatch integrity | Hostcall payload validation, required-capability derivation | Caller can spoof intent and bypass policy mapping |
| B3 | Hostcall bridge -> policy engine | Dangerous capability boundaries (`exec`, `env`) | Policy profile resolution, allow/deny/prompt checks | Dangerous calls execute despite policy |
| B4 | Policy allow path -> runtime risk controller | Runtime abuse detection and containment | Risk scoring, action selection (`harden/deny/terminate`) | Repeated abuse is not escalated or quarantined |
| B5 | Allowed action -> connectors (tool/exec/http/session/ui/events) | Filesystem, shell, secrets, session state | Connector-specific validation, timeout/cancel controls | Direct asset compromise or exfiltration |
| B6 | Security decisions/events -> ledger/persistence | Forensic integrity, auditability | Hash-chained runtime risk ledger, structured logs | Tamper or replay gaps reduce incident confidence |
| B7 | User/operator prompts -> persisted permission state | Long-lived authorization correctness | Prompt decision cache + permission store semantics | Over-grants persist and widen blast radius |

Actionable operator checks per boundary:
- B1/B2: treat scanner or hostcall validation failures as release blockers.
- B3/B4: on unexpected allow events for dangerous calls, force profile review (`safe` baseline) and investigate runtime risk logs.
- B5: treat connector parameter-validation regressions as critical-severity defects.
- B6/B7: periodically audit decision store and verify ledger continuity during incident response.

## 6. Assumptions

- Extension code is untrusted by default.
- Policy configuration may be user-modified and potentially misconfigured.
- Runtime risk scoring operates under bounded latency and can fail closed.
- Operators need deterministic traces, not probabilistic explanations.
- Existing capability prompts and persisted decisions are part of normal UX.

## 7. Attacker Classes

AC1: Malicious extension author shipping intentionally hostile logic.

AC2: Supply-chain attacker modifying extension package contents or dependency tree.

AC3: Compromised maintainer account publishing a backdoored update.

AC4: Opportunistic actor abusing benign extension bugs (path traversal, prompt confusion).

AC5: Local attacker with user-level process access attempting evidence tampering.

## 8. Threat Catalogue (Install-Time + Runtime)

Install-time vectors covered here:
- Extension package/dependency tampering and unsafe API surfacing (T1, T8).
- Policy/profile drift introduced through configuration changes before runtime (T3).

Runtime vectors covered here:
- Hostcall ABI abuse, capability mismatch, and connector misuse (T2, T6, T7).
- Behavioral abuse after successful load, including bursty dangerous calls (T4, T5).

### 8.1 Attack Path Inventory

| Path ID | Attack path | Primary stage | Typical attacker class(es) | Security objective targeted |
|---|---|---|---|---|
| AP1 | Supply-chain insertion into extension package/dependency artifact | Install/update | AC2, AC3 | Extension/runtime integrity |
| AP2 | Runtime hostcall abuse after benign-looking load | Runtime | AC1, AC4 | Capability containment |
| AP3 | Privilege escalation from low-risk to dangerous capability surface | Runtime | AC1, AC4 | Policy correctness |
| AP4 | Secret exfiltration through env/connector outputs | Runtime | AC1, AC4 | Secret protection |
| AP5 | Decision/ledger tampering to reduce forensic visibility | Runtime/post-incident | AC5 | Evidence integrity |
| AP6 | Human-in-the-loop over-grant persistence through prompt fatigue | Runtime/operations | AC4 | Least privilege durability |

### 8.2 Threat Rating Summary (Inherent Risk)

| Threat | Primary stage | Likelihood | Impact | Inherent risk |
|---|---|---|---|---|
| T1 forbidden APIs/imports | Install-time + load-time | Possible | High | High |
| T2 capability mismatch abuse | Runtime | Unlikely | Critical | High |
| T3 dangerous capability misconfig | Config/runtime | Possible | Critical | Critical |
| T4 runtime abuse after passing scan | Runtime | Possible | Critical | Critical |
| T5 decision/evidence tampering | Runtime/post-runtime | Unlikely | High | High |
| T6 env-based secret exfiltration | Runtime | Possible | Critical | Critical |
| T7 persistent over-grant from prompts | Runtime/human workflow | Likely | High | High |
| T8 update/provenance drift | Install/update | Possible | High | High |

### T1. Malicious Extension Imports Forbidden Native/Unsafe APIs

Vector:
- Extension imports or references forbidden APIs (`process.binding`, `process.dlopen`) or high-risk dynamic execution patterns.

Controls:
- Compatibility scanner classifies forbidden and flagged patterns and records evidence in `CompatLedger`.
- Static rules for forbidden builtins and suspicious dynamic APIs.

Code:
- `src/extensions.rs` (`CompatibilityScanner`, forbidden/flagged rules).

Residual risk:
- Obfuscation/minification may evade simple lexical detectors; mitigated by runtime policy/risk layers.

### T2. Capability Escalation via Hostcall Method/Capability Mismatch

Vector:
- Extension attempts to request privileged behavior while declaring lower-risk capability metadata.

Controls:
- Required capability is derived from hostcall kind/tool name, not trusted from extension-provided labels.
- Shared dispatch enforces policy against derived capability.

Code:
- `src/extensions_js.rs` (`HostcallRequest::required_capability`).
- `src/extensions.rs` (`dispatch_host_call_shared` and policy checks).

Residual risk:
- Future connector additions could introduce mapping gaps if not covered by tests.

### T3. Dangerous Capability Misconfiguration (`exec`, `env`)

Vector:
- Profile/configuration drift enables dangerous operations unintentionally.

Controls:
- Unknown policy profiles fail closed to `safe`.
- Defaults deny dangerous capabilities (`exec`, `env`) unless explicit override.
- `allowDangerous` must be explicit (`config`/env).

Code:
- `src/config.rs` (`resolve_extension_policy_with_metadata`).
- `src/extensions.rs` (`PolicyProfile`, `ExtensionPolicy::default`).

Residual risk:
- Human misconfiguration remains possible; needs clear UX and rollout guardrails.

### T4. Runtime Abuse Despite Passing Static Scan

Vector:
- Signed/benign-looking extension performs risky behavior at runtime (bursts, anomalous transitions, repeated dangerous calls).

Controls:
- Deterministic runtime risk controller computes risk score, posterior, and action.
- Actions include `Allow`, `Harden`, `Deny`, `Terminate`.
- Quarantine behavior after repeated unsafe outcomes.

Code:
- `src/extensions.rs` (`evaluate_runtime_risk`, `record_runtime_risk_outcome`).

Residual risk:
- Controller sensitivity/specificity tuning is ongoing; requires WS6 calibration evidence.

### T5. Decision/Evidence Tampering

Vector:
- Attacker attempts to rewrite decision history to hide malicious behavior.

Controls:
- Runtime risk ledger entries are hash-chained with previous hash linkage.
- Verification/replay functions detect chain mismatch and reconstruct decision path.

Code:
- `src/extensions.rs` (`runtime_risk_compute_ledger_hash`, verify/replay helpers).

Residual risk:
- In-memory ledger is bounded; long history needs external archival/export workflows.

### T6. Secret Exfiltration Through Environment Access

Vector:
- Extension reads credentials via `pi.env` or equivalent environment access paths.

Controls:
- Environment variable filtering blocklists known sensitive exact names, suffixes, prefixes.
- Policy still gates `env` capability separately.

Code:
- `src/extensions_js.rs` (`is_env_var_allowed`).
- `src/extensions.rs` policy enforcement path.

Residual risk:
- Unknown secret naming conventions can bypass simple name-based blocklists.

### T7. Persistent Over-Grant from Capability Prompts

Vector:
- User grants permanent capability without understanding risk; grant persists.

Controls:
- Permission store keyed by `(extension_id, capability)` with optional version/expiry semantics.
- Deny fallback when prompt/UI path is unavailable.

Code:
- `src/permissions.rs`.
- `src/extensions.rs` prompt-resolution/policy handling.

Residual risk:
- Social engineering and prompt fatigue remain human-layer risks.

### T8. Install/Update Drift and Provenance Ambiguity

Vector:
- Extension updates change behavior without clear provenance controls.

Controls (current + planned):
- Current: deterministic package lockfile, fail-closed digest/provenance verification, and trust-transition audit ledger (`.pi/packages.lock.json`, `.pi/package-trust-audit.jsonl`).
- Current: extension scanner/ledger evidence path in runtime.
- Planned: quarantine-to-trust promotion workflow (SEC-2.4).

Code / Tracking:
- Lock/provenance pipeline in `src/package_manager.rs` and docs in `docs/packages.md`.
- Existing scanner in `src/extensions.rs`.
- Remaining follow-on tracked in `bd-21nj4`.

Residual risk:
- Quarantine/promotion controls are still pending; lock/provenance verification now blocks mismatches by default.

### 8.3 Threat Likelihood and Impact Quantification

| Threat | Phase | Likelihood | Impact | Risk band | Rationale |
|---|---|---|---|---|---|
| T1 forbidden imports/APIs | Install-time | Possible | High | High | Straightforward attacker path; scanner reduces but does not eliminate bypass risk |
| T2 capability mismatch | Runtime | Unlikely | Critical | High | Strong derived-capability checks exist; bypass would directly cross execution boundary |
| T3 dangerous misconfig | Install-time/runtime | Possible | Critical | Critical | Human/config drift remains realistic and can expose dangerous capabilities |
| T4 runtime abuse post-load | Runtime | Possible | Critical | Critical | Practical abuse path for compromised extensions; controller is still being tuned |
| T5 evidence tampering | Runtime/post-incident | Unlikely | High | High | Hash-chaining helps, but bounded in-memory evidence and ops gaps remain |
| T6 env secret exfiltration | Runtime | Possible | Critical | Critical | Naming-based blocklists can miss novel secret keys |
| T7 persistent over-grant | Runtime/operations | Likely | High | High | Prompt fatigue and permissive user decisions are common operational failure modes |
| T8 provenance/update drift | Install/update-time | Unlikely | High | High | Fail-closed lockfile/provenance checks are in place; quarantine workflow remains pending |

## 9. Threat-to-Control Matrix

| Threat | Primary prevention | Primary detection | Primary response |
|---|---|---|---|
| T1 forbidden imports/APIs | Compatibility scanner | Scanner evidence ledger | Deny load/promotion (policy + ops) |
| T2 capability mismatch | Derived required capability mapping | Structured hostcall logs | Deny request |
| T3 dangerous misconfig | Safe defaults + fail-closed profile parse | Explain-policy diagnostics | Revert to safe profile |
| T4 runtime abuse | Policy gate + least privilege | Runtime risk controller | Harden/Deny/Terminate |
| T5 evidence tampering | Hash chaining | Ledger verify/replay | Incident escalation |
| T6 secret exfil | Env blocklist + `env` policy gate | Hostcall + risk logs | Deny/Harden + revoke decisions |
| T7 over-grant prompts | Prompt workflow + decision store | Audit of persisted decisions | Revoke/reset permissions |
| T8 update/provenance drift | Scanner + deterministic lockfile/provenance verification | Lockfile + trust audit JSONL + artifact diff | Quarantine/promotion workflow |

## 10. Abuse Cases and Expected Outcomes

Representative abuse cases:
- Extension attempts repeated `exec` in risky burst pattern -> runtime risk should escalate to deny/terminate.
- Extension imports `process.binding` -> scanner must emit forbidden evidence.
- Extension requests `env` access for blocked secret names -> value access denied.
- Unknown policy profile token in config/env -> effective profile must fail closed to safe.

## 11. Residual Risks and Owners

| Residual risk | Current state | Owner role | Follow-on beads |
|---|---|---|---|
| Supply-chain provenance/lock completeness | In progress (lock/provenance done, quarantine pending) | WS2 lead | `bd-21nj4` |
| Runtime threshold calibration for low FP/FN | In progress | WS3/WS6 leads | `bd-3i9da`, `bd-cu17q`, `bd-2vlb5` |
| Secret-name blocklist coverage gaps | Partial | WS4 lead | `bd-zh0hj`, `bd-wzzp4` |
| Prompt fatigue / trust UX clarity | Partial | WS5 lead | `bd-qudx1`, `bd-ww5br` |
| Incident evidence portability and replay ergonomics | In progress | WS5/WS7 leads | `bd-11mqo`, `bd-2kle2` |

## 12. Security Invariants (Draft)

Canonical precedence semantics and machine-checkable invariant mappings now live in `docs/security/invariants.md` (SEC-1.2).

I1: Unknown extension policy profile names must fail closed to `safe`.

I2: Dangerous capabilities (`exec`, `env`) are never implicitly allowed by default.

I3: Hostcall capability enforcement uses derived capability mapping, not caller-provided trust.

I4: Runtime risk controller actions are deterministic for identical inputs and config.

I5: Risk ledger is tamper-evident via hash chain and replay-verifiable.

I6: Sensitive environment variables are denied regardless of extension intent.

I7: Policy and risk decisions are observable through structured logs.

## 13. Verification and Evidence Plan

### 13.1 Threat-to-Test Traceability

| Threat | Deterministic test evidence (current) | Intent |
|---|---|---|
| T1 forbidden imports/APIs | `src/extensions.rs::compatibility_scanner_ignores_commented_patterns`; `src/extensions.rs::compatibility_scanner_still_reports_live_code_with_nearby_comments`; `src/extensions.rs::compatibility_scanner_keeps_late_requires_in_minified_lines` | Scanner catches live risky patterns and avoids comment false positives |
| T2 capability mismatch | `src/extensions.rs::required_capability_for_host_call_maps_tools_and_fs_ops`; `tests/extensions_policy_negative.rs::hostcall_exec_maps_to_exec_capability`; `tests/extensions_policy_negative.rs::hostcall_unknown_method_returns_none` | Hostcall mapping is authoritative and rejects ambiguous methods |
| T3 dangerous misconfig | `src/config.rs::extension_policy_metadata_unknown_profile_falls_back_to_safe`; `tests/config_edge_cases.rs::extension_policy_unknown_profile_falls_back_to_safe`; `tests/capability_policy_scoped.rs::default_config_resolves_to_permissive` | Unknown profiles fail closed to safe, and strict mode remains explicitly selectable when permissive compatibility defaults are too broad |
| T4 runtime abuse post-load | `src/extensions.rs::shared_dispatch_runtime_risk_hardens_exec_calls`; `src/extensions.rs::shared_dispatch_runtime_risk_quarantines_repeated_unsafe_attempts` | Deterministic runtime risk actions escalate under hostile behavior |
| T5 decision/evidence tampering | `src/extensions.rs::shared_dispatch_runtime_risk_ledger_is_tamper_evident`; `src/extensions.rs::shared_dispatch_runtime_risk_ledger_replay_reconstructs_decision_path`; `src/extensions.rs::shared_dispatch_runtime_risk_ledger_verifies_after_ring_buffer_truncation` | Hash chain detects tamper and replay is deterministic even with truncation |
| T6 env secret exfiltration | `src/extensions_js.rs::pijs_env_get_honors_allowlist`; `src/extensions.rs::wasm_host_env_denied_by_policy_even_when_allowlisted`; `tests/extensions_policy_negative.rs::deny_caps_env_denied_in_all_modes` | Secret reads require allowlist and capability gate alignment |
| T7 persistent over-grant | `src/extensions.rs::js_hostcall_prompt_mode_asks_once_per_capability`; `src/extensions.rs::js_hostcall_prompt_policy_caches_user_allow_and_never_logs_raw_params`; `src/permissions.rs::record_and_lookup` | Prompt decisions are cached per capability and persisted deterministically |
| T8 provenance/update drift | `tests/ext_provenance_verification.rs::provenance_verification_evidence_log`; `tests/ext_conformance_artifacts.rs` checksum/corpus validation suite | Artifact drift is detectable via deterministic provenance checks |

### 13.2 E2E Security Evidence Contract

For SEC WS6 and adversarial corpus execution (`bd-3jpm3` and dependents), every e2e security run must emit JSONL records containing:

| Field | Type | Requirement |
|---|---|---|
| `timestamp` | RFC3339 string | Event time in UTC |
| `issue_id` | string | Bead identifier (for this workstream, `bd-3jyg8` lineage) |
| `extension_id` | string | Stable extension identity under test |
| `capability` | string | Evaluated capability token (for example `exec`, `env`) |
| `policy_profile` | string | Effective policy profile (`safe`, `balanced`, `permissive`) |
| `score` | number | Runtime risk score used by action policy |
| `reason_codes` | string[] | Deterministic reason taxonomy for allow/deny/escalation |
| `action` | string | Selected action (`allow`, `harden`, `deny`, `terminate`) |
| `latency_ms` | number | End-to-end decision latency for the event |
| `correlation_id` | string | Cross-log join key for a scenario run |
| `redaction_summary` | object | What was redacted and why (no raw secrets/params) |

Required scenario classes:
- Benign baseline flow: normal extension behavior remains functional under `safe` and `balanced`.
- Adversarial flow: malicious patterns trigger deny/harden/terminate with expected reason codes.
- Rollback/recovery flow: policy/risk rollback restores expected behavior without stale over-grants.

### 13.3 Quality Gates

```bash
cargo fmt --check
cargo check --all-targets
cargo clippy --all-targets -- -D warnings
cargo test
```

### 13.4 SEC-1.1 Scope Note

`bd-3jyg8` is a formal-baseline documentation bead. It does not itself modify runtime behavior.
Therefore, unit/e2e additions are specified as explicit traceability and evidence contracts in this document, while runtime test implementation is executed in dependent beads (`bd-2ezm9`, `bd-3jpm3`, WS6 calibration/observability beads).

## 14. Change Control Notes

- This document is the formal threat baseline for SEC WS1 and should be updated before any major policy/risk architecture change.
- If a new connector/hostcall class is introduced, update:
  - attacker goals,
  - trust boundaries,
  - threat matrix,
  - invariants,
  - verification plan.

## 15. Artifact Manifest

| Artifact | Role | Determinism rule |
|---|---|---|
| `docs/security/threat-model.md` | SEC-1.1 canonical threat baseline | Hash via `sha256sum docs/security/threat-model.md` and record in bead comments |
| `docs/security/invariants.md` | SEC-1.2 canonical invariants + precedence semantics | Hash via `sha256sum docs/security/invariants.md` and record in bead comments |
