Detection rules › Panther

Panther rules: shai

Sha1-Hulud V2 Filenames Added to Repository

#
Tags
GitHub, Supply Chain, Suspicious Files, Code Injection
Source
github.com/panther-labs/panther-analysis

This saved query detects filenames associated with the Sha1-Hulud worm 2.0 campaign, where malicious JS files are inserted into GitHub repositories to exfiltrate secrets. Attack details: - GitHub repositories get compromised via vulnerable workflows - Attackers are able to push their malicious code, contained in filenames "setup_bun.js" and "bun_environment.js" - These files are responsible for exfiltrating cloud credentials, secrets and tokens.

Rule specification

AnalysisType: saved_query
QueryName: Sha1-Hulud V2 Filenames Added to Repository
Description: |
  This saved query detects filenames associated with the Sha1-Hulud worm 2.0 campaign, 
  where malicious JS files are inserted into GitHub repositories to exfiltrate secrets.
  Attack details: 
  - GitHub repositories get compromised via vulnerable workflows
  - Attackers are able to push their malicious code, contained in
    filenames "setup_bun.js" and "bun_environment.js"
  - These files are responsible for exfiltrating cloud credentials, secrets and tokens.
Tags:
  - GitHub
  - Supply Chain
  - Suspicious Files
  - Code Injection
SnowflakeQuery: |
  SELECT
      github_webhook.*,
      all_commits.value AS commit_data,
      added_files.value AS added_file
  FROM panther_logs.public.github_webhook,
      TABLE(FLATTEN(input => commits, outer => true)) all_commits,
      TABLE(FLATTEN(input => all_commits.value:added, outer => true)) added_files
  WHERE p_event_time >= TIMESTAMP '2025-11-24 03:00:00'
    AND (
      added_files.value::STRING IN ('setup_bun.js', 'bun_environment.js')
      OR ARRAY_CONTAINS('setup_bun.js'::VARIANT, head_commit:added)
      OR ARRAY_CONTAINS('bun_environment.js'::VARIANT, head_commit:added)
    )
  ORDER BY p_event_time DESC

DatabricksQuery: |
  SELECT
      github_webhook.*,
      commit_value AS commit_data,
      added_file_value AS added_file
  FROM panther_logs.github_webhook
      LATERAL VIEW OUTER EXPLODE(
        from_json(TO_JSON(commits), 'ARRAY<STRUCT<added: ARRAY<STRING>>>')
      ) commits_exploded AS commit_value
      LATERAL VIEW OUTER EXPLODE(commit_value.added) added_exploded AS added_file_value
  WHERE p_event_time >= TIMESTAMP '2025-11-24 03:00:00'
    AND (
      added_file_value IN ('setup_bun.js', 'bun_environment.js')
      OR ARRAY_CONTAINS(from_json(TO_JSON(head_commit), 'STRUCT<added: ARRAY<STRING>>').added, 'setup_bun.js')
      OR ARRAY_CONTAINS(from_json(TO_JSON(head_commit), 'STRUCT<added: ARRAY<STRING>>').added, 'bun_environment.js')
    )
  ORDER BY p_event_time DESC

Stages and Predicates

Stage 1: source

Table
panther_logs.public.github_webhook

Stage 2: filter

  • p_event_time is at least 2025-11-24 03:00:00
  • added_files.value is one of setup_bun.js, bun_environment.js

This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

FieldSource
github_webhook . *
commit_dataall_commits.value
added_fileadded_files.value