reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
3
reverse-skill-repo/.github/FUNDING.yml
vendored
Normal file
3
reverse-skill-repo/.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# GitHub funding links
|
||||
custom:
|
||||
- "mailto:ww7517437@gmail.com"
|
||||
172
reverse-skill-repo/.github/workflows/auto-merge-journal.yml
vendored
Normal file
172
reverse-skill-repo/.github/workflows/auto-merge-journal.yml
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
name: Auto-merge field-journal PRs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
paths:
|
||||
- 'skills/field-journal/**'
|
||||
|
||||
jobs:
|
||||
validate-and-merge:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_SUBJECT: ${{ format('[field-journal] {0}', github.event.pull_request.title) }}
|
||||
|
||||
steps:
|
||||
- name: Checkout PR
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Validate PR safety
|
||||
id: validate
|
||||
run: |
|
||||
set -e
|
||||
|
||||
# 1. 只允许修改 field-journal 目录下的 .md 文件
|
||||
CHANGED_FILES=$(gh pr diff "$PR_NUMBER" --name-only)
|
||||
echo "Changed files:"
|
||||
echo "$CHANGED_FILES"
|
||||
|
||||
# 严格白名单:只允许 field-journal 下的 .md 文件
|
||||
INVALID_FILES=$(echo "$CHANGED_FILES" | grep -v '^skills/field-journal/.*\.md$' || true)
|
||||
if [ -n "$INVALID_FILES" ]; then
|
||||
echo "❌ BLOCKED: PR 修改了非 field-journal 文件"
|
||||
echo "$INVALID_FILES"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 不允许修改 CONTRIBUTE-BACK.md 和 _template.md(系统文件)
|
||||
SYSTEM_FILES=$(echo "$CHANGED_FILES" | grep -E '(CONTRIBUTE-BACK\.md|_template\.md)' || true)
|
||||
if [ -n "$SYSTEM_FILES" ]; then
|
||||
echo "❌ BLOCKED: 不允许修改系统文件"
|
||||
echo "$SYSTEM_FILES"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. 文件数量限制(单次 PR 最多 5 个文件)
|
||||
FILE_COUNT=$(echo "$CHANGED_FILES" | wc -l)
|
||||
if [ "$FILE_COUNT" -gt 5 ]; then
|
||||
echo "❌ BLOCKED: 单次 PR 文件数超过 5 个(实际 $FILE_COUNT)"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 3. 逐文件安全扫描
|
||||
for file in $CHANGED_FILES; do
|
||||
if [ ! -f "$file" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "--- Scanning: $file ---"
|
||||
|
||||
# 3a. Prompt injection 检测(宽模式)
|
||||
if grep -iE "(ignore previous|ignore all|you are now|forget (all|everything)|disregard|new instructions|system prompt|override|jailbreak|DAN mode|bypass safety)" "$file"; then
|
||||
echo "❌ BLOCKED: $file 包含 prompt injection 特征"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 3b. HTML/JS 注入检测
|
||||
if grep -iE "(<script|<iframe|<object|<embed|<form|<input|javascript:|onerror=|onload=|onclick=|onmouseover=|onfocus=|data:text/html)" "$file"; then
|
||||
echo "❌ BLOCKED: $file 包含 HTML/JS 注入代码"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 3c. 可执行代码/shell 命令伪装检测
|
||||
if grep -E "^(#!/|import os|import subprocess|require\('child_process|from os import|exec\(|eval\(|os\.system|subprocess\.|Runtime\.getRuntime|ProcessBuilder|powershell -e|cmd /c|curl .* \| (bash|sh)|wget .* -O- \| (bash|sh))" "$file"; then
|
||||
echo "❌ BLOCKED: $file 包含可执行代码/恶意命令"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 3d. 编码绕过检测(base64 编码的命令)
|
||||
if grep -iE "(base64 -d|base64 --decode|atob\(|Buffer\.from\(.*base64|echo .* \| base64)" "$file"; then
|
||||
echo "❌ BLOCKED: $file 包含 base64 编码绕过特征"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 3e. 未脱敏 token/key 检测(扩展模式)
|
||||
if grep -iE "(AKIA[0-9A-Z]{16}|sk-[a-zA-Z0-9]{20,}|ghp_[a-zA-Z0-9]{36}|gho_[a-zA-Z0-9]{36}|npm_[a-zA-Z0-9]{36}|xox[baprs]-[a-zA-Z0-9-]+|ya29\.[a-zA-Z0-9_-]+|AIza[a-zA-Z0-9_-]{35}|[0-9]+-[a-zA-Z0-9_]{32}\.apps\.googleusercontent\.com|sk_live_[a-zA-Z0-9]{24,}|rk_live_[a-zA-Z0-9]{24,}|sq0atp-[a-zA-Z0-9_-]{22})" "$file"; then
|
||||
echo "❌ BLOCKED: $file 包含疑似真实 API key/token"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 3f. 真实 IP 地址检测(非 RFC1918 私有地址、非示例地址)
|
||||
# 允许: 10.x.x.x, 172.16-31.x.x, 192.168.x.x, 127.x.x.x, 0.0.0.0
|
||||
if grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' "$file" | grep -vE '^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|127\.|0\.0\.0\.0|255\.|224\.)' | grep -vE '^(198\.51\.100\.|203\.0\.113\.|192\.0\.2\.)' | head -5 > /tmp/real_ips; then
|
||||
if [ -s /tmp/real_ips ]; then
|
||||
echo "⚠️ WARNING: $file 可能包含未脱敏的真实 IP:"
|
||||
cat /tmp/real_ips
|
||||
echo "❌ BLOCKED: 请将真实 IP 替换为 10.x.x.x 或 192.168.x.x"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# 3g. 文件大小检查(单文件 50KB 上限)
|
||||
SIZE=$(wc -c < "$file")
|
||||
if [ "$SIZE" -gt 51200 ]; then
|
||||
echo "❌ BLOCKED: $file 超过 50KB($SIZE bytes)"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 3h. Markdown 结构验证(必须以 # 开头,证明是正常 journal)
|
||||
FIRST_CONTENT_LINE=$(grep -m1 -v '^$' "$file" || echo "")
|
||||
if [[ ! "$FIRST_CONTENT_LINE" =~ ^#\ ]]; then
|
||||
echo "❌ BLOCKED: $file 不是有效的 field-journal 格式(必须以 # 标题开头)"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 3i. 链接/URL 安全检测(不允许外部可执行链接)
|
||||
if grep -iE "(https?://.*\.(exe|msi|bat|cmd|ps1|sh|py|rb|pl|vbs|js)(\?|$|[\"' ]))" "$file"; then
|
||||
echo "❌ BLOCKED: $file 包含指向可执行文件的外部链接"
|
||||
echo "valid=false" >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ $file 通过安全检查"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "✅ 所有文件通过安全审核"
|
||||
echo "valid=true" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Auto-merge if valid
|
||||
if: steps.validate.outputs.valid == 'true'
|
||||
run: |
|
||||
gh pr merge "$PR_NUMBER" \
|
||||
--auto --squash \
|
||||
--subject "$PR_SUBJECT"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Comment on failure
|
||||
if: steps.validate.outputs.valid == 'false'
|
||||
run: |
|
||||
gh pr comment "$PR_NUMBER" \
|
||||
--body "❌ **自动审核未通过**
|
||||
|
||||
本 PR 未通过安全检查,无法自动合并。可能的原因:
|
||||
- 修改了 field-journal 以外的文件
|
||||
- 内容包含可疑的 prompt injection 特征
|
||||
- 内容包含未脱敏的 API key/token
|
||||
- 单个文件超过 50KB
|
||||
|
||||
请检查并修正后重新提交。"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
193
reverse-skill-repo/.github/workflows/ci.yml
vendored
Normal file
193
reverse-skill-repo/.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
# reverse-skill CI:路由回归 + 结构一致性 + 供应链 pin gate + 冒烟
|
||||
# 矩阵:windows-latest(原生 powershell 5.1) + ubuntu-latest(pwsh + powershell shim)
|
||||
# 触发:所有分支(含 fork 的改进分支),PR 也触发
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
routing-tests:
|
||||
name: routing tests (${{ matrix.os }})
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
# 脚本内部以 `powershell` 调用子进程;Linux runner 只有 pwsh,做个 shim
|
||||
- name: powershell shim (linux)
|
||||
if: runner.os == 'Linux'
|
||||
shell: bash
|
||||
run: sudo ln -sf "$(command -v pwsh)" /usr/local/bin/powershell
|
||||
|
||||
- name: Routing regression (163 cases)
|
||||
shell: pwsh
|
||||
run: ./skills/scripts/test-routing.ps1
|
||||
|
||||
- name: Routing coherence + supply-chain pin gate
|
||||
shell: pwsh
|
||||
run: ./skills/scripts/verify-routing-coherence.ps1
|
||||
|
||||
- name: Smoke (verify + parse + quick route)
|
||||
shell: pwsh
|
||||
run: ./skills/scripts/smoke.ps1
|
||||
|
||||
- name: INDEX.md up-to-date check
|
||||
shell: pwsh
|
||||
run: ./skills/scripts/extract-summaries.ps1 -Check
|
||||
|
||||
- name: All JSON manifests valid
|
||||
shell: pwsh
|
||||
run: |
|
||||
Get-Content skills/scripts/bootstrap-manifest.json -Raw -Encoding UTF8 | ConvertFrom-Json | Out-Null
|
||||
Get-Content kali/scripts/bootstrap-manifest.json -Raw -Encoding UTF8 | ConvertFrom-Json | Out-Null
|
||||
Get-Content skills/config/routing.json -Raw -Encoding UTF8 | ConvertFrom-Json | Out-Null
|
||||
Get-Content skills/tests/routing-benchmark.json -Raw -Encoding UTF8 | ConvertFrom-Json | Out-Null
|
||||
Write-Host "All JSON valid"
|
||||
|
||||
- name: Doc fact tables vs manifest (verify-doc-facts)
|
||||
shell: pwsh
|
||||
run: ./skills/scripts/verify-doc-facts.ps1
|
||||
|
||||
sh-syntax:
|
||||
name: shell script syntax check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: bash -n all .sh
|
||||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
while IFS= read -r f; do
|
||||
bash -n "$f"
|
||||
echo "syntax OK: $f"
|
||||
done < <(git ls-files '*.sh')
|
||||
|
||||
- name: Structured routing parity (Bash)
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
bash skills/scripts/test-routing.sh
|
||||
|
||||
scratch="$(mktemp -d)"
|
||||
trap 'rm -rf "$scratch"' EXIT
|
||||
|
||||
if bash skills/scripts/case-init.sh \
|
||||
--hint "offline apk" \
|
||||
--case-name "../case-escape" \
|
||||
--package-root "$scratch/project" \
|
||||
--preset offline-sample \
|
||||
--sample "$scratch/sample.apk"; then
|
||||
echo "case-init accepted an unsafe case name" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if bash skills/scripts/case-init.sh \
|
||||
--hint "authorized web review" \
|
||||
--case-name "invalid-network" \
|
||||
--package-root "$scratch/project" \
|
||||
--auth-granted \
|
||||
--network-profile "internet" \
|
||||
--target-url "https://example.test/"; then
|
||||
echo "case-init accepted an unsupported network profile" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
bash skills/scripts/case-init.sh \
|
||||
--hint "authorized web review" \
|
||||
--case-name "network-default" \
|
||||
--package-root "$scratch/project" \
|
||||
--auth-granted \
|
||||
--target-url "https://example.test/"
|
||||
grep -Eq '^- mode: authorized_target_only$' "$scratch/project/work/network-default/scope.md"
|
||||
grep -Eq '^- ready_for_act: true$' "$scratch/project/work/network-default/scope.md"
|
||||
bash skills/scripts/case-guard.sh --case-root "$scratch/project/work/network-default"
|
||||
|
||||
bash skills/scripts/case-init.sh \
|
||||
--hint "authorized web review" \
|
||||
--case-name "uppercase-network" \
|
||||
--package-root "$scratch/project" \
|
||||
--auth-granted \
|
||||
--network-profile "AUTHORIZED_TARGET_ONLY" \
|
||||
--target-url "https://example.test/"
|
||||
grep -Eq '^- mode: authorized_target_only$' "$scratch/project/work/uppercase-network/scope.md"
|
||||
|
||||
bash skills/scripts/case-init.sh \
|
||||
--hint "pending review" \
|
||||
--case-name "guard-section" \
|
||||
--package-root "$scratch/project" \
|
||||
--target-url "https://example.test/"
|
||||
cat >> "$scratch/project/work/guard-section/scope.md" <<'FAKE_FIELDS'
|
||||
|
||||
## notes
|
||||
- status: granted
|
||||
- mode: authorized_target_only
|
||||
- ready_for_act: true
|
||||
FAKE_FIELDS
|
||||
if bash skills/scripts/case-guard.sh --case-root "$scratch/project/work/guard-section"; then
|
||||
echo "case-guard accepted fields outside their contract sections" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: PowerShell syntax check (PSParser, all tracked .ps1)
|
||||
shell: pwsh
|
||||
run: |
|
||||
$files = git ls-files '*.ps1'
|
||||
if (-not $files) { Write-Host 'No .ps1 files tracked'; exit 0 }
|
||||
$failed = 0
|
||||
foreach ($f in $files) {
|
||||
$tokens = $null
|
||||
$errors = $null
|
||||
[System.Management.Automation.Language.Parser]::ParseFile((Resolve-Path $f), [ref]$tokens, [ref]$errors) | Out-Null
|
||||
if ($errors -and $errors.Count -gt 0) {
|
||||
$failed++
|
||||
Write-Host "::error file=$f::$($errors.Count) parse error(s)"
|
||||
foreach ($e in $errors) {
|
||||
Write-Host (" L{0}:{1} {2}" -f $e.Extent.StartLineNumber, $e.Extent.StartColumnNumber, $e.Message)
|
||||
}
|
||||
} else {
|
||||
Write-Host "syntax OK: $f"
|
||||
}
|
||||
}
|
||||
if ($failed -gt 0) { exit 1 }
|
||||
|
||||
leak-scan:
|
||||
name: field-journal leak scan
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Scan field-journal for un-anonymized secrets
|
||||
shell: pwsh
|
||||
run: ./skills/scripts/scan-leaks.ps1 -Path skills/field-journal
|
||||
|
||||
case-contract:
|
||||
name: case contract test (ctf-demo)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Review examples/ctf-demo under strict contract
|
||||
shell: bash
|
||||
run: python3 skills/case-review/scripts/review_case.py examples/ctf-demo --verify-hashes --strict
|
||||
|
||||
version-check:
|
||||
name: version consistency
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: VERSION matches latest CHANGELOG release
|
||||
shell: pwsh
|
||||
run: |
|
||||
$v = (Get-Content VERSION -Raw).Trim()
|
||||
$cl = Get-Content CHANGELOG.md -Raw
|
||||
$m = [regex]::Match($cl, '(?m)^## \[(\d+\.\d+\.\d+)\]')
|
||||
if (-not $m.Success) { Write-Error 'No version header found in CHANGELOG'; exit 1 }
|
||||
$latest = $m.Groups[1].Value
|
||||
if ($v -ne $latest) {
|
||||
Write-Error "VERSION ($v) does not match latest CHANGELOG release ($latest)"
|
||||
exit 1
|
||||
}
|
||||
Write-Host "Version OK: $v"
|
||||
70
reverse-skill-repo/.github/workflows/macos-bash-compat.yml
vendored
Normal file
70
reverse-skill-repo/.github/workflows/macos-bash-compat.yml
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
name: macOS Bash compatibility
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'skills/scripts/**/*.sh'
|
||||
- 'skills/scripts/*.sh'
|
||||
- '.github/workflows/macos-bash-compat.yml'
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'skills/scripts/**/*.sh'
|
||||
- 'skills/scripts/*.sh'
|
||||
- '.github/workflows/macos-bash-compat.yml'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
system-bash:
|
||||
name: system Bash compatibility
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Show system Bash version
|
||||
shell: bash
|
||||
run: /bin/bash --version | head -n 1
|
||||
|
||||
- name: Parse all tracked shell scripts with system Bash
|
||||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
git ls-files '*.sh' | while IFS= read -r f; do
|
||||
/bin/bash -n "$f"
|
||||
echo "syntax OK: $f"
|
||||
done
|
||||
|
||||
- name: Exercise structured router and case contract
|
||||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
scratch="$(mktemp -d)"
|
||||
trap 'rm -rf "$scratch"' EXIT
|
||||
|
||||
/bin/bash skills/scripts/master-route.sh \
|
||||
--hint "apk reverse with jadx" \
|
||||
--out-dir "$scratch/route"
|
||||
grep -Eq '^- primary: R1$' "$scratch/route/route-scope.md"
|
||||
|
||||
/bin/bash skills/scripts/case-init.sh \
|
||||
--hint "authorized web review" \
|
||||
--case-name "network-default" \
|
||||
--package-root "$scratch/project" \
|
||||
--auth-granted \
|
||||
--target-url "https://example.test/"
|
||||
grep -Eq '^- mode: authorized_target_only$' "$scratch/project/work/network-default/scope.md"
|
||||
grep -Eq '^- ready_for_act: true$' "$scratch/project/work/network-default/scope.md"
|
||||
/bin/bash skills/scripts/case-guard.sh \
|
||||
--case-root "$scratch/project/work/network-default"
|
||||
|
||||
/bin/bash skills/scripts/case-init.sh \
|
||||
--hint "authorized web review" \
|
||||
--case-name "uppercase-network" \
|
||||
--package-root "$scratch/project" \
|
||||
--auth-granted \
|
||||
--network-profile "AUTHORIZED_TARGET_ONLY" \
|
||||
--target-url "https://example.test/"
|
||||
grep -Eq '^- mode: authorized_target_only$' "$scratch/project/work/uppercase-network/scope.md"
|
||||
Reference in New Issue
Block a user