Conformance Check Failure
Check ID: SEC-004
Severity: MEDIUM
Category: Security
Problem Description
The Safe Outputs conformance checker (scripts/check-safe-outputs-conformance.sh) flags handlers that contain a body/body: field but no detectable sanitization call (sanitize, stripHTML, escapeMarkdown, cleanContent). Two handlers currently trip this check:
actions/setup/js/exchange_otlp_workload_identity.cjs
actions/setup/js/report_failed_jobs.cjs
Affected Components
🔍 Current vs Expected Behavior
Current Behavior
exchange_otlp_workload_identity.cjs (lines 36, 64): the body: fields here are HTTP request payloads (URLSearchParams and JSON.stringify) sent to Google's OAuth/token-exchange endpoints — not GitHub-facing content built from agent/safe-output data. This is almost certainly a false positive: the same pattern is already exempted elsewhere (see actions/setup/js/artifact_client.cjs:5, annotated @safe-outputs-exempt SEC-004: "body" references are HTTP transport payloads). This file lacks the equivalent exemption annotation, so the checker keeps flagging it.
report_failed_jobs.cjs (lines ~156-181): this handler builds a real GitHub issue body (issueBody) that is submitted via github.rest.issues.create(...). The body embeds failedJobsList, produced by formatFailedJobsList() from job.name and job.html_url values returned by the Actions Jobs API, with no sanitization step before interpolation into the markdown list (- [\${job.name}`](${job.html_url})`). Job names are normally maintainer-controlled, but they are not validated/escaped here, and the spec's SEC-004 requirement is that any handler embedding data into an issue/PR/comment body sanitize that content regardless of the presumed trust level of the source field. This is a genuine (if low-risk) gap, not a false positive.
Expected Behavior
-
exchange_otlp_workload_identity.cjs should carry a @safe-outputs-exempt SEC-004 annotation (matching the wording style used in artifact_client.cjs) documenting that its body fields are outbound HTTP transport payloads, not GitHub content requiring sanitization.
-
report_failed_jobs.cjs should sanitize the dynamic job.name (and any other interpolated dynamic fields) via the existing sanitizeContent helper (see actions/setup/js/sanitize_content.cjs / sanitize_content_core.cjs) before it is embedded into issueBody, consistent with how other issue/comment-creating handlers (e.g. add_comment.cjs, assign_to_agent.cjs) already sanitize dynamic content.
Remediation Steps
This task can be assigned to a Copilot coding agent with the following steps:
- In
actions/setup/js/exchange_otlp_workload_identity.cjs, add a top-of-file (or adjacent to the body: usages) comment: // @safe-outputs-exempt SEC-004 — "body" references are HTTP transport payloads for OAuth token exchange, not GitHub content, matching the existing convention used in actions/setup/js/artifact_client.cjs.
- In
actions/setup/js/report_failed_jobs.cjs, import the existing sanitizeContent helper from actions/setup/js/sanitize_content.cjs and apply it to job.name (and job.html_url if not already a validated URL) inside formatFailedJobsList() before interpolating into the markdown list.
- Add/update unit tests in
actions/setup/js/report_failed_jobs.test.cjs (or equivalent) covering a failed job whose name contains markdown/HTML special characters, asserting the rendered issue body is sanitized.
- Re-run the conformance checker locally to confirm SEC-004 passes for both files.
Verification
After remediation, verify the fix by running:
bash scripts/check-safe-outputs-conformance.sh
The check SEC-004 should pass without errors for both files.
References
- Safe Outputs Specification: docs/src/content/docs/specs/safe-outputs-specification.md
- Conformance Checker: scripts/check-safe-outputs-conformance.sh
- Existing exemption precedent: actions/setup/js/artifact_client.cjs:5
- Run ID: 31077346908
- Date: 2026-08-06
Generated by ✅ Daily Safe Outputs Conformance Checker · agent · 35.5 AIC · ⌖ 24.4 AIC · ⊞ 6.8K · ◷
Conformance Check Failure
Check ID: SEC-004
Severity: MEDIUM
Category: Security
Problem Description
The Safe Outputs conformance checker (
scripts/check-safe-outputs-conformance.sh) flags handlers that contain abody/body:field but no detectable sanitization call (sanitize,stripHTML,escapeMarkdown,cleanContent). Two handlers currently trip this check:actions/setup/js/exchange_otlp_workload_identity.cjsactions/setup/js/report_failed_jobs.cjsAffected Components
actions/setup/js/exchange_otlp_workload_identity.cjsactions/setup/js/report_failed_jobs.cjs🔍 Current vs Expected Behavior
Current Behavior
exchange_otlp_workload_identity.cjs(lines 36, 64): thebody:fields here are HTTP request payloads (URLSearchParamsandJSON.stringify) sent to Google's OAuth/token-exchange endpoints — not GitHub-facing content built from agent/safe-output data. This is almost certainly a false positive: the same pattern is already exempted elsewhere (seeactions/setup/js/artifact_client.cjs:5, annotated@safe-outputs-exempt SEC-004: "body" references are HTTP transport payloads). This file lacks the equivalent exemption annotation, so the checker keeps flagging it.report_failed_jobs.cjs(lines ~156-181): this handler builds a real GitHub issue body (issueBody) that is submitted viagithub.rest.issues.create(...). The body embedsfailedJobsList, produced byformatFailedJobsList()fromjob.nameandjob.html_urlvalues returned by the Actions Jobs API, with no sanitization step before interpolation into the markdown list (- [\${job.name}`](${job.html_url})`). Job names are normally maintainer-controlled, but they are not validated/escaped here, and the spec's SEC-004 requirement is that any handler embedding data into an issue/PR/comment body sanitize that content regardless of the presumed trust level of the source field. This is a genuine (if low-risk) gap, not a false positive.Expected Behavior
exchange_otlp_workload_identity.cjsshould carry a@safe-outputs-exempt SEC-004annotation (matching the wording style used inartifact_client.cjs) documenting that itsbodyfields are outbound HTTP transport payloads, not GitHub content requiring sanitization.report_failed_jobs.cjsshould sanitize the dynamicjob.name(and any other interpolated dynamic fields) via the existingsanitizeContenthelper (seeactions/setup/js/sanitize_content.cjs/sanitize_content_core.cjs) before it is embedded intoissueBody, consistent with how other issue/comment-creating handlers (e.g.add_comment.cjs,assign_to_agent.cjs) already sanitize dynamic content.Remediation Steps
This task can be assigned to a Copilot coding agent with the following steps:
actions/setup/js/exchange_otlp_workload_identity.cjs, add a top-of-file (or adjacent to thebody:usages) comment://@safe-outputs-exemptSEC-004 — "body" references are HTTP transport payloads for OAuth token exchange, not GitHub content, matching the existing convention used inactions/setup/js/artifact_client.cjs.actions/setup/js/report_failed_jobs.cjs, import the existingsanitizeContenthelper fromactions/setup/js/sanitize_content.cjsand apply it tojob.name(andjob.html_urlif not already a validated URL) insideformatFailedJobsList()before interpolating into the markdown list.actions/setup/js/report_failed_jobs.test.cjs(or equivalent) covering a failed job whosenamecontains markdown/HTML special characters, asserting the rendered issue body is sanitized.Verification
After remediation, verify the fix by running:
The check SEC-004 should pass without errors for both files.
References