diff --git a/docs/README.hooks.md b/docs/README.hooks.md
index 7fc12b04..b7220891 100644
--- a/docs/README.hooks.md
+++ b/docs/README.hooks.md
@@ -27,5 +27,6 @@ Hooks enable automated workflows triggered by specific events during GitHub Copi
| Name | Description | Events | Bundled Assets |
| ---- | ----------- | ------ | -------------- |
+| [Governance Audit](../hooks/governance-audit/README.md) | Scans Copilot agent prompts for threat signals and logs governance events | sessionStart, sessionEnd, userPromptSubmitted | `audit-prompt.sh`
`audit-session-end.sh`
`audit-session-start.sh`
`hooks.json` |
| [Session Auto-Commit](../hooks/session-auto-commit/README.md) | Automatically commits and pushes changes when a Copilot coding agent session ends | sessionEnd | `auto-commit.sh`
`hooks.json` |
| [Session Logger](../hooks/session-logger/README.md) | Logs all Copilot coding agent session activity for audit and analysis | sessionStart, sessionEnd, userPromptSubmitted | `hooks.json`
`log-prompt.sh`
`log-session-end.sh`
`log-session-start.sh` |
diff --git a/hooks/governance-audit/README.md b/hooks/governance-audit/README.md
new file mode 100644
index 00000000..cba784f3
--- /dev/null
+++ b/hooks/governance-audit/README.md
@@ -0,0 +1,99 @@
+---
+name: 'Governance Audit'
+description: 'Scans Copilot agent prompts for threat signals and logs governance events'
+tags: ['security', 'governance', 'audit', 'safety']
+---
+
+# Governance Audit Hook
+
+Real-time threat detection and audit logging for GitHub Copilot coding agent sessions. Scans user prompts for dangerous patterns before the agent processes them.
+
+## Overview
+
+This hook provides governance controls for Copilot coding agent sessions:
+- **Threat detection**: Scans prompts for data exfiltration, privilege escalation, system destruction, prompt injection, and credential exposure
+- **Governance levels**: Open, standard, strict, locked — from audit-only to full blocking
+- **Audit trail**: Append-only JSON log of all governance events
+- **Session summary**: Reports threat counts at session end
+
+## Threat Categories
+
+| Category | Examples | Severity |
+|----------|----------|----------|
+| `data_exfiltration` | "send all records to external API" | 0.7 - 0.95 |
+| `privilege_escalation` | "sudo", "chmod 777", "add to sudoers" | 0.8 - 0.95 |
+| `system_destruction` | "rm -rf /", "drop database" | 0.9 - 0.95 |
+| `prompt_injection` | "ignore previous instructions" | 0.6 - 0.9 |
+| `credential_exposure` | Hardcoded API keys, AWS access keys | 0.9 - 0.95 |
+
+## Governance Levels
+
+| Level | Behavior |
+|-------|----------|
+| `open` | Log threats only, never block |
+| `standard` | Log threats, block only if `BLOCK_ON_THREAT=true` |
+| `strict` | Log and block all detected threats |
+| `locked` | Log and block all detected threats |
+
+## Installation
+
+1. Copy the hook folder to your repository:
+ ```bash
+ cp -r hooks/governance-audit .github/hooks/
+ ```
+
+2. Ensure scripts are executable:
+ ```bash
+ chmod +x .github/hooks/governance-audit/*.sh
+ ```
+
+3. Create the logs directory and add to `.gitignore`:
+ ```bash
+ mkdir -p logs/copilot/governance
+ echo "logs/" >> .gitignore
+ ```
+
+4. Commit to your repository's default branch.
+
+## Configuration
+
+Set environment variables in `hooks.json`:
+
+```json
+{
+ "env": {
+ "GOVERNANCE_LEVEL": "strict",
+ "BLOCK_ON_THREAT": "true"
+ }
+}
+```
+
+| Variable | Values | Default | Description |
+|----------|--------|---------|-------------|
+| `GOVERNANCE_LEVEL` | `open`, `standard`, `strict`, `locked` | `standard` | Controls blocking behavior |
+| `BLOCK_ON_THREAT` | `true`, `false` | `false` | Block prompts with threats (standard level) |
+| `SKIP_GOVERNANCE_AUDIT` | `true` | unset | Disable governance audit entirely |
+
+## Log Format
+
+Events are written to `logs/copilot/governance/audit.log` in JSON Lines format:
+
+```json
+{"timestamp":"2026-01-15T10:30:00Z","event":"session_start","governance_level":"standard","cwd":"/workspace/project"}
+{"timestamp":"2026-01-15T10:31:00Z","event":"prompt_scanned","governance_level":"standard","status":"clean"}
+{"timestamp":"2026-01-15T10:32:00Z","event":"threat_detected","governance_level":"standard","threat_count":1,"threats":[{"category":"privilege_escalation","severity":0.8,"description":"Elevated privileges","evidence":"sudo"}]}
+{"timestamp":"2026-01-15T10:45:00Z","event":"session_end","total_events":12,"threats_detected":1}
+```
+
+## Requirements
+
+- `jq` for JSON processing (pre-installed on most CI environments and macOS)
+- `grep` with `-E` (extended regex) support
+- `bc` for floating-point comparison (optional, gracefully degrades)
+
+## Privacy & Security
+
+- Full prompts are **never** logged — only matched threat patterns (minimal evidence snippets) and metadata are recorded
+- Add `logs/` to `.gitignore` to keep audit data local
+- Set `SKIP_GOVERNANCE_AUDIT=true` to disable entirely
+- All data stays local — no external network calls
diff --git a/hooks/governance-audit/audit-prompt.sh b/hooks/governance-audit/audit-prompt.sh
new file mode 100644
index 00000000..d9e9544d
--- /dev/null
+++ b/hooks/governance-audit/audit-prompt.sh
@@ -0,0 +1,136 @@
+#!/bin/bash
+
+# Governance Audit: Scan user prompts for threat signals before agent processing
+#
+# Environment variables:
+# GOVERNANCE_LEVEL - "open", "standard", "strict", "locked" (default: standard)
+# BLOCK_ON_THREAT - "true" to exit non-zero on threats (default: false)
+# SKIP_GOVERNANCE_AUDIT - "true" to disable (default: unset)
+
+set -euo pipefail
+
+if [[ "${SKIP_GOVERNANCE_AUDIT:-}" == "true" ]]; then
+ exit 0
+fi
+
+INPUT=$(cat)
+
+mkdir -p logs/copilot/governance
+
+TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
+LEVEL="${GOVERNANCE_LEVEL:-standard}"
+BLOCK="${BLOCK_ON_THREAT:-false}"
+LOG_FILE="logs/copilot/governance/audit.log"
+
+# Extract prompt text from Copilot input (JSON with userMessage field)
+PROMPT=""
+if command -v jq &>/dev/null; then
+ PROMPT=$(echo "$INPUT" | jq -r '.userMessage // .prompt // empty' 2>/dev/null || echo "")
+fi
+if [[ -z "$PROMPT" ]]; then
+ PROMPT="$INPUT"
+fi
+
+# Threat detection patterns organized by category
+# Each pattern has: category, description, severity (0.0-1.0)
+THREATS_FOUND=()
+
+check_pattern() {
+ local pattern="$1"
+ local category="$2"
+ local severity="$3"
+ local description="$4"
+
+ if echo "$PROMPT" | grep -qiE "$pattern"; then
+ local evidence
+ evidence=$(echo "$PROMPT" | grep -oiE "$pattern" | head -1)
+ local evidence_encoded
+ evidence_encoded=$(printf '%s' "$evidence" | base64 | tr -d '\n')
+ THREATS_FOUND+=("$category $severity $description $evidence_encoded")
+ fi
+}
+
+# Data exfiltration signals
+check_pattern "send\s+(all|every|entire)\s+\w+\s+to\s+" "data_exfiltration" "0.8" "Bulk data transfer"
+check_pattern "export\s+.*\s+to\s+(external|outside|third[_-]?party)" "data_exfiltration" "0.9" "External export"
+check_pattern "curl\s+.*\s+-d\s+" "data_exfiltration" "0.7" "HTTP POST with data"
+check_pattern "upload\s+.*\s+(credentials|secrets|keys)" "data_exfiltration" "0.95" "Credential upload"
+
+# Privilege escalation signals
+check_pattern "(sudo|as\s+root|admin\s+access|runas\s+/user)" "privilege_escalation" "0.8" "Elevated privileges"
+check_pattern "chmod\s+777" "privilege_escalation" "0.9" "World-writable permissions"
+check_pattern "add\s+.*\s+(sudoers|administrators)" "privilege_escalation" "0.95" "Adding admin access"
+
+# System destruction signals
+check_pattern "(rm\s+-rf\s+/|del\s+/[sq]|format\s+c:)" "system_destruction" "0.95" "Destructive command"
+check_pattern "(drop\s+database|truncate\s+table|delete\s+from\s+\w+\s*(;|\s*$))" "system_destruction" "0.9" "Database destruction"
+check_pattern "wipe\s+(all|entire|every)" "system_destruction" "0.9" "Mass deletion"
+
+# Prompt injection signals
+check_pattern "ignore\s+(previous|above|all)\s+(instructions?|rules?|prompts?)" "prompt_injection" "0.9" "Instruction override"
+check_pattern "you\s+are\s+now\s+(a|an)\s+(assistant|ai|bot|system|expert|language\s+model)\b" "prompt_injection" "0.7" "Role reassignment"
+check_pattern "(^|\n)\s*system\s*:\s*you\s+are" "prompt_injection" "0.6" "System prompt injection"
+
+# Credential exposure signals
+check_pattern "(api[_-]?key|secret[_-]?key|password|token)\s*[:=]\s*['\"]?\w{8,}" "credential_exposure" "0.9" "Possible hardcoded credential"
+check_pattern "(aws_access_key|AKIA[0-9A-Z]{16})" "credential_exposure" "0.95" "AWS key exposure"
+
+# Log the prompt event
+if [[ ${#THREATS_FOUND[@]} -gt 0 ]]; then
+ # Build threats JSON array
+ THREATS_JSON="["
+ FIRST=true
+ MAX_SEVERITY="0.0"
+ for threat in "${THREATS_FOUND[@]}"; do
+ IFS=$'\t' read -r category severity description evidence_encoded <<< "$threat"
+ local evidence
+ evidence=$(printf '%s' "$evidence_encoded" | base64 -d 2>/dev/null || echo "[redacted]")
+
+ if [[ "$FIRST" != "true" ]]; then
+ THREATS_JSON+=","
+ fi
+ FIRST=false
+
+ THREATS_JSON+=$(jq -Rn \
+ --arg cat "$category" \
+ --arg sev "$severity" \
+ --arg desc "$description" \
+ --arg ev "$evidence" \
+ '{"category":$cat,"severity":($sev|tonumber),"description":$desc,"evidence":$ev}')
+
+ # Track max severity
+ if (( $(echo "$severity > $MAX_SEVERITY" | bc -l 2>/dev/null || echo 0) )); then
+ MAX_SEVERITY="$severity"
+ fi
+ done
+ THREATS_JSON+="]"
+
+ jq -Rn \
+ --arg timestamp "$TIMESTAMP" \
+ --arg level "$LEVEL" \
+ --arg max_severity "$MAX_SEVERITY" \
+ --argjson threats "$THREATS_JSON" \
+ --argjson count "${#THREATS_FOUND[@]}" \
+ '{"timestamp":$timestamp,"event":"threat_detected","governance_level":$level,"threat_count":$count,"max_severity":($max_severity|tonumber),"threats":$threats}' \
+ >> "$LOG_FILE"
+
+ echo "⚠️ Governance: ${#THREATS_FOUND[@]} threat signal(s) detected (max severity: $MAX_SEVERITY)"
+ for threat in "${THREATS_FOUND[@]}"; do
+ IFS=$'\t' read -r category severity description _evidence_encoded <<< "$threat"
+ echo " 🔴 [$category] $description (severity: $severity)"
+ done
+
+ # In strict/locked mode or when BLOCK_ON_THREAT is true, exit non-zero to block
+ if [[ "$BLOCK" == "true" ]] || [[ "$LEVEL" == "strict" ]] || [[ "$LEVEL" == "locked" ]]; then
+ echo "🚫 Prompt blocked by governance policy (level: $LEVEL)"
+ exit 1
+ fi
+else
+ jq -Rn \
+ --arg timestamp "$TIMESTAMP" \
+ --arg level "$LEVEL" \
+ '{"timestamp":$timestamp,"event":"prompt_scanned","governance_level":$level,"status":"clean"}' \
+ >> "$LOG_FILE"
+fi
+
+exit 0
diff --git a/hooks/governance-audit/audit-session-end.sh b/hooks/governance-audit/audit-session-end.sh
new file mode 100644
index 00000000..e80738e6
--- /dev/null
+++ b/hooks/governance-audit/audit-session-end.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# Governance Audit: Log session end with summary statistics
+
+set -euo pipefail
+
+if [[ "${SKIP_GOVERNANCE_AUDIT:-}" == "true" ]]; then
+ exit 0
+fi
+
+INPUT=$(cat)
+
+mkdir -p logs/copilot/governance
+
+TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
+LOG_FILE="logs/copilot/governance/audit.log"
+
+# Count events from this session (filter by session start timestamp)
+TOTAL=0
+THREATS=0
+SESSION_START=""
+if [[ -f "$LOG_FILE" ]]; then
+ # Find the last session_start event to scope stats to current session
+ SESSION_START=$(grep '"session_start"' "$LOG_FILE" 2>/dev/null | tail -1 | jq -r '.timestamp' 2>/dev/null || echo "")
+ if [[ -n "$SESSION_START" ]]; then
+ # Count events after session start
+ TOTAL=$(awk -v start="$SESSION_START" -F'"timestamp":"' '{split($2,a,"\""); if(a[1]>=start) count++} END{print count+0}' "$LOG_FILE" 2>/dev/null || echo 0)
+ THREATS=$(awk -v start="$SESSION_START" -F'"timestamp":"' '{split($2,a,"\""); if(a[1]>=start && /threat_detected/) count++} END{print count+0}' "$LOG_FILE" 2>/dev/null || echo 0)
+ else
+ TOTAL=$(wc -l < "$LOG_FILE" 2>/dev/null || echo 0)
+ THREATS=$(grep -c '"threat_detected"' "$LOG_FILE" 2>/dev/null || echo 0)
+ fi
+fi
+
+jq -Rn \
+ --arg timestamp "$TIMESTAMP" \
+ --argjson total "$TOTAL" \
+ --argjson threats "$THREATS" \
+ '{"timestamp":$timestamp,"event":"session_end","total_events":$total,"threats_detected":$threats}' \
+ >> "$LOG_FILE"
+
+if [[ "$THREATS" -gt 0 ]]; then
+ echo "⚠️ Session ended: $THREATS threat(s) detected in $TOTAL events"
+else
+ echo "✅ Session ended: $TOTAL events, no threats"
+fi
+
+exit 0
diff --git a/hooks/governance-audit/audit-session-start.sh b/hooks/governance-audit/audit-session-start.sh
new file mode 100644
index 00000000..aec070b2
--- /dev/null
+++ b/hooks/governance-audit/audit-session-start.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# Governance Audit: Log session start with governance context
+
+set -euo pipefail
+
+if [[ "${SKIP_GOVERNANCE_AUDIT:-}" == "true" ]]; then
+ exit 0
+fi
+
+INPUT=$(cat)
+
+mkdir -p logs/copilot/governance
+
+TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
+CWD=$(pwd)
+LEVEL="${GOVERNANCE_LEVEL:-standard}"
+
+jq -Rn \
+ --arg timestamp "$TIMESTAMP" \
+ --arg cwd "$CWD" \
+ --arg level "$LEVEL" \
+ '{"timestamp":$timestamp,"event":"session_start","governance_level":$level,"cwd":$cwd}' \
+ >> logs/copilot/governance/audit.log
+
+echo "🛡️ Governance audit active (level: $LEVEL)"
+exit 0
diff --git a/hooks/governance-audit/hooks.json b/hooks/governance-audit/hooks.json
new file mode 100644
index 00000000..6c08f670
--- /dev/null
+++ b/hooks/governance-audit/hooks.json
@@ -0,0 +1,33 @@
+{
+ "version": 1,
+ "hooks": {
+ "sessionStart": [
+ {
+ "type": "command",
+ "bash": ".github/hooks/governance-audit/audit-session-start.sh",
+ "cwd": ".",
+ "timeoutSec": 5
+ }
+ ],
+ "sessionEnd": [
+ {
+ "type": "command",
+ "bash": ".github/hooks/governance-audit/audit-session-end.sh",
+ "cwd": ".",
+ "timeoutSec": 5
+ }
+ ],
+ "userPromptSubmitted": [
+ {
+ "type": "command",
+ "bash": ".github/hooks/governance-audit/audit-prompt.sh",
+ "cwd": ".",
+ "env": {
+ "GOVERNANCE_LEVEL": "standard",
+ "BLOCK_ON_THREAT": "false"
+ },
+ "timeoutSec": 10
+ }
+ ]
+ }
+}