Skip to main content

Overview

GitHub Copilot’s Coding Agent supports hooks for monitoring and controlling tool executions. The Secure MCP Gateway provides guardrails integration through hooks that validate prompts, tool inputs, and outputs.
Hooks Support: Copilot hooks work with Copilot Coding Agent and Copilot CLI, but NOT with VS Code Copilot Chat or inline suggestions.

Where Hooks Work

EnvironmentHooks SupportDescription
Copilot Coding Agent✅ YESCloud-based agent triggered via GitHub Issues/PRs
Copilot CLI (gh copilot)✅ YESCommand-line interface for Copilot
VS Code Copilot Chat❌ NOChat sidebar does not support hooks
Copilot Inline Suggestions❌ NOCode completions do not trigger hooks

Installation

Prerequisites

  • GitHub Copilot with coding agent hooks support
  • Python 3.8+
  • PowerShell 7+ for Windows (required for Copilot CLI)
  • Enkrypt API key
Windows Users: Copilot CLI requires PowerShell 7+ (pwsh.exe), not Windows PowerShell 5.x.Install via:
winget install Microsoft.PowerShell

Step 1: Install Dependencies

cd hooks/copilot
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
pip install -r hooks/requirements.txt

Step 2: Configure Guardrails

cp hooks/copilot/hooks/guardrails_config_example.json \
   hooks/copilot/hooks/guardrails_config.json

# Set API key
export ENKRYPT_API_KEY="your-api-key"

Configuration

Hook Locations

The location of hooks.json depends on which Copilot environment you’re using:
Environmenthooks.json LocationNotes
Copilot Coding Agent.github/hooks/hooks.jsonMust be on the repository’s default branch
Copilot CLIhooks.json (project root)Loaded from current working directory

Copilot Coding Agent Setup

# Create hooks directory
mkdir -p .github/hooks

# Copy template
cp hooks/copilot/hooks_example.json .github/hooks/hooks.json

# Commit and push to default branch
git add .github/hooks/hooks.json
git commit -m "Add Copilot hooks configuration"
git push

Copilot CLI Setup

# Copy template to project root
cp hooks/copilot/hooks_example.json hooks.json

Hooks Configuration

hooks.json Format

{
  "version": 1,
  "hooks": {
    "sessionStart": [
      {
        "type": "command",
        "bash": "python hooks/copilot/hooks/session_start.py",
        "powershell": "hooks\\copilot\\venv\\Scripts\\python.exe hooks\\copilot\\hooks\\session_start.py",
        "cwd": ".",
        "timeoutSec": 10
      }
    ],
    "userPromptSubmitted": [
      {
        "type": "command",
        "bash": "python hooks/copilot/hooks/user_prompt_submitted.py",
        "powershell": "hooks\\copilot\\venv\\Scripts\\python.exe hooks\\copilot\\hooks\\user_prompt_submitted.py",
        "cwd": ".",
        "timeoutSec": 30
      }
    ],
    "preToolUse": [
      {
        "type": "command",
        "bash": "python hooks/copilot/hooks/pre_tool_use.py",
        "powershell": "hooks\\copilot\\venv\\Scripts\\python.exe hooks\\copilot\\hooks\\pre_tool_use.py",
        "cwd": ".",
        "timeoutSec": 30
      }
    ],
    "postToolUse": [
      {
        "type": "command",
        "bash": "python hooks/copilot/hooks/post_tool_use.py",
        "powershell": "hooks\\copilot\\venv\\Scripts\\python.exe hooks\\copilot\\hooks\\post_tool_use.py",
        "cwd": ".",
        "timeoutSec": 30
      }
    ],
    "sessionEnd": [
      {
        "type": "command",
        "bash": "python hooks/copilot/hooks/session_end.py",
        "powershell": "hooks\\copilot\\venv\\Scripts\\python.exe hooks\\copilot\\hooks\\session_end.py",
        "cwd": ".",
        "timeoutSec": 10
      }
    ],
    "errorOccurred": [
      {
        "type": "command",
        "bash": "python hooks/copilot/hooks/error_occurred.py",
        "powershell": "hooks\\copilot\\venv\\Scripts\\python.exe hooks\\copilot\\hooks\\error_occurred.py",
        "cwd": ".",
        "timeoutSec": 10
      }
    ]
  }
}

Hook Events

HookWhen It RunsCan Block?Output Fields
sessionStartSession beginsNO (ignored)none
userPromptSubmittedAfter user submits promptNO (audit)none
preToolUseBefore tool executesYESpermissionDecision, permissionDecisionReason
postToolUseAfter tool returnsNO (audit)none
sessionEndSession completesNO (ignored)none
errorOccurredWhen error occursNO (ignored)none
Only preToolUse can block actions. All other hooks are observational.

Guardrails Configuration

guardrails_config.json

{
  "enkrypt_api": {
    "url": "https://api.enkryptai.com/guardrails/policy/detect",
    "api_key": "YOUR_ENKRYPT_API_KEY",
    "ssl_verify": true,
    "timeout": 15,
    "fail_silently": true
  },
  "userPromptSubmitted": {
    "enabled": true,
    "guardrail_name": "Sample Airline Guardrail",
    "block": ["injection_attack", "pii", "toxicity"]
  },
  "preToolUse": {
    "enabled": true,
    "guardrail_name": "Sample Airline Guardrail",
    "block": ["injection_attack", "pii"]
  },
  "postToolUse": {
    "enabled": true,
    "guardrail_name": "Sample Airline Guardrail",
    "block": ["pii"]
  },
  "sensitive_tools": [
    "execute_sql",
    "delete_*",
    "run_command"
  ]
}

Available Detectors

DetectorDescription
injection_attackPrompt injection attempts
piiPersonal Identifiable Information
toxicityToxic/harmful content
nsfwNot Safe For Work content
keyword_detectorCustom banned keywords
policy_violationCustom policy violations
biasBiased content
sponge_attackResource exhaustion attacks
topic_detectorOff-topic content

How It Works

1. preToolUse (BLOCKING)

Tool call initiated → Hook intercepts → Enkrypt API scans → Allow or Deny
Input from Copilot:
{
  "timestamp": 1704614600000,
  "cwd": "/path/to/project",
  "toolName": "bash",
  "toolArgs": "{\"command\": \"rm -rf /\"}"
}
Output to Copilot:
{
  "permissionDecision": "deny",
  "permissionDecisionReason": "Blocked by Enkrypt AI Guardrails:\nInjection attack pattern detected"
}

2. userPromptSubmitted (AUDIT-ONLY)

User submits prompt → Hook receives prompt → Scan for violations → Log alerts (no blocking)
This hook cannot block prompts — Copilot ignores its output. Violations are logged to security_alerts.jsonl.

3. postToolUse (AUDIT-ONLY)

Tool completes → Hook receives output → Scan for sensitive data → Log alerts
Input from Copilot:
{
  "timestamp": 1704614700000,
  "cwd": "/path/to/project",
  "toolName": "bash",
  "toolArgs": "{\"command\": \"cat .env\"}",
  "toolResult": {
    "resultType": "success",
    "textResultForLlm": "API_KEY=sk-12345..."
  }
}

Audit Logs

All events are logged to ~/copilot/hooks_logs/:
Log FileContents
sessionStart.jsonlSession start events
userPromptSubmitted.jsonlPrompt audit events
preToolUse.jsonlTool input validation events
postToolUse.jsonlTool output audit events
sessionEnd.jsonlSession end events
errorOccurred.jsonlError events
combined_audit.jsonlAll events combined
security_alerts.jsonlSecurity-related alerts

View Logs

# View latest tool blocks
tail -5 ~/copilot/hooks_logs/preToolUse.jsonl

# View security alerts
tail -5 ~/copilot/hooks_logs/security_alerts.jsonl

# View all audit events
tail -10 ~/copilot/hooks_logs/combined_audit.jsonl

Testing

Test Hook Manually

echo '{"timestamp":1704614600000,"cwd":".","toolName":"bash","toolArgs":"ls"}' | \
  python hooks/copilot/hooks/pre_tool_use.py
Expected output:
{"permissionDecision": "allow"}

Troubleshooting

Hooks Not Running

  1. Ensure hooks.json is in the correct location:
    • Coding Agent: .github/hooks/hooks.json on default branch
    • Copilot CLI: hooks.json in current working directory
  2. Verify "version": 1 is set in hooks.json
  3. Check Python is accessible at the configured path
  4. Validate JSON syntax of hooks.json

PowerShell 7 Not Found (Windows)

If you see this error with Copilot CLI:
PowerShell 6+ (pwsh) is not available. Please install it from https://aka.ms/powershell
Solution:
  1. Install PowerShell 7+:
    winget install Microsoft.PowerShell
    
  2. Add to system PATH:
    • Open System Properties → Environment Variables
    • Edit the Path system variable
    • Add: C:\Program Files\PowerShell\7
  3. Restart your terminal/IDE completely
  4. Verify: pwsh --version should show PowerShell 7.x.x

API Returning 404

The "Policy not found" error means:
  • The policy_violation detector references a non-existent policy
  • Fix: Disable policy_violation or create the policy in Enkrypt Dashboard

Metrics

from enkrypt_guardrails import get_hook_metrics

metrics = get_hook_metrics("preToolUse")
print(f"Total calls: {metrics['total_calls']}")
print(f"Blocked calls: {metrics['blocked_calls']}")
print(f"Avg latency: {metrics['avg_latency_ms']:.2f}ms")

Resources


Next Steps

Configure Policies

Create custom guardrail policies

View Logs

Monitor security events

Add Detectors

Configure detection rules

Metrics

Track performance

Build docs developers (and LLMs) love