Add safe-outputs.allowed-url-domains for additive URL domain allowlisting#21083
Add safe-outputs.allowed-url-domains for additive URL domain allowlisting#21083
safe-outputs.allowed-url-domains for additive URL domain allowlisting#21083Conversation
… URL domain allowlisting Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
safe-outputs.allowed-url-domains for additive URL domain allowlisting
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in 0d4c530. Added a All 19 smoke-* workflows now include: safe-outputs:
allowed-url-domains: [default-redaction]The resulting Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
There was a problem hiding this comment.
Pull request overview
Adds a new safe-outputs.allowed-url-domains frontmatter field to additively expand the URL-sanitization allowlist (unioned with engine defaults + network.allowed), including new ecosystem domain groups (dev-tools, default-redaction) and updates smoke workflows to use the new baseline.
Changes:
- Introduce
safe-outputs.allowed-url-domainsparsing, validation, schema support, and allowlist computation/unioning. - Add
dev-toolsecosystem domains and adefault-redactioncompound ecosystem (defaults ∪ dev-tools). - Apply
allowed-url-domains: [default-redaction]across smoke workflows and update generated lock files; add/extend tests.
Reviewed changes
Copilot reviewed 49 out of 49 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/safe_outputs_validation.go | Adds validation for safe-outputs.allowed-url-domains (skipping ecosystem identifiers). |
| pkg/workflow/safe_outputs_config.go | Parses allowed-url-domains from safe-outputs frontmatter into SafeOutputsConfig. |
| pkg/workflow/domains.go | Adds compound ecosystem expansion and computes the unioned URL-sanitization allowlist. |
| pkg/workflow/domains_test.go | Adds unit tests for URL domain expansion/unioning and compound ecosystem behavior. |
| pkg/workflow/data/ecosystem_domains.json | Adds dev-tools domain set used by URL allowlisting. |
| pkg/workflow/compiler_yaml.go | Emits GH_AW_ALLOWED_DOMAINS using the new unioned computation when allowed-url-domains is set. |
| pkg/workflow/compiler_safe_outputs_steps.go | Same as above for the consolidated safe-outputs handler manager step. |
| pkg/workflow/compiler_types.go | Extends SafeOutputsConfig with AllowedURLDomains. |
| pkg/workflow/compiler.go | Hooks allowed-url-domains validation into workflow compilation. |
| pkg/workflow/allowed_domains_sanitization_test.go | Adds integration-style tests verifying union behavior via compiled lock output. |
| pkg/parser/schemas/main_workflow_schema.json | Adds schema support for safe-outputs.allowed-url-domains (plus some unrelated unicode-escape updates). |
| .github/workflows/smoke-workflow-call.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-workflow-call.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-workflow-call-with-inputs.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-workflow-call-with-inputs.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-update-cross-repo-pr.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-update-cross-repo-pr.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-test-tools.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-test-tools.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-temporary-id.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-temporary-id.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-project.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-project.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-multi-pr.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-multi-pr.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-gemini.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-gemini.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-create-cross-repo-pr.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-create-cross-repo-pr.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-copilot.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-copilot.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-copilot-arm.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-copilot-arm.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-codex.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-codex.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-claude.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-claude.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-call-workflow.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-call-workflow.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-agent-scoped-approved.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-agent-scoped-approved.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-agent-public-none.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-agent-public-none.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-agent-public-approved.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-agent-public-approved.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-agent-all-none.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-agent-all-none.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
| .github/workflows/smoke-agent-all-merged.md | Adds safe-outputs.allowed-url-domains: [default-redaction]. |
| .github/workflows/smoke-agent-all-merged.lock.yml | Regenerates lock output with expanded GH_AW_ALLOWED_DOMAINS. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| // Should include both defaults and dev-tools (at least 34+21 = 55 domains) | ||
| if len(result) < 50 { | ||
| t.Errorf("Expected at least 50 domains in default-redaction, got %d", len(result)) | ||
| } |
| for i, domain := range config.AllowedURLDomains { | ||
| // Skip ecosystem identifiers - they don't need domain pattern validation | ||
| if isEcosystemIdentifier(domain) { | ||
| safeOutputsDomainsValidationLog.Printf("Skipping ecosystem identifier: %s", domain) | ||
| continue | ||
| } |
| if data.SafeOutputs != nil && len(data.SafeOutputs.AllowedDomains) > 0 { | ||
| // Use manually configured allowed domains | ||
| // Use manually configured allowed domains (legacy override behavior) | ||
| domainsStr = strings.Join(data.SafeOutputs.AllowedDomains, ",") | ||
| } else if data.SafeOutputs != nil && len(data.SafeOutputs.AllowedURLDomains) > 0 { | ||
| // allowed-url-domains: additional domains unioned with engine/network base set | ||
| domainsStr = c.computeAllowedURLDomainsForSanitization(data) | ||
| } else { |
| var domainsStr string | ||
| if data.SafeOutputs != nil && len(data.SafeOutputs.AllowedDomains) > 0 { | ||
| domainsStr = strings.Join(data.SafeOutputs.AllowedDomains, ",") | ||
| } else if data.SafeOutputs != nil && len(data.SafeOutputs.AllowedURLDomains) > 0 { | ||
| // allowed-url-domains: additional domains unioned with engine/network base set | ||
| domainsStr = c.computeAllowedURLDomainsForSanitization(data) | ||
| } else { | ||
| domainsStr = c.computeAllowedDomainsForSanitization(data) | ||
| } |
| // expandAllowedURLDomains expands a list of domain entries (which may include ecosystem | ||
| // identifiers like "python", "node", "dev-tools") into a deduplicated, sorted list of | ||
| // concrete domain strings. This uses the same expansion logic as network.allowed. | ||
| func expandAllowedURLDomains(entries []string) []string { | ||
| domainMap := make(map[string]bool) | ||
| for _, entry := range entries { | ||
| ecosystemDomains := getEcosystemDomains(entry) | ||
| if len(ecosystemDomains) > 0 { | ||
| for _, d := range ecosystemDomains { | ||
| domainMap[d] = true | ||
| } | ||
| } else { | ||
| domainMap[entry] = true | ||
| } | ||
| } |
| "dev-tools": [ | ||
| "app.renovatebot.com", | ||
| "appveyor.com", | ||
| "badgen.net", | ||
| "circleci.com", | ||
| "codacy.com", | ||
| "codeclimate.com", | ||
| "codecov.io", | ||
| "coveralls.io", | ||
| "deepsource.io", | ||
| "docs.github.com", | ||
| "drone.io", | ||
| "img.shields.io", | ||
| "readthedocs.io", | ||
| "readthedocs.org", | ||
| "renovatebot.com", | ||
| "semaphoreci.com", | ||
| "shields.io", | ||
| "snyk.io", | ||
| "sonarcloud.io", | ||
| "sonarqube.com", | ||
| "travis-ci.com" | ||
| ] |
Document two user-facing features merged on 2026-03-15 after DDUw's 04:31 UTC scan: - gh aw domains (PR #21086): new CLI command to list effective network domains for each workflow, including ecosystem-expanded domains and engine defaults. Added to the Monitoring section of cli.md. - safe-outputs.allowed-url-domains (PR #21083): new safe-outputs field that additively extends the URL sanitization domain allowlist (unions with the engine/network base set). Distinct from allowed-domains, which replaces the default set. Updated the Text Sanitization section of safe-outputs.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds
safe-outputs.allowed-url-domains: a new field for specifying additional domains allowed in URL sanitization. Unlike the existingallowed-domains(full override), this field unions with the engine defaults andnetwork.allowed.Changes
New field
safe-outputs.allowed-url-domainsnetwork.allowed(python,node,dev-tools,default-redaction, etc.)expandAllowedURLDomains; merged into the engine/network base set viacomputeAllowedURLDomainsForSanitizationlocalhostandgithub.comin the final setNew
dev-toolsecosystem (pkg/workflow/data/ecosystem_domains.json)codecov.io,snyk.io,circleci.com,shields.io,readthedocs.org,sonarcloud.io, etc.New
default-redactioncompound ecosystemdefaults(infrastructure/cert domains) +dev-tools(CI/CD/code-quality domains)compoundEcosystemsmap indomains.go— no data duplication, resolved at lookup timesafe-outputs.allowed-url-domainsin most workflowsApplied to all smoke- workflows* — all 19
smoke-*.mdworkflows now includeallowed-url-domains: [default-redaction]Validation —
validateSafeOutputsAllowedURLDomainsskips ecosystem identifiers (same asvalidateNetworkAllowedDomains); plain domains go throughvalidateDomainPatternSchema —
allowed-url-domainsadded tomain_workflow_schema.jsonExample
Result:
GH_AW_ALLOWED_DOMAINS= engine defaults ∪network.allowed∪allowed-url-domains+localhost+github.comOriginal prompt
📍 Connect Copilot coding agent with Jira, Azure Boards or Linear to delegate work to Copilot in one click without leaving your project management tool.