Skip to content

Commit eaa63fe

Browse files
committed
fix: harden supply-chain security via obfuscation scanner + advisory policy
- Add CI workflow (supply-chain-scan.yml) scanning PR diffs for obfuscation/supply-chain attack patterns - Add .github/scripts/scan-obfuscation.sh: detection of packed code, hidden eval, global hijack, base64/hex payloads, build-config targeting - Update SECURITY.md: actionable advisory link, email fallback, supply-chain as in-scope - Non-blocking: scan runs on all PRs, auto-comments when suspicious patterns found but does not block merge - Mitigates real-world supply-chain attacks seen in this repo (PR #198, #206, #261)
1 parent 09ede19 commit eaa63fe

3 files changed

Lines changed: 208 additions & 6 deletions

File tree

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#!/usr/bin/env bash
2+
# Supply-chain obfuscation scanner
3+
# Scans PR diffs for patterns commonly found in malicious supply-chain attacks:
4+
# - Obfuscated code (packed, shuffled, base64-encoded, hex-encoded)
5+
# - Suspicious global/prototype assignments in build config files
6+
# - Hidden eval / Function constructor calls
7+
# - Large diffs dominated by non-human-readable strings
8+
#
9+
# Exit 0 = clean. Exit 1 = suspicious patterns found (review required).
10+
11+
set -euo pipefail
12+
13+
RED='\033[0;31m'
14+
YELLOW='\033[1;33m'
15+
NC='\033[0m' # No Color
16+
17+
WARNINGS=0
18+
19+
check_pattern() {
20+
local label="$1"
21+
local pattern="$2"
22+
local severity="${3:-WARN}"
23+
24+
if grep -n -P "$pattern" /tmp/pr-diff.txt 2>/dev/null; then
25+
echo -e "${RED}[${severity}]${NC} $label — matches found (see above)"
26+
WARNINGS=$((WARNINGS + 1))
27+
fi
28+
}
29+
30+
echo "::group::Obfuscation Scan"
31+
32+
# ---------------------------------------------------------------------------
33+
# 1. OBFUSCATION PATTERNS
34+
# ---------------------------------------------------------------------------
35+
36+
echo "→ Scanning for obfuscation patterns..."
37+
38+
# Packed/obfuscated code blocks (long base64-like strings, hex chains)
39+
check_pattern \
40+
"Packed/obfuscated JavaScript blob (self-decoding function pattern)" \
41+
'(\w+),\s*\w+\s*=\s*function\s*\(\w+,\s*\w+,\s*\w+\)' \
42+
"HIGH"
43+
44+
# Large base64 strings (potential hidden payloads)
45+
check_pattern \
46+
"Large base64-encoded string (≥100 chars, potential hidden payload)" \
47+
'['\''"][A-Za-z0-9+/=]{100,}['\''"]' \
48+
"HIGH"
49+
50+
# Hex-encoded strings
51+
check_pattern \
52+
"Hex-encoded string ≥40 chars" \
53+
'\\x[0-9a-fA-F]{2}\\x[0-9a-fA-F]{2}\\x[0-9a-fA-F]{2}' \
54+
"MEDIUM"
55+
56+
# String-shuffle decoders
57+
check_pattern \
58+
"String-shuffle / deobfuscation wrapper" \
59+
'\[\]\s*=\s*\(\w+\[\]\[\w+\]\+"\w+"\)' \
60+
"HIGH"
61+
62+
# ---------------------------------------------------------------------------
63+
# 2. DANGEROUS RUNTIME PATTERNS IN BUILD FILES
64+
# ---------------------------------------------------------------------------
65+
66+
echo "→ Scanning for suspicious patterns in build-config files..."
67+
68+
for pattern in 'global\['\''[!$]'\''\]' 'global\s*=\s*global'; do
69+
for match in $(grep -l "$pattern" /tmp/pr-diff.txt 2>/dev/null || true); do
70+
echo -e "${RED}[HIGH]${NC} Suspicious global assignment in build/config file: $match"
71+
WARNINGS=$((WARNINGS + 1))
72+
done
73+
done
74+
75+
# ---------------------------------------------------------------------------
76+
# 3. HIDDEN CODE EXECUTION
77+
# ---------------------------------------------------------------------------
78+
79+
echo "→ Scanning for hidden code execution..."
80+
81+
# eval / Function / setTimeout with long strings (> 80 chars, likely obfuscated)
82+
check_pattern \
83+
"Hidden eval/Function call with large argument" \
84+
'(?:eval|Function|setTimeout|setInterval)\s*\(\s*['\''"`][^)]{80,}['\''"`]\s*\)' \
85+
"HIGH"
86+
87+
# require/module rebinding
88+
check_pattern \
89+
"require/module rebinding via global" \
90+
'global\[.*\]\s*=\s*require' \
91+
"CRITICAL"
92+
93+
# ---------------------------------------------------------------------------
94+
# 4. FILE-TYPE TARGETING
95+
# ---------------------------------------------------------------------------
96+
97+
echo "→ Checking for targeted build-config file modifications..."
98+
99+
# Check if the PR modifies config files that auto-execute
100+
CONFIG_FILES=(
101+
'astro.config.mjs'
102+
'astro.config.ts'
103+
'vite.config.ts'
104+
'vite.config.js'
105+
'next.config.js'
106+
'next.config.mjs'
107+
'webpack.config.js'
108+
'.npmrc'
109+
'.env'
110+
'package.json'
111+
)
112+
113+
for cf in "${CONFIG_FILES[@]}"; do
114+
if grep -q "^.*${cf}\$" /tmp/pr-diff.txt 2>/dev/null; then
115+
echo -e "${YELLOW}[INFO]${NC} PR modifies auto-exec config file: $cf — requires manual review"
116+
WARNINGS=$((WARNINGS + 1))
117+
fi
118+
done
119+
120+
echo "::endgroup::"
121+
122+
# ---------------------------------------------------------------------------
123+
# RESULT
124+
# ---------------------------------------------------------------------------
125+
126+
if [ "$WARNINGS" -gt 0 ]; then
127+
echo ""
128+
echo "⚠️ $WARNINGS suspicious pattern(s) detected — manual security review required before merging."
129+
echo " See https://github.com/Egonex-AI/Understand-Anything/security/advisories for guidance."
130+
exit 1
131+
else
132+
echo "✅ No supply-chain obfuscation patterns detected."
133+
exit 0
134+
fi
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: Supply-Chain Security Scan
2+
3+
on:
4+
pull_request:
5+
# Trigger on any PR so we catch supply-chain attacks before review
6+
types: [opened, synchronize, reopened, edited]
7+
paths-ignore:
8+
# Skip docs-only PRs (but NOT build config files)
9+
- '**/*.md'
10+
- '**/*.png'
11+
- '**/*.svg'
12+
- '**/*.jpg'
13+
14+
concurrency:
15+
group: supply-chain-${{ github.event.pull_request.number }}
16+
cancel-in-progress: true
17+
18+
jobs:
19+
scan-obfuscation:
20+
runs-on: ubuntu-latest
21+
if: github.event.pull_request.head.repo.fork || github.event_name != 'pull_request_target'
22+
# ^ Always runs for forks (highest risk). For non-fork PRs, runs on pull_request too.
23+
24+
steps:
25+
- name: Checkout PR head
26+
uses: actions/checkout@v4
27+
with:
28+
ref: ${{ github.event.pull_request.head.sha }}
29+
fetch-depth: 0
30+
31+
- name: Generate PR diff
32+
run: |
33+
git diff \
34+
${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} \
35+
> /tmp/pr-diff.txt
36+
echo "Diff size: $(wc -c < /tmp/pr-diff.txt) bytes"
37+
echo "Diff lines: $(wc -l < /tmp/pr-diff.txt)"
38+
39+
- name: Run obfuscation scanner
40+
run: bash .github/scripts/scan-obfuscation.sh
41+
42+
- name: Flag for manual review (non-blocking)
43+
if: failure()
44+
uses: actions/github-script@v7
45+
with:
46+
script: |
47+
await github.rest.issues.createComment({
48+
owner: context.repo.owner,
49+
repo: context.repo.repo,
50+
issue_number: context.issue.number,
51+
body: `⚠️ **Supply-chain security scan detected suspicious patterns** in this PR.
52+
53+
The obfuscation scanner found code patterns commonly associated with supply-chain attacks (packed/obfuscated JavaScript, suspicious global assignments, hidden eval calls).
54+
55+
**Action required:** A maintainer must manually review the diff before merging.
56+
See the [scan-obfuscation.sh](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/main/.github/scripts/scan-obfuscation.sh) script for details.
57+
58+
If this is a false positive, a maintainer can override this check.
59+
For legitimate security concerns, please report via [Security Advisories](https://github.com/${context.repo.owner}/${context.repo.repo}/security/advisories/new).`
60+
});

SECURITY.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ Thanks for taking the time to disclose responsibly.
44

55
## How to report
66

7-
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)
8-
on this repository. That keeps the report visible to the maintainer without
9-
exposing the details publicly.
7+
👉 **Please use the [Security Advisories](https://github.com/Egonex-AI/Understand-Anything/security/advisories/new) page** to privately report a vulnerability.
8+
This sends the report directly to the maintainers and keeps details confidential
9+
until a fix ships.
1010

11-
If private reporting is unavailable for any reason, open a regular issue
12-
titled `security: brief description` **without** any exploit details, and
13-
the maintainer will reply with a private channel.
11+
If the Security Advisories page is unavailable for any reason, email
12+
**security@egonex.ai** or open a regular issue titled `security: brief description`
13+
**without** any exploit details, and the maintainer will reply with a private channel.
14+
15+
> ⚠️ **Do not** submit vulnerability details in a public issue, pull request, or
16+
> discussion — that puts every user at risk before a fix can ship.
1417
1518
## What to include
1619

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

4653
Issues that are **out of scope**:
4754

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

0 commit comments

Comments
 (0)