Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions .github/scripts/scan-obfuscation.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#!/usr/bin/env bash
# Supply-chain obfuscation scanner
# Scans PR diffs for patterns commonly found in malicious supply-chain attacks:
# - Obfuscated code (packed, shuffled, base64-encoded, hex-encoded)
# - Suspicious global/prototype assignments in build config files
# - Hidden eval / Function constructor calls
# - Large diffs dominated by non-human-readable strings
#
# Exit 0 = clean. Exit 1 = suspicious patterns found (review required).

set -euo pipefail

RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

WARNINGS=0

check_pattern() {
local label="$1"
local pattern="$2"
local severity="${3:-WARN}"

if grep -n -P "$pattern" /tmp/pr-diff.txt 2>/dev/null; then
echo -e "${RED}[${severity}]${NC} $label — matches found (see above)"
WARNINGS=$((WARNINGS + 1))
fi
}

echo "::group::Obfuscation Scan"

# ---------------------------------------------------------------------------
# 1. OBFUSCATION PATTERNS
# ---------------------------------------------------------------------------

echo "→ Scanning for obfuscation patterns..."

# Packed/obfuscated code blocks (long base64-like strings, hex chains)
check_pattern \
"Packed/obfuscated JavaScript blob (self-decoding function pattern)" \
'(\w+),\s*\w+\s*=\s*function\s*\(\w+,\s*\w+,\s*\w+\)' \
"HIGH"

# Large base64 strings (potential hidden payloads)
check_pattern \
"Large base64-encoded string (≥100 chars, potential hidden payload)" \
'['\''"][A-Za-z0-9+/=]{100,}['\''"]' \
"HIGH"

# Hex-encoded strings
check_pattern \
"Hex-encoded string ≥40 chars" \
'\\x[0-9a-fA-F]{2}\\x[0-9a-fA-F]{2}\\x[0-9a-fA-F]{2}' \
"MEDIUM"

# String-shuffle decoders
check_pattern \
"String-shuffle / deobfuscation wrapper" \
'\[\]\s*=\s*\(\w+\[\]\[\w+\]\+"\w+"\)' \
"HIGH"

# ---------------------------------------------------------------------------
# 2. DANGEROUS RUNTIME PATTERNS IN BUILD FILES
# ---------------------------------------------------------------------------

echo "→ Scanning for suspicious patterns in build-config files..."

for pattern in 'global\['\''[!$]'\''\]' 'global\s*=\s*global'; do
for match in $(grep -l "$pattern" /tmp/pr-diff.txt 2>/dev/null || true); do
echo -e "${RED}[HIGH]${NC} Suspicious global assignment in build/config file: $match"
WARNINGS=$((WARNINGS + 1))
done
done

# ---------------------------------------------------------------------------
# 3. HIDDEN CODE EXECUTION
# ---------------------------------------------------------------------------

echo "→ Scanning for hidden code execution..."

# eval / Function / setTimeout with long strings (> 80 chars, likely obfuscated)
check_pattern \
"Hidden eval/Function call with large argument" \
'(?:eval|Function|setTimeout|setInterval)\s*\(\s*['\''"`][^)]{80,}['\''"`]\s*\)' \
"HIGH"

# require/module rebinding
check_pattern \
"require/module rebinding via global" \
'global\[.*\]\s*=\s*require' \
"CRITICAL"

# ---------------------------------------------------------------------------
# 4. FILE-TYPE TARGETING
# ---------------------------------------------------------------------------

echo "→ Checking for targeted build-config file modifications..."

# Check if the PR modifies config files that auto-execute
CONFIG_FILES=(
'astro.config.mjs'
'astro.config.ts'
'vite.config.ts'
'vite.config.js'
'next.config.js'
'next.config.mjs'
'webpack.config.js'
'.npmrc'
'.env'
'package.json'
)

for cf in "${CONFIG_FILES[@]}"; do
if grep -q "^.*${cf}\$" /tmp/pr-diff.txt 2>/dev/null; then
echo -e "${YELLOW}[INFO]${NC} PR modifies auto-exec config file: $cf — requires manual review"
WARNINGS=$((WARNINGS + 1))
fi
done

echo "::endgroup::"

# ---------------------------------------------------------------------------
# RESULT
# ---------------------------------------------------------------------------

if [ "$WARNINGS" -gt 0 ]; then
echo ""
echo "⚠️ $WARNINGS suspicious pattern(s) detected — manual security review required before merging."
echo " See https://github.com/Egonex-AI/Understand-Anything/security/advisories for guidance."
exit 1
else
echo "✅ No supply-chain obfuscation patterns detected."
exit 0
fi
60 changes: 60 additions & 0 deletions .github/workflows/supply-chain-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Supply-Chain Security Scan

on:
pull_request:
# Trigger on any PR so we catch supply-chain attacks before review
types: [opened, synchronize, reopened, edited]
paths-ignore:
# Skip docs-only PRs (but NOT build config files)
- '**/*.md'
- '**/*.png'
- '**/*.svg'
- '**/*.jpg'

concurrency:
group: supply-chain-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
scan-obfuscation:
runs-on: ubuntu-latest
if: github.event.pull_request.head.repo.fork || github.event_name != 'pull_request_target'
# ^ Always runs for forks (highest risk). For non-fork PRs, runs on pull_request too.

steps:
- name: Checkout PR head
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0

- name: Generate PR diff
run: |
git diff \
${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} \
> /tmp/pr-diff.txt
echo "Diff size: $(wc -c < /tmp/pr-diff.txt) bytes"
echo "Diff lines: $(wc -l < /tmp/pr-diff.txt)"

- name: Run obfuscation scanner
run: bash .github/scripts/scan-obfuscation.sh

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Run the scanner from trusted code

Because the job checks out the PR head before this line, a malicious fork PR can change .github/scripts/scan-obfuscation.sh in the same PR to simply exit 0 or omit the dangerous patterns, so the supply-chain scan is bypassed exactly in the untrusted PRs it is meant to catch. Run the scanner from the base repository/workflow checkout or otherwise pin the script before checking out untrusted code.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make the manual-review path actually non-blocking

When scan-obfuscation.sh finds any warning it exits 1, and GitHub Actions keeps the job failed even though the following if: failure() comment step runs; without continue-on-error or capturing the exit code manually, PRs that only modify package.json or a build config will get a red check rather than the documented non-blocking warning, which can block merges if this workflow is required.

Useful? React with 👍 / 👎.


- name: Flag for manual review (non-blocking)
if: failure()
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
Comment on lines +47 to +50

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid posting fork warnings with a read-only token

In fork PRs, which this workflow explicitly targets, the pull_request GITHUB_TOKEN is read-only, while creating an issue/PR comment requires issues: write or pull-requests: write; this github.rest.issues.createComment call will fail with a permission error instead of surfacing the scanner warning to maintainers unless the notification is moved to a privileged follow-up workflow or another safe reporting mechanism.

Useful? React with 👍 / 👎.

body: `⚠️ **Supply-chain security scan detected suspicious patterns** in this PR.

The obfuscation scanner found code patterns commonly associated with supply-chain attacks (packed/obfuscated JavaScript, suspicious global assignments, hidden eval calls).

**Action required:** A maintainer must manually review the diff before merging.
See the [scan-obfuscation.sh](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/main/.github/scripts/scan-obfuscation.sh) script for details.

If this is a false positive, a maintainer can override this check.
For legitimate security concerns, please report via [Security Advisories](https://github.com/${context.repo.owner}/${context.repo.repo}/security/advisories/new).`
});
20 changes: 14 additions & 6 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ Thanks for taking the time to disclose responsibly.

## How to report

Please use GitHub's [private vulnerability reporting](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability)
on this repository. That keeps the report visible to the maintainer without
exposing the details publicly.
👉 **Please use the [Security Advisories](https://github.com/Egonex-AI/Understand-Anything/security/advisories/new) page** to privately report a vulnerability.
This sends the report directly to the maintainers and keeps details confidential
until a fix ships.

If private reporting is unavailable for any reason, open a regular issue
titled `security: brief description` **without** any exploit details, and
the maintainer will reply with a private channel.
If the Security Advisories page is unavailable for any reason, email
**security@egonex.ai** or open a regular issue titled `security: brief description`
**without** any exploit details, and the maintainer will reply with a private channel.

> ⚠️ **Do not** submit vulnerability details in a public issue, pull request, or
> discussion — that puts every user at risk before a fix can ship.

## What to include

Expand Down Expand Up @@ -42,10 +45,15 @@ Issues we care about:
- The dashboard's file-content endpoint serving files outside the allowlist.
- The `/understand` skill running shell commands derived from untrusted
paths or contents.
- Supply-chain attacks via pull requests (obfuscated payloads, dependency
hijacking, build-time code execution from PR-diff content).
- Malicious PRs that modify build-config files (e.g. `astro.config.mjs`,
`vite.config.ts`, `next.config.js`) with obfuscated or packed code.

Issues that are **out of scope**:

- Bugs that require a malicious local user with write access to the
analyzed project (they could just edit the source directly).
- Anything that requires the user to copy a malicious URL and paste it back
into the dashboard.
- Social-engineering-only attacks with no technical exploit.
Loading