Conformance Check Failure
Check ID: SEC-005
Severity: HIGH
Category: Security — Cross-Repository Validation
Problem Description
actions/setup/js/setup_comment_memory_files.cjs reads comment memory from a GitHub-configured target-repo, which can point to any repository. Unlike dispatch_workflow.cjs and dispatch_repository.cjs (which enforce an explicit allowed_repos allowlist via validateTargetRepo and throw E004 on violation), this handler resolves the target repository and accesses GitHub Issues API with no allowlist gate.
This violates the Safe Outputs Specification §3.2.6 (SP6): cross-repository access requires an explicit allowlist with default-deny semantics.
Affected Components
- File:
actions/setup/js/setup_comment_memory_files.cjs
- Function:
resolveTargetRepo (line ~54) and collectCommentMemoryFiles (line ~64)
🔍 Current vs Expected Behavior
Current Behavior
resolveTargetRepo accepts any target-repo value from config and constructs an { owner, repo, slug } object without validating it against an allowlist:
function resolveTargetRepo(commentMemoryConfig) {
const configuredRepo = String(commentMemoryConfig?.["target-repo"] || "").trim();
const repoSlug = configuredRepo || `\$\{context.repo.owner}/\$\{context.repo.repo}`;
// No allowlist check here
return { owner, repo, slug: ... };
}
Expected Behavior
When target-repo resolves to a repo other than the current context repo, an allowlist check must be performed (matching the pattern in dispatch_workflow.cjs):
if (isCrossRepo) {
if (allowedRepos.size === 0) {
throw new Error("E004: Cross-repo comment-memory access denied. No allowlist configured.");
}
const validation = validateTargetRepo(resolvedSlug, contextSlug, allowedRepos);
if (!validation.valid) throw new Error(`E004: \$\{validation.error}`);
}
Alternatively, add a @safe-outputs-exempt SEC-005 annotation with a documented justification if the cross-repo access is intentionally unrestricted by design.
Remediation Steps
This task can be assigned to a Copilot coding agent with the following steps:
- In
setup_comment_memory_files.cjs, compute isCrossRepo by comparing the resolved targetRepo.slug against \$\{context.repo.owner}/\$\{context.repo.repo}.
- If
isCrossRepo is true, read an allowed_repos list from the handler config (consistent with how dispatch_workflow.cjs reads it).
- Call
validateTargetRepo (from repo_helpers.cjs) and throw E004 if the resolved repo is not in the allowlist or no allowlist is set.
- If the feature is intentionally unrestricted, add
// @safe-outputs-exempt SEC-005: <reason> and document why in the specification.
Verification
After remediation, verify by running:
bash scripts/check-safe-outputs-conformance.sh
Check SEC-005 should pass without errors.
References
- Safe Outputs Specification:
docs/src/content/docs/reference/safe-outputs-specification.md
- Reference implementation:
actions/setup/js/dispatch_workflow.cjs (lines 50–65)
- Conformance Checker:
scripts/check-safe-outputs-conformance.sh
- Run ID: §24748719577
- Date: 2026-04-21
Generated by Daily Safe Outputs Conformance Checker · ● 110.8K · ◷
Conformance Check Failure
Check ID: SEC-005
Severity: HIGH
Category: Security — Cross-Repository Validation
Problem Description
actions/setup/js/setup_comment_memory_files.cjsreads comment memory from a GitHub-configuredtarget-repo, which can point to any repository. Unlikedispatch_workflow.cjsanddispatch_repository.cjs(which enforce an explicitallowed_reposallowlist viavalidateTargetRepoand throwE004on violation), this handler resolves the target repository and accesses GitHub Issues API with no allowlist gate.This violates the Safe Outputs Specification §3.2.6 (SP6): cross-repository access requires an explicit allowlist with default-deny semantics.
Affected Components
actions/setup/js/setup_comment_memory_files.cjsresolveTargetRepo(line ~54) andcollectCommentMemoryFiles(line ~64)🔍 Current vs Expected Behavior
Current Behavior
resolveTargetRepoaccepts anytarget-repovalue from config and constructs an{ owner, repo, slug }object without validating it against an allowlist:Expected Behavior
When
target-reporesolves to a repo other than the current context repo, an allowlist check must be performed (matching the pattern indispatch_workflow.cjs):Alternatively, add a
@safe-outputs-exempt SEC-005annotation with a documented justification if the cross-repo access is intentionally unrestricted by design.Remediation Steps
This task can be assigned to a Copilot coding agent with the following steps:
setup_comment_memory_files.cjs, computeisCrossRepoby comparing the resolvedtargetRepo.slugagainst\$\{context.repo.owner}/\$\{context.repo.repo}.isCrossRepois true, read anallowed_reposlist from the handler config (consistent with howdispatch_workflow.cjsreads it).validateTargetRepo(fromrepo_helpers.cjs) and throwE004if the resolved repo is not in the allowlist or no allowlist is set.//@safe-outputs-exemptSEC-005: <reason>and document why in the specification.Verification
After remediation, verify by running:
Check
SEC-005should pass without errors.References
docs/src/content/docs/reference/safe-outputs-specification.mdactions/setup/js/dispatch_workflow.cjs(lines 50–65)scripts/check-safe-outputs-conformance.sh