Skip to content
Draft
Show file tree
Hide file tree
Changes from 5 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
70 changes: 69 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ npx wsa list
npx workspace-architect list instructions
npx wsa list agents
npx wsa list prompts
npx wsa list skills
npx wsa list hooks
npx wsa list plugins
npx wsa list collections
```

Expand All @@ -109,6 +112,15 @@ npx wsa download instructions reactjs
# Download an agent
npx wsa download agents planner

# Download a skill
npx wsa download skills example-planner

# Download a hook
npx wsa download hooks governance-audit

# Download a plugin
npx wsa download plugins awesome-copilot

# Download a complete collection
npx wsa download collections devops-essentials
```
Expand All @@ -121,14 +133,16 @@ npx wsa download collections devops-essentials

## Asset Types

Workspace Architect provides five types of assets:
Workspace Architect provides seven types of assets:

| Type | Description | Location |
|------|-------------|----------|
| **Instructions** | System-level guidelines for Copilot context | `.github/copilot-instructions.md` |
| **Prompts** | Reusable templates for specific tasks | `.github/prompts/` |
| **Agents** | Specialized personas defining Copilot behavior | `.github/agents/` |
| **Skills** | Claude Skills with templates, scripts, and resources | `.github/skills/` |
| **Hooks** | Event-driven scripts that run during Copilot sessions | `.github/hooks/` |
| **Plugins** | Bundled collections of agents, skills, and commands | `.github/plugins/` |
| **Collections** | Bundled assets for specific domains or workflows | Multiple locations |

### What are Skills?
Expand All @@ -153,6 +167,58 @@ npx workspace-architect list skills

For more information, see [Skills User Guide](docs/skills-guide.md) and [Skills vs Agents](docs/skills-vs-agents.md).

### What are Hooks?

**Hooks** are event-driven scripts that execute automatically during GitHub Copilot coding agent sessions. They enable:

- **Session Management**: Run scripts when sessions start or end
- **Prompt Monitoring**: Execute logic when users submit prompts
- **Governance & Auditing**: Track and control agent behavior
- **Custom Workflows**: Integrate with external tools and systems

Hooks are directory-based assets containing:
- **README.md**: Documentation with metadata (name, description, tags)
- **hooks.json**: Hook configuration defining event triggers
- **Shell scripts**: Executable scripts for each hook event

**Example:**
```bash
# Download a Hook
npx workspace-architect download hooks governance-audit

# List all Hooks
npx workspace-architect list hooks
```

**Available Hook Events:**
- `sessionStart` - Triggered when a coding session begins
- `sessionEnd` - Triggered when a coding session ends
- `userPromptSubmitted` - Triggered when a user submits a prompt

### What are Plugins?

**Plugins** are bundled packages that extend GitHub Copilot with curated collections of agents, skills, and commands for specific domains or workflows. Each plugin provides:

- **Agents**: Custom agents for specialized tasks
- **Skills**: Meta-prompts and slash commands
- **Commands**: Interactive workflows
- **Documentation**: Setup and usage guides

Plugins are directory-based assets containing:
- **README.md**: Documentation with metadata
- **agents/**: Agent definitions
- **skills/**: Skill definitions
- **.github/plugin/**: Plugin configuration

**Example:**
```bash
# Download a Plugin
npx workspace-architect download plugins awesome-copilot

# List all Plugins
npx workspace-architect list plugins
```

## Roadmap

See [ROADMAP.md](ROADMAP.md) for our development timeline, upcoming features, and current capabilities.
Expand Down Expand Up @@ -227,6 +293,8 @@ Create a JSON file in `assets/collections/`:
- `npm run sync-instructions` - Sync instructions from github/awesome-copilot
- `npm run sync-prompts` - Sync prompts from github/awesome-copilot
- `npm run sync-skills` - Sync skills from anthropics/skills
- `npm run sync-hooks` - Sync hooks from github/awesome-copilot
- `npm run sync-plugins` - Sync plugins from github/awesome-copilot
- `npm run validate-skills` - Validate all synced skills

#### Upstream Configuration
Expand Down
13 changes: 13 additions & 0 deletions assets/hooks/.upstream-sync.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"sources": [
{
"source": "github/awesome-copilot/hooks",
"lastSync": "2026-02-27T18:03:52.988Z",
"files": [
"governance-audit",
"session-auto-commit",
"session-logger"
]
}
]
}
99 changes: 99 additions & 0 deletions assets/hooks/governance-audit/README.md
Original file line number Diff line number Diff line change
@@ -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
136 changes: 136 additions & 0 deletions assets/hooks/governance-audit/audit-prompt.sh
Original file line number Diff line number Diff line change
@@ -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
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local is used outside of a function (local evidence), which will cause the script to error ("local: can only be used in a function") and, with set -e, abort the hook. Remove local here or move this logic into a function where local is valid.

Suggested change
local evidence

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This issue exists in the upstream hook script from github/awesome-copilot. Since these files are synced from upstream and not authored by this PR, this should be reported to the github/awesome-copilot repository. Our sync process correctly pulls the hooks as-is from upstream.

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}')
Comment on lines +85 to +99
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The audit-prompt.sh hook logs the full matched evidence string from user prompts into logs/copilot/governance/audit.log, which for patterns like credential_exposure (API keys, passwords, tokens, AWS keys) will persist actual secrets in cleartext. An attacker who gains access to the filesystem, backups, or accidentally committed logs could harvest these credentials, turning the governance hook into a secondary exfiltration point. Instead of storing raw evidence, log only non-sensitive metadata (category, severity, and perhaps a redacted hash or truncated sample) so that secrets detected in prompts are never written to disk unredacted.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This security issue exists in the upstream hook script from github/awesome-copilot. Since these files are synced from upstream and not authored by this PR, this vulnerability should be reported and fixed in the github/awesome-copilot repository. Our sync process correctly pulls the hooks as-is from upstream without modifying their behavior.


# 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
Loading