mirror of
https://github.com/github/awesome-copilot.git
synced 2026-02-20 02:15:12 +00:00
fix: address Copilot PR review comments on governance-audit hook
- Switch from colon to tab delimiter to handle colons in evidence text - Base64-encode evidence to prevent parsing issues - Use MAX_SEVERITY in log output and JSON events - Narrow regex patterns to reduce false positives: - third[_-]?party instead of third.?party - Role reassignment scoped to AI terms - System prompt injection requires 'you are' context - Fix session-end stats to scope to current session only - Update privacy statement to clarify evidence snippets are logged - Rename credential description to 'Possible hardcoded credential' - Fix database destruction regex to also match semicolons Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -93,7 +93,7 @@ Events are written to `logs/copilot/governance/audit.log` in JSON Lines format:
|
|||||||
|
|
||||||
## Privacy & Security
|
## Privacy & Security
|
||||||
|
|
||||||
- Prompts are **never** logged — only threat signals and metadata are recorded
|
- 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
|
- Add `logs/` to `.gitignore` to keep audit data local
|
||||||
- Set `SKIP_GOVERNANCE_AUDIT=true` to disable entirely
|
- Set `SKIP_GOVERNANCE_AUDIT=true` to disable entirely
|
||||||
- All data stays local — no external network calls
|
- All data stays local — no external network calls
|
||||||
|
|||||||
@@ -44,13 +44,15 @@ check_pattern() {
|
|||||||
if echo "$PROMPT" | grep -qiE "$pattern"; then
|
if echo "$PROMPT" | grep -qiE "$pattern"; then
|
||||||
local evidence
|
local evidence
|
||||||
evidence=$(echo "$PROMPT" | grep -oiE "$pattern" | head -1)
|
evidence=$(echo "$PROMPT" | grep -oiE "$pattern" | head -1)
|
||||||
THREATS_FOUND+=("$category:$severity:$description:$evidence")
|
local evidence_encoded
|
||||||
|
evidence_encoded=$(printf '%s' "$evidence" | base64 | tr -d '\n')
|
||||||
|
THREATS_FOUND+=("$category $severity $description $evidence_encoded")
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Data exfiltration signals
|
# Data exfiltration signals
|
||||||
check_pattern "send\s+(all|every|entire)\s+\w+\s+to\s+" "data_exfiltration" "0.8" "Bulk data transfer"
|
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 "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 "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"
|
check_pattern "upload\s+.*\s+(credentials|secrets|keys)" "data_exfiltration" "0.95" "Credential upload"
|
||||||
|
|
||||||
@@ -61,16 +63,16 @@ check_pattern "add\s+.*\s+(sudoers|administrators)" "privilege_escalation" "0.95
|
|||||||
|
|
||||||
# System destruction signals
|
# System destruction signals
|
||||||
check_pattern "(rm\s+-rf\s+/|del\s+/[sq]|format\s+c:)" "system_destruction" "0.95" "Destructive command"
|
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*$)" "system_destruction" "0.9" "Database destruction"
|
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"
|
check_pattern "wipe\s+(all|entire|every)" "system_destruction" "0.9" "Mass deletion"
|
||||||
|
|
||||||
# Prompt injection signals
|
# Prompt injection signals
|
||||||
check_pattern "ignore\s+(previous|above|all)\s+(instructions?|rules?|prompts?)" "prompt_injection" "0.9" "Instruction override"
|
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+" "prompt_injection" "0.7" "Role reassignment"
|
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 "system\s*:\s*" "prompt_injection" "0.6" "System prompt injection"
|
check_pattern "(^|\n)\s*system\s*:\s*you\s+are" "prompt_injection" "0.6" "System prompt injection"
|
||||||
|
|
||||||
# Credential exposure signals
|
# Credential exposure signals
|
||||||
check_pattern "(api[_-]?key|secret[_-]?key|password|token)\s*[:=]\s*['\"]?\w{8,}" "credential_exposure" "0.9" "Hardcoded credential"
|
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"
|
check_pattern "(aws_access_key|AKIA[0-9A-Z]{16})" "credential_exposure" "0.95" "AWS key exposure"
|
||||||
|
|
||||||
# Log the prompt event
|
# Log the prompt event
|
||||||
@@ -80,7 +82,9 @@ if [[ ${#THREATS_FOUND[@]} -gt 0 ]]; then
|
|||||||
FIRST=true
|
FIRST=true
|
||||||
MAX_SEVERITY="0.0"
|
MAX_SEVERITY="0.0"
|
||||||
for threat in "${THREATS_FOUND[@]}"; do
|
for threat in "${THREATS_FOUND[@]}"; do
|
||||||
IFS=':' read -r category severity description evidence <<< "$threat"
|
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
|
if [[ "$FIRST" != "true" ]]; then
|
||||||
THREATS_JSON+=","
|
THREATS_JSON+=","
|
||||||
@@ -104,14 +108,15 @@ if [[ ${#THREATS_FOUND[@]} -gt 0 ]]; then
|
|||||||
jq -Rn \
|
jq -Rn \
|
||||||
--arg timestamp "$TIMESTAMP" \
|
--arg timestamp "$TIMESTAMP" \
|
||||||
--arg level "$LEVEL" \
|
--arg level "$LEVEL" \
|
||||||
|
--arg max_severity "$MAX_SEVERITY" \
|
||||||
--argjson threats "$THREATS_JSON" \
|
--argjson threats "$THREATS_JSON" \
|
||||||
--argjson count "${#THREATS_FOUND[@]}" \
|
--argjson count "${#THREATS_FOUND[@]}" \
|
||||||
'{"timestamp":$timestamp,"event":"threat_detected","governance_level":$level,"threat_count":$count,"threats":$threats}' \
|
'{"timestamp":$timestamp,"event":"threat_detected","governance_level":$level,"threat_count":$count,"max_severity":($max_severity|tonumber),"threats":$threats}' \
|
||||||
>> "$LOG_FILE"
|
>> "$LOG_FILE"
|
||||||
|
|
||||||
echo "⚠️ Governance: ${#THREATS_FOUND[@]} threat signal(s) detected"
|
echo "⚠️ Governance: ${#THREATS_FOUND[@]} threat signal(s) detected (max severity: $MAX_SEVERITY)"
|
||||||
for threat in "${THREATS_FOUND[@]}"; do
|
for threat in "${THREATS_FOUND[@]}"; do
|
||||||
IFS=':' read -r category severity description evidence <<< "$threat"
|
IFS=$'\t' read -r category severity description _evidence_encoded <<< "$threat"
|
||||||
echo " 🔴 [$category] $description (severity: $severity)"
|
echo " 🔴 [$category] $description (severity: $severity)"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,21 @@ mkdir -p logs/copilot/governance
|
|||||||
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||||
LOG_FILE="logs/copilot/governance/audit.log"
|
LOG_FILE="logs/copilot/governance/audit.log"
|
||||||
|
|
||||||
# Count events from this session
|
# Count events from this session (filter by session start timestamp)
|
||||||
TOTAL=0
|
TOTAL=0
|
||||||
THREATS=0
|
THREATS=0
|
||||||
|
SESSION_START=""
|
||||||
if [[ -f "$LOG_FILE" ]]; then
|
if [[ -f "$LOG_FILE" ]]; then
|
||||||
TOTAL=$(wc -l < "$LOG_FILE" 2>/dev/null || echo 0)
|
# Find the last session_start event to scope stats to current session
|
||||||
THREATS=$(grep -c '"threat_detected"' "$LOG_FILE" 2>/dev/null || echo 0)
|
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
|
fi
|
||||||
|
|
||||||
jq -Rn \
|
jq -Rn \
|
||||||
|
|||||||
Reference in New Issue
Block a user