SEC-7.3 (bd-2kle2) -- Step-by-step procedures for common security incident categories.
- General Incident Workflow
- INC-1: Unauthorized Capability Use
- INC-2: Secret Exposure
- INC-3: Ledger Integrity Failure
- INC-4: Scanner Bypass
- INC-5: Quarantine Escape
- INC-6: Resource Quota Abuse
- Evidence Collection
- Rollback Procedures
Every incident follows this sequence regardless of classification:
DETECT → CONTAIN → COLLECT → VERIFY → ANALYZE → REMEDIATE → POSTMORTEM
| Phase | SLA | Actions |
|---|---|---|
| Detect | Automatic | Alert raised by risk controller or CI gate |
| Contain | < 5 min | Kill extension, verify isolation |
| Collect | < 15 min | Export evidence bundle, snapshot config |
| Verify | < 30 min | Verify bundle hash, ledger chain, alert counts |
| Analyze | < 2 hours | Root cause analysis with forensic replay |
| Remediate | Varies | Policy update, scanner rule, bead filed |
| Postmortem | < 24 hours | Written, reviewed, artifacts archived |
Symptoms: Policy violation alert; a denied capability was somehow exercised.
-
Identify the call.
- Check security alerts filtered by category
policy_violation - Note the
extension_id,capability,method, andcall_id
- Check security alerts filtered by category
-
Check policy evaluation path.
pi --explain-extension-policy
- Verify the capability is in
deny_caps - Check if per-extension overrides exist for this extension
- Verify the capability is in
-
Examine the dispatch path.
- If the call succeeded despite a Deny decision, this indicates a bypass in the dispatch pipeline
- Check
dispatch_host_call_shared()-- the capability must be derived server-side viarequired_capability_for_host_call_static(), NOT from the caller'scapabilityfield
-
Verify invariants.
cargo test --test policy_profile_hardening -- --nocapture cargo test --test capability_denial_matrix -- --nocapture
- Security alert with category
policy_violation - Risk ledger entry showing the denied call
- Policy explanation snapshot at time of incident
- If policy misconfiguration: fix config, verify with
--explain-extension-policy - If bypass bug: file Critical bead, add regression test in
capability_denial_matrix.rs - Reference: Invariant INV-001 (policy precedence chain)
Symptoms: Secret broker alert; environment variable value exposed to an extension.
-
Identify the exposure.
- Check alerts with category
secret_exposure - Determine which env var was exposed and to which extension
- Check alerts with category
-
Check the secret broker configuration.
- Default blocklist: 26 exact names, 11 suffixes (
*_API_KEY,*_SECRET, etc.), 2 prefixes - Verify the exposed variable matches a blocklist pattern
- Check if the variable was in the
disclosure_allowlist(intentional pass-through)
- Default blocklist: 26 exact names, 11 suffixes (
-
Verify the broker was enabled.
SecretBrokerPolicy.enabledmust betrue- Check
secret_broker_enabledin the policy explanation
-
Examine the exposure path.
- Was it via
env.readhostcall? - Was it via
exec(child process inheriting env)? - Was it via
http(sent as header/body)?
- Was it via
- Secret broker ledger entry with
name_hashof the exposed variable - Alert with category
secret_exposure - Incident evidence bundle with
secret_brokersection populated
- Immediate: Rotate the exposed credential
- Short-term: Add the variable pattern to the blocklist if not already covered
- Long-term: If exposure was via
exec, verify exec mediation blocks env passthrough - Reference: Invariant INV-009 (secret broker coverage)
Symptoms: Hash chain verification fails; verify_runtime_risk_ledger_artifact() reports errors.
-
Run ledger verification. The verification function checks:
- Schema version matches expected
- Each entry's
ledger_hashmatches recomputed hash - Chain linkage: each
prev_ledger_hashmatches the prior entry's hash - No missing or duplicate entries
-
Identify the break point.
- Check
verification_errorsin the report - The first broken link indicates where tampering or corruption occurred
- Check
-
Distinguish corruption from tampering.
- Corruption: Typically a single entry with bad hash (memory issue, serialization bug)
- Tampering: Modified/removed entries break the chain at the point of alteration
-
Forensic replay.
- Replay the ledger up to the break point to reconstruct valid history
- Entries after the break are untrusted and must be re-evaluated
-
RuntimeRiskLedgerVerificationReportwithchain_valid: false - Specific
verification_errorslisting broken entries - Evidence bundle with
risk_ledgersection
- If corruption: investigate OOM or serialization bugs, file bead
- If tampering: this is Critical severity -- full security audit required
- Reference: Invariant INV-010 (ledger integrity)
Symptoms: Malicious or dangerous code was loaded despite compatibility scanning.
-
Examine the extension source.
- Check for forbidden imports that the scanner should have caught:
process.binding,eval,Function(),require('child_process'), etc.
- Check for forbidden imports that the scanner should have caught:
-
Review scan results.
- The
CompatibilityScannerclassifies entries asforbidden,flagged, orsafe - Check if the dangerous pattern was in a form the scanner doesn't recognize
- The
-
Test scanner detection.
cargo test --test install_time_security_scanner -- --nocapture -
Check for evasion techniques.
- Dynamic requires:
require(variable)vsrequire('child_process') - String concatenation:
eval('rm' + ' -rf') - Encoded payloads: base64 or unicode escape sequences
- Prototype pollution paths
- Dynamic requires:
- Scanner results for the extension (compat ledger)
- The extension source code
- Evidence of what the extension actually executed
- Add the evasion pattern to the scanner's forbidden/flagged patterns
- Add a regression test in
install_time_security_scanner.rs - Reference: SLO-02 (scanner detection >= 95%)
Symptoms: An extension marked as quarantined resumed execution without explicit trust promotion.
-
Check trust state transitions.
ExtensionTrustTrackermanages the state machine: Unknown -> Probation -> Trusted / Quarantined- Verify the state transition log shows Quarantined -> Active without a valid promotion
-
Check the kill-switch state.
- If a kill-switch was active, verify it was not prematurely lifted
- Kill-switch lifted events should include audit metadata
-
Verify
is_hostcall_allowed_for_trust()enforcement.- This function gates hostcalls based on trust state
- Quarantined extensions should be blocked from all hostcalls
- Trust state transition history
- Kill-switch activation/deactivation events
- Security alerts with the quarantined extension's ID
- If state machine bug: fix the transition logic, add regression test
- If promotion was unauthorized: investigate who/what triggered it
- Reference: Threat T4 (runtime abuse escalation)
Symptoms: Extension exceeds resource quotas (memory, API calls, time).
-
Check quota breach events.
drain_quota_breach_events()returns all recorded breaches- Each breach includes: extension_id, resource type, limit, actual, timestamp
-
Verify quota configuration.
- Default:
max_memory_mb: 256 - Per-extension overrides via
ExtensionOverride.quota
- Default:
-
Assess impact.
- Did the breach cause OOM? Check system logs
- Did it degrade other extensions? Check isolation
- Quota breach events in incident evidence bundle
- Memory/resource usage telemetry
- Alert with category
quota_breach
- Tighten quota for the offending extension
- If legitimate high usage: increase quota with documentation
- Reference: SLO-14 (runtime overhead <= 3%)
The incident evidence bundle aggregates all security artifacts into a single, hash-verified package.
Components included:
- Runtime risk ledger (hash-chained entries)
- Security alerts (filtered by time/extension/category/severity)
- Hostcall telemetry (call timing and context)
- Exec mediation log (command allow/deny decisions)
- Secret broker log (redaction events)
- Quota breach events
- Risk replay (reconstructed decision timeline)
- Summary statistics
Bundle integrity:
bundle_hash: SHA-256 over all content sectionsschema:pi.security.incident_evidence_bundle.v1- Verify with
verify_incident_evidence_bundle()
Bundles support scoping via IncidentBundleFilter:
start_ms/end_ms: Time rangeextension_id: Specific extensionalert_categories: Specific alert typesmin_severity: Minimum severity threshold
Bundles support redaction via IncidentBundleRedactionPolicy:
redact_params_hash: Redact parameter fingerprintsredact_context_hash: Redact context hashesredact_args_shape_hash: Redact argument shape hashesredact_command_hash: Redact command hashesredact_name_hash: Redact name hashesredact_remediation: Redact remediation text
Use full redaction for external sharing; use no redaction for internal forensics.
After collecting evidence:
- Verify bundle hash matches recomputed hash
- Verify ledger chain integrity (no broken links)
- Verify summary counts match actual sub-artifact counts
- Verify schema version matches expected
- If redaction was applied, verify no raw values leak
// Before: settings.json (problematic)
{
"extensionPolicy": {
"profile": "permissive",
"allowDangerous": true
}
}
// After: rollback to safe defaults
{
"extensionPolicy": {
"profile": "safe",
"allowDangerous": false
}
}Verification:
pi --explain-extension-policy # Confirm safe profile active
cargo test --test security_conformance_benign -- --nocapture # Confirm compatibility// Revert to defaults
{
"extensionRisk": {
"enabled": false,
"enforce": true,
"alpha": 0.01,
"windowSize": 128,
"failClosed": true
}
}Or disable entirely: set enabled: false. The controller stops scoring but existing ledger entries are preserved.
pi --no-extensions # Disable all extension discovery and loadingThis is the nuclear option. Use only when containment requires complete extension isolation.