| name | gh-aw-safe-outputs |
| description | Expert knowledge in GitHub Agentic Workflows safe outputs - security architecture, sanitization, controlled AI actions, and write operation patterns |
| license | Apache-2.0 |
| version | 2.0.1 |
| last_updated | "2026-04-13T00:00:00.000Z" |
| tags | ["github-agentic-workflows","safe-outputs","security","ai-safety","sanitization"] |
🛡️ GitHub Agentic Workflows - Safe Outputs Skill
🔴 AI FIRST Quality Principle
Apply the AI FIRST principle: never accept first-pass quality. Minimum 2 iterations. Read all output, improve every section. No shortcuts.
📋 Purpose
Master the safe outputs pattern in GitHub Agentic Workflows - the foundational security mechanism that enables AI agents to perform write operations safely through explicit, human-approved outputs. This skill provides comprehensive expertise in designing, implementing, and operating safe output patterns for controlled AI automation.
🎯 Core Concept
What Are Safe Outputs?
Safe outputs are the only way AI agents can perform write operations (create/update files, issues, PRs) in GitHub Agentic Workflows. Unlike direct tool access, safe outputs require explicit approval and sanitization before execution.
Key Principles:
- 🔒 Write Isolation: All write operations go through safe outputs
- ✅ Explicit Approval: Outputs must be explicitly declared in workflow
- �� Automatic Sanitization: All outputs sanitized before execution
- 📊 Auditable: All actions logged and traceable
- 🚫 No Direct Writes: AI cannot write files/issues/PRs directly
Security Model:
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ │ │ │ │ │
│ AI Agent │─────▶│ Safe Outputs │─────▶│ Sanitization │
│ (Read-Only) │ │ (Declare) │ │ & Execution │
│ │ │ │ │ │
└─────────────┘ └──────────────┘ └─────────────────┘
│
▼
┌──────────────┐
│ Workflow │
│ Configuration│
│ (Allowlist) │
└──────────────┘
🏗️ Safe Output Types
1. safeoutputs___issue
Create or update GitHub issues with AI-generated content.
Configuration:
tools:
safeoutputs___issue:
Usage Pattern:
# Workflow markdown body
Analyze this codebase and create issues for improvement opportunities.
For each issue, use safeoutputs___issue:
- title: Brief description
- body: Detailed explanation with code examples
- labels: ["enhancement", "ai-generated"]
AI Output Format:
{
"tool": "safeoutputs___issue",
"title": "Improve error handling in authentication module",
"body": "## Problem\n\nThe authentication module lacks comprehensive error handling...\n\n## Proposed Solution\n\n1. Add try-catch blocks\n2. Implement error logging\n3. Return user-friendly messages",
"labels": ["enhancement", "security"]
}
Sanitization Applied:
- ✅ Title limited to 256 characters
- ✅ Body sanitized for XSS (HTML tags stripped)
- ✅ Labels validated against repository labels
- ✅ Malicious URLs removed
- ✅ Code injection patterns blocked
Execution:
- Creates new issue if none exists
- Updates existing issue if specified
- Returns issue URL
- Logs all actions
2. safeoutputs___pull_request
Create pull requests with AI-generated code changes.
Configuration:
tools:
safeoutputs___pull_request:
base_branch: main
auto_merge: false
Usage Pattern:
Review this codebase and propose improvements.
Create a pull request using safeoutputs___pull_request:
- branch: "ai/improve-error-handling"
- title: "Improve error handling"
- body: Description of changes
- files: List of file changes
AI Output Format:
{
"tool": "safeoutputs___pull_request",
"branch": "ai/improve-error-handling",
"title": "Improve error handling in authentication module",
"body": "## Changes\n\n- Added try-catch blocks\n- Implemented error logging\n- Added tests",
"files": [
{
"path": "src/auth.ts",
"content": "// New content...",
"encoding": "utf-8"
}
]
}
Sanitization Applied:
- ✅ Branch name validated (alphanumeric, hyphens, slashes only)
- ✅ File paths validated (no directory traversal)
- ✅ File content scanned for secrets
- ✅ File size limits enforced (max 1MB per file)
- ✅ Binary files rejected
- ✅ Suspicious patterns blocked
Execution:
- Creates new branch from base
- Commits files with AI signature
- Creates pull request
- Returns PR URL
- Triggers CI/CD
3. safeoutputs___comment
Add comments to issues or pull requests.
Configuration:
tools:
safeoutputs___comment:
Usage Pattern:
Provide helpful feedback on this pull request.
Add a comment using safeoutputs___comment:
- issue_number: 123 # or pr_number
- body: Your feedback
AI Output Format:
{
"tool": "safeoutputs___comment",
"issue_number": 123,
"body": "## Code Review\n\nI noticed a few areas for improvement:\n\n1. **Error Handling**: Consider adding...\n2. **Performance**: The loop in line 45 could be optimized..."
}
Sanitization Applied:
- ✅ Body sanitized for XSS
- ✅ Malicious URLs removed
- ✅ Code injection blocked
- ✅ Length limits enforced
4. safeoutputs___file
Create or update files in the repository.
Configuration:
tools:
safeoutputs___file:
allowed_paths:
- "docs/**"
- "*.md"
- "src/**/*.ts"
max_file_size: 1048576
Usage Pattern:
Update documentation to reflect recent changes.
Create/update files using safeoutputs___file:
- path: docs/api.md
- content: Updated documentation
- commit_message: Update API documentation
AI Output Format:
{
"tool": "safeoutputs___file",
"path": "docs/api.md",
"content": "# API Documentation\n\n## Authentication\n\n...",
"commit_message": "Update API documentation with new endpoints",
"encoding": "utf-8"
}
Sanitization Applied:
- ✅ Path validated against allowed_paths
- ✅ No directory traversal (../)
- ✅ File size limits enforced
- ✅ Secret scanning
- ✅ Binary file detection
- ✅ Malicious content removed
5. safeoutputs___label
Add or remove labels from issues or pull requests.
Configuration:
tools:
safeoutputs___label:
Usage Pattern:
Triage this issue and apply appropriate labels.
Use safeoutputs___label:
- issue_number: 123
- add: ["bug", "high-priority"]
- remove: ["needs-triage"]
AI Output Format:
{
"tool": "safeoutputs___label",
"issue_number": 123,
"add": ["bug", "high-priority"],
"remove": ["needs-triage"]
}
Sanitization Applied:
- ✅ Labels validated against repository labels
- ✅ Label names sanitized
- ✅ Protected labels blocked (e.g., "security-approved")
6. safeoutputs___noop
No operation - AI provides information without taking action.
Configuration:
tools:
safeoutputs___noop:
Usage Pattern:
Analyze this issue and provide recommendations without taking action.
Use safeoutputs___noop to report findings.
AI Output Format:
{
"tool": "safeoutputs___noop",
"message": "## Analysis\n\nThis issue appears to be a duplicate of #456.\n\n## Recommendation\n\nClose this issue and direct the reporter to #456."
}
Use Cases:
- ✅ Read-only analysis
- ✅ Recommendations without action
- ✅ Dry-run scenarios
- ✅ Human-in-the-loop workflows
🔐 Security Architecture
Defense-in-Depth Layers
Layer 1: Compile-Time Validation
tools:
safeoutputs___issue:
safeoutputs___file:
allowed_paths: ["docs/**"]
- Tool allowlist validated at compile time
- Configuration schema validated
- Path patterns validated
Layer 2: Runtime Isolation
AI Agent Environment:
- Read-only filesystem
- No network access (except MCP)
- Limited memory/CPU
- Sandboxed container
Layer 3: Output Sanitization
function sanitize(output: SafeOutput): SanitizedOutput {
validateSchema(output);
sanitizeHTML(output.body);
sanitizeURLs(output.body);
detectSecrets(output);
validatePaths(output.files);
enforceSize(output);
return sanitized;
}
Layer 4: Execution Control
Approved outputs only:
- Tool in workflow allowlist? ✅
- Path in allowed_paths? ✅
- Size under limit? ✅
- No secrets detected? ✅
- Sanitization passed? ✅
→ Execute action
→ Log to audit trail
Threat Model
Threats Mitigated:
| Threat | Mitigation | Layer |
|---|
| Path Traversal | Path validation, allowlist | Layer 3 |
| Secret Leakage | Secret scanning | Layer 3 |
| XSS Injection | HTML sanitization | Layer 3 |
| Code Injection | Pattern blocking | Layer 3 |
| Unauthorized Files | allowed_paths | Layer 1 |
| Excessive Size | Size limits | Layer 3 |
| Binary Uploads | Binary detection | Layer 3 |
| Protected Labels | Label validation | Layer 3 |
| Branch Hijacking | Branch validation | Layer 3 |
📊 Configuration Patterns
Minimal (High Security)
on: issues
permissions: read-all
tools:
github:
toolsets: [issues]
safeoutputs___comment:
Use Case: Issue triage, read-only analysis
Standard (Balanced)
on: issues
permissions: read-all
tools:
github:
toolsets: [issues, repos]
safeoutputs___issue:
safeoutputs___comment:
safeoutputs___label:
safeoutputs___file:
allowed_paths:
- "docs/**/*.md"
Use Case: Documentation updates, issue management
Advanced (Controlled Automation)
on: pull_request
permissions: read-all
tools:
github:
toolsets: [issues, repos, pull_requests]
bash:
allowed-commands: [npm, git]
safeoutputs___pull_request:
base_branch: main
safeoutputs___comment:
safeoutputs___file:
allowed_paths:
- "src/**/*.ts"
- "tests/**/*.test.ts"
- "docs/**"
max_file_size: 1048576
Use Case: Code generation, automated PRs
🎯 Best Practices
1. Principle of Least Privilege
tools:
safeoutputs___*:
tools:
safeoutputs___issue:
safeoutputs___comment:
2. Restrict File Paths
tools:
safeoutputs___file:
allowed_paths: ["**"]
tools:
safeoutputs___file:
allowed_paths:
- "docs/**/*.md"
- "README.md"
3. Use Human-in-the-Loop for Critical Operations
tools:
safeoutputs___noop:
4. Audit Trail
5. Test in Sandbox First
tools:
safeoutputs___noop:
🔄 Workflow Examples
Example 1: Issue Triage
---
on: issues
tools:
github:
toolsets: [issues]
safeoutputs___label:
safeoutputs___comment:
---
Analyze this issue and provide triage:
1. Determine if it's a bug, feature, or question
2. Apply appropriate labels using safeoutputs___label
3. Add helpful comment using safeoutputs___comment
4. Suggest assignee if applicable
Example 2: Documentation Updates
---
on: push
tools:
github:
toolsets: [repos]
bash:
allowed-commands: [git]
safeoutputs___file:
allowed_paths: ["docs/**"]
---
Review recent code changes and update documentation:
1. Identify changed files
2. Review related documentation
3. Update docs using safeoutputs___file
4. Ensure examples are current
Example 3: Code Review
---
on: pull_request
tools:
github:
toolsets: [pull_requests]
safeoutputs___comment:
---
Review this pull request and provide feedback:
1. Check code quality
2. Identify potential issues
3. Add review comment using safeoutputs___comment
4. Suggest improvements
🚨 Common Pitfalls
Pitfall 1: Overly Permissive Paths
allowed_paths: ["**"]
allowed_paths: ["docs/**/*.md"]
Pitfall 2: Assuming Direct Write Access
# ❌ BAD: Trying to write files directly
Write to src/config.ts
# ✅ GOOD: Using safe outputs
Use safeoutputs___file to update src/config.ts
Pitfall 3: Not Testing Sanitization
Pitfall 4: Ignoring Size Limits
max_file_size: 1048576
max_file_size: 10485760
📊 Monitoring & Observability
Log Analysis
tail -f /tmp/gh-aw/safe-outputs.log
grep "safeoutputs___file" /tmp/gh-aw/safe-outputs.log
grep -c "safeoutputs___" /tmp/gh-aw/safe-outputs.log
Metrics to Track
- ✅ Total safe outputs executed
- ✅ Outputs by type
- ✅ Sanitization blocks
- ✅ Execution failures
- ✅ Average output size
- ✅ Most used tools
Security Alerts
alerts:
- pattern: "Path traversal blocked"
severity: high
- pattern: "Secret detected"
severity: critical
- pattern: "XSS blocked"
severity: high
🔗 Related Skills
- gh-aw-security-architecture - Overall security model
- gh-aw-mcp-gateway - MCP protocol integration
- gh-aw-workflow-authoring - Workflow creation
- gh-aw-logging-monitoring - Observability
🆕 Threat Detection Integration (v0.68.1)
Before any safe output is applied, a dedicated threat detection job runs an AI-powered scan:
Agent Output → Threat Detection Scan → ✓ safe → Write Job → GitHub API
→ ✗ suspicious → BLOCKED (workflow fails)
The scan checks for:
- Prompt injection — Attempts to override instructions via crafted content
- Leaked credentials — API keys, tokens, passwords in output
- Malicious code — Known attack patterns, obfuscated payloads
This is automatic — no configuration needed. If detection fails, nothing is written.
Safe Output Types Reference
| Type | Frontmatter Key | What It Does |
|---|
| Issue | create-issue | Create/update GitHub issues |
| Pull Request | create-pull-request | Create PRs (including cross-repo) |
| Comment | add-comment | Add comments to issues/PRs |
| Label | add-labels | Add labels to issues/PRs |
| File | create-or-update-file | Modify repository files |
| Dispatch | dispatch-workflow | Trigger other workflows (with workflows whitelist and max count) |
| Noop | (default) | Read-only, no writes |
Additionally, safe-outputs supports a top-level allowed-domains key to whitelist network endpoints the agent may contact (see this repo's news workflows for examples).
Constraints You Can Set
---
safe-outputs:
create-issue:
title-prefix: "[bot] " # Required title prefix
labels: [automated, report] # Allowed labels only
max-count: 1 # Max issues per run
close-older-issues: true # Auto-close previous
create-pull-request:
max-count: 1
target-repo: owner/other-repo # Cross-repo support
add-labels:
allowed: [bug, feature, docs] # Whitelist of labels
---
📚 References
✅ Remember
- ✅ Safe outputs are the ONLY way AI agents write to GitHub
- ✅ All outputs pass through threat detection before applying
- ✅ Sanitization is automatic — no opt-in needed
- ✅ Set
max-count to limit operations per run
- ✅ Use
title-prefix for easy identification
- ✅ Use
allowed lists to restrict labels/paths
- ✅ Cross-repo PRs supported via
target-repo
- ✅ Use noop (default) for read-only analysis workflows
- ✅ Monitor audit logs for anomalies
- ✅ Secret scanning prevents credential leaks in outputs
Version: 2.0.0
Last Updated: 2026-04-02
Maintained by: Hack23 AB
🔗 Integration with Riksdagsmonitor agentic workflows
This gh-aw skill is applied by the 11 agentic news workflows in .github/workflows/news-*.md. Their domain contract (analysis-artifact product, gate, article contract) lives in:
Upstream gh-aw docs (v0.69.3): abridged · complete · agentic-workflows blog series · source repo · GitHub CLI manual.