Skip to content

🚨 [SECURITY] Security Red Team Findings - 2026-03-22 (Weekly Full Scan) #22278

@github-actions

Description

@github-actions

Summary

  • Scan Date: 2026-03-22 (Sunday)
  • Scan Mode: WEEKLY FULL SCAN (all 6 techniques)
  • Files Analyzed: 499 (461 .cjs + 38 .sh)
  • Findings: 1 (MEDIUM severity)
  • Status: ⚠️ Review required

Critical Issues

None. No backdoors, secret leaks, destructive code, obfuscated payloads, or suspicious network domains were detected.

Finding 1: Unsanitized Path in Dynamic require() — MEDIUM

Type: DYNAMIC_REQUIRE_PATH_TRAVERSAL
Severity: MEDIUM
Location: actions/setup/js/safe_output_handler_manager.cjs:171

Vulnerable code (simplified):

// scriptFilename comes directly from GH_AW_SAFE_OUTPUT_SCRIPTS env var (JSON-parsed)
const scriptPath = require("path").join(
  process.env.RUNNER_TEMP || "/tmp",
  "gh-aw", "actions",
  scriptFilename   // ← not sanitized for path traversal
);
const scriptModule = require(scriptPath);

Why it matters:
path.join() does NOT prevent directory traversal. A scriptFilename value like ../../../some/other/file would resolve outside the intended $RUNNER_TEMP/gh-aw/actions/ directory. Since require() then loads the resolved path, an attacker who controls the GH_AW_SAFE_OUTPUT_SCRIPTS environment variable could cause arbitrary .cjs files from the runner filesystem to be loaded and executed.

Context:
GH_AW_SAFE_OUTPUT_SCRIPTS is populated by the workflow compiler from user-defined safe-outputs.scripts configuration. If untrusted workflow inputs can influence this value (e.g., via expression injection), it becomes an execution vector.

Forensics:
Repository history is shallow (1 commit visible: debeacbdocs: update dictation skill glossary with current project terms). Unable to determine the exact commit that introduced this pattern from available history.

Remediation Tasks

  • Task 1: Add path traversal sanitization for scriptFilename in safe_output_handler_manager.cjs:171

    • Validate that scriptFilename contains no path separators (/, \) or .. sequences
    • Example fix: if (scriptFilename.includes('/') || scriptFilename.includes('\\') || scriptFilename.includes('..')) { core.error('Invalid script filename'); continue; }
    • Alternatively, use path.basename(scriptFilename) to strip any directory components before joining
    • Re-verify the resolved scriptPath starts with the expected base directory before calling require()
  • Task 2: Audit GH_AW_SAFE_OUTPUT_SCRIPTS population path

    • Confirm whether untrusted workflow inputs can influence the filenames written to GH_AW_SAFE_OUTPUT_SCRIPTS
    • If user-provided values flow into this env var, add sanitization at the compiler/writer level as well

Scan Results by Technique

View All Technique Results
Technique Result
Pattern Analysis ✅ Clean — no secret exfiltration, no eval with external input, no suspicious domains, no backdoor keywords
AST Inspection ✅ Clean — no suspicious function names, no unusual exports
Entropy Analysis ✅ Clean — no anomalous base64/hex blobs, no obfuscated payloads
Network Analysis ✅ Clean — all network calls target expected GitHub/Microsoft endpoints
Behavioral Analysis ✅ Clean — no time bombs, no anti-debugging, no persistence mechanisms
Dependency Audit ⚠️ 1 finding — dynamic require() path without traversal sanitization

References

  • Workflow Run: §23405378463
  • Scanned Directories: actions/setup/js/ (461 files), actions/setup/sh/ (38 files)
  • Cache State: /tmp/gh-aw/cache-memory/security-red-team/

Generated by Daily Security Red Team Agent ·

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions