mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
Merge branch 'dev' of github.com:Tria-plc/edr-platform into dev
This commit is contained in:
243
.github/workflows/polinrider-scan.yml
vendored
243
.github/workflows/polinrider-scan.yml
vendored
@@ -1,243 +0,0 @@
|
||||
name: PolinRider Malware Scan
|
||||
|
||||
# ── Triggers ──────────────────────────────────────────────────────────────────
|
||||
# Runs on every push and every PR targeting main/master/develop.
|
||||
# Also available as a manual trigger (workflow_dispatch) and on a nightly
|
||||
# schedule so dormant infections in older branches are caught too.
|
||||
on:
|
||||
push:
|
||||
branches: ["**"]
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
schedule:
|
||||
# Nightly full-repo scan at 02:00 UTC
|
||||
- cron: "0 2 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
# ── Permissions ───────────────────────────────────────────────────────────────
|
||||
permissions:
|
||||
contents: read # checkout
|
||||
security-events: write # upload SARIF to GitHub Security tab
|
||||
actions: read
|
||||
checks: write # annotate PRs with scan findings
|
||||
|
||||
# ── Deployment gate ───────────────────────────────────────────────────────────
|
||||
# All other jobs (build, test, deploy) should list this job under `needs:`.
|
||||
# If this job fails (exit code 1 from the scanner), the whole workflow stops.
|
||||
jobs:
|
||||
polinrider-scan:
|
||||
name: "PolinRider / Famous Chollima Scan"
|
||||
runs-on: ubuntu-latest
|
||||
# Prevent CI from being disabled by any workflow override
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
# ── 1. Checkout full history ─────────────────────────────────────────────
|
||||
# Full depth so we can inspect recent commits for temp_auto_push.bat traces
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# ── 2. Detect suspicious force-push patterns in git history ──────────────
|
||||
- name: Check git history for force-push and timestamp manipulation
|
||||
id: git-check
|
||||
shell: bash
|
||||
run: |
|
||||
echo "=== Checking for suspicious git history patterns ==="
|
||||
|
||||
# Check for .gitignore entries hiding known malware artifacts
|
||||
GITIGNORE_HITS=0
|
||||
if [ -f .gitignore ]; then
|
||||
for pattern in "branch_structure.json" "temp_auto_push.bat" "temp_interactive_push.bat"; do
|
||||
if grep -qF "$pattern" .gitignore 2>/dev/null; then
|
||||
echo "::warning file=.gitignore::SUSPICIOUS: .gitignore hides known PolinRider artifact: $pattern"
|
||||
GITIGNORE_HITS=$((GITIGNORE_HITS + 1))
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Check if malware persistence artifacts exist anywhere in the tree
|
||||
ARTIFACTS_FOUND=0
|
||||
for artifact in "temp_auto_push.bat" "temp_interactive_push.bat" "branch_structure.json"; do
|
||||
FOUND=$(find . -name "$artifact" -not -path "./.git/*" 2>/dev/null)
|
||||
if [ -n "$FOUND" ]; then
|
||||
echo "::error ::CRITICAL: PolinRider persistence artifact found: $artifact"
|
||||
echo "$FOUND"
|
||||
ARTIFACTS_FOUND=$((ARTIFACTS_FOUND + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
# Scan recent commit messages for --no-verify (used by temp_auto_push.bat)
|
||||
NO_VERIFY_COMMITS=$(git log --oneline -50 --format="%H %s" 2>/dev/null | grep -i "no.verify\|force.*push\|amend" || true)
|
||||
if [ -n "$NO_VERIFY_COMMITS" ]; then
|
||||
echo "::warning ::Recent commits with suspicious metadata (--no-verify / force amend patterns):"
|
||||
echo "$NO_VERIFY_COMMITS"
|
||||
fi
|
||||
|
||||
# Check for .woff2 files with unusually large sizes (>50KB is suspicious)
|
||||
find . -name "*.woff2" -not -path "./.git/*" -size +50k 2>/dev/null | while read f; do
|
||||
SIZE=$(stat -c%s "$f" 2>/dev/null || echo 0)
|
||||
echo "::warning file=$f::Oversized .woff2 font file ($SIZE bytes) — may contain embedded payload"
|
||||
done
|
||||
|
||||
echo "GITIGNORE_HITS=$GITIGNORE_HITS" >> "$GITHUB_OUTPUT"
|
||||
echo "ARTIFACTS_FOUND=$ARTIFACTS_FOUND" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# ── 3. Run the JavaScript malware scanner ────────────────────────────────
|
||||
- name: Run PolinRider malware scanner
|
||||
id: scanner
|
||||
shell: bash
|
||||
run: |
|
||||
echo "=== Running PolinRider IOC scanner ==="
|
||||
|
||||
# The scanner is zero-dependency — just needs Node.js (always present on ubuntu-latest)
|
||||
node .github/scripts/scan.js \
|
||||
--json \
|
||||
--output scan-report.json \
|
||||
.
|
||||
|
||||
SCANNER_EXIT=$?
|
||||
echo "SCANNER_EXIT=$SCANNER_EXIT" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Also emit a human-readable summary to the Actions log
|
||||
node .github/scripts/scan.js . || true
|
||||
|
||||
exit $SCANNER_EXIT
|
||||
|
||||
# ── 4. Upload scan report as artifact ────────────────────────────────────
|
||||
# - name: Upload scan report
|
||||
# if: always()
|
||||
# uses: actions/upload-artifact@v4
|
||||
# with:
|
||||
# name: polinrider-scan-report
|
||||
# path: scan-report.json
|
||||
# retention-days: 90
|
||||
|
||||
# # ── 5. Convert to SARIF and upload to GitHub Security tab ─────────────
|
||||
# - name: Convert scan results to SARIF
|
||||
# if: always()
|
||||
# shell: bash
|
||||
# run: |
|
||||
# node - << 'SCRIPT'
|
||||
# const fs = require('fs');
|
||||
|
||||
# let report;
|
||||
# try {
|
||||
# report = JSON.parse(fs.readFileSync('scan-report.json', 'utf8'));
|
||||
# } catch {
|
||||
# // No report = no findings, write empty SARIF
|
||||
# report = { results: [] };
|
||||
# }
|
||||
|
||||
# const severityMap = {
|
||||
# CRITICAL: 'error',
|
||||
# HIGH: 'warning',
|
||||
# MEDIUM: 'note',
|
||||
# };
|
||||
|
||||
# const sarif = {
|
||||
# version: '2.1.0',
|
||||
# $schema: 'https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.5.json',
|
||||
# runs: [{
|
||||
# tool: {
|
||||
# driver: {
|
||||
# name: 'PolinRider Malware Scanner',
|
||||
# version: '1.0.0',
|
||||
# informationUri: 'https://github.com/your-org/your-repo',
|
||||
# rules: [
|
||||
# { id: 'POLINRIDER-001', name: 'StringShufflerVariable',
|
||||
# shortDescription: { text: 'PolinRider _$_1e42 shuffler variable' },
|
||||
# helpUri: 'https://safedep.io/astro-config-blockchain-c2-supply-chain/' },
|
||||
# { id: 'POLINRIDER-002', name: 'CampaignMarkerAssignment',
|
||||
# shortDescription: { text: "global['!'] campaign marker" } },
|
||||
# { id: 'POLINRIDER-003', name: 'ShufflerSeedString',
|
||||
# shortDescription: { text: 'rmcej%otb% seed string' } },
|
||||
# { id: 'POLINRIDER-004', name: 'KnownC2IP',
|
||||
# shortDescription: { text: 'Known PolinRider C2 IP address' } },
|
||||
# { id: 'POLINRIDER-005', name: 'TRONWallet',
|
||||
# shortDescription: { text: 'Known TRON dead-drop wallet' } },
|
||||
# { id: 'POLINRIDER-006', name: 'AptosAddress',
|
||||
# shortDescription: { text: 'Known Aptos dead-drop address' } },
|
||||
# { id: 'POLINRIDER-007', name: 'XORKey',
|
||||
# shortDescription: { text: 'Known XOR decryption key' } },
|
||||
# { id: 'POLINRIDER-008', name: 'KnownMalwareHash',
|
||||
# shortDescription: { text: 'SHA-256 matches known malware sample' } },
|
||||
# { id: 'POLINRIDER-009', name: 'BlockchainC2Contact',
|
||||
# shortDescription: { text: 'Blockchain RPC dead-drop infrastructure' } },
|
||||
# { id: 'POLINRIDER-010', name: 'HiddenProcessSpawn',
|
||||
# shortDescription: { text: 'windowsHide:true hidden process spawn' } },
|
||||
# { id: 'POLINRIDER-011', name: 'DuplicateCreateRequire',
|
||||
# shortDescription: { text: 'Duplicate createRequire injection' } },
|
||||
# { id: 'POLINRIDER-012', name: 'HorizontalWhitespacePadding',
|
||||
# shortDescription: { text: 'Hidden payload via horizontal whitespace' } },
|
||||
# { id: 'POLINRIDER-013', name: 'ConfigFileSizeAnomaly',
|
||||
# shortDescription: { text: 'Config file size anomaly' } },
|
||||
# { id: 'POLINRIDER-014', name: 'PersistenceArtifact',
|
||||
# shortDescription: { text: 'PolinRider persistence artifact present' } },
|
||||
# { id: 'POLINRIDER-015', name: 'CampaignMarkerPattern',
|
||||
# shortDescription: { text: 'Numeric campaign marker pattern' } },
|
||||
# { id: 'POLINRIDER-016', name: 'SfLObfuscationFunction',
|
||||
# shortDescription: { text: 'sfL obfuscation function' } },
|
||||
# { id: 'POLINRIDER-017', name: 'GlobalRequireInjection',
|
||||
# shortDescription: { text: 'global require/module injection' } },
|
||||
# ],
|
||||
# },
|
||||
# },
|
||||
# results: (report.results || []).flatMap(file =>
|
||||
# (file.findings || []).map(finding => ({
|
||||
# ruleId: finding.id,
|
||||
# level: severityMap[finding.severity] || 'warning',
|
||||
# message: { text: finding.description + ' — ' + finding.matches.join('; ') },
|
||||
# locations: [{
|
||||
# physicalLocation: {
|
||||
# artifactLocation: { uri: file.filePath.replace(/^\.\//,''), uriBaseId: '%SRCROOT%' },
|
||||
# region: { startLine: 1 },
|
||||
# },
|
||||
# }],
|
||||
# }))
|
||||
# ),
|
||||
# }],
|
||||
# };
|
||||
|
||||
# fs.writeFileSync('scan-results.sarif', JSON.stringify(sarif, null, 2));
|
||||
# console.log('SARIF written.');
|
||||
# SCRIPT
|
||||
|
||||
# - name: Upload SARIF to GitHub Security tab
|
||||
# if: always()
|
||||
# uses: github/codeql-action/upload-sarif@v3
|
||||
# with:
|
||||
# sarif_file: scan-results.sarif
|
||||
# category: polinrider-malware-scan
|
||||
|
||||
# ── 6. Block deployment if infected ──────────────────────────────────────
|
||||
- name: Enforce clean-scan gate
|
||||
if: steps.scanner.outputs.SCANNER_EXIT == '1' || steps.git-check.outputs.ARTIFACTS_FOUND != '0'
|
||||
shell: bash
|
||||
run: |
|
||||
echo ""
|
||||
echo "╔══════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ DEPLOYMENT BLOCKED — PolinRider malware signatures detected ║"
|
||||
echo "║ ║"
|
||||
echo "║ This repository contains code signatures consistent with the ║"
|
||||
echo "║ PolinRider supply-chain campaign (DPRK / Famous Chollima). ║"
|
||||
echo "║ ║"
|
||||
echo "║ DO NOT run npm install, build, or deploy until remediated. ║"
|
||||
echo "║ ║"
|
||||
echo "║ See scan-report.json artifact for full details. ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════╝"
|
||||
exit 1
|
||||
|
||||
# ── Dependent jobs — add `needs: polinrider-scan` to block on clean scan ─────
|
||||
# Example: your existing build/deploy jobs should look like this:
|
||||
#
|
||||
# build:
|
||||
# needs: polinrider-scan
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# ...
|
||||
#
|
||||
# deploy:
|
||||
# needs: [polinrider-scan, build]
|
||||
# ...
|
||||
Reference in New Issue
Block a user