Merge pull request #92 from jhuang-tw/fix/cross-platform-case-contract
fix: make case setup consistent across Windows, Linux, and macOS Owner integration: preserve routing.json SSoT, keep reports optional by default, and require offline samples to resolve to real local files.
This commit is contained in:
+99
-10
@@ -49,6 +49,51 @@ jobs:
|
||||
shell: pwsh
|
||||
run: ./skills/scripts/test-workflow-title-safety.ps1
|
||||
|
||||
- name: Offline sample case contract (Windows PowerShell 5.1)
|
||||
if: runner.os == 'Windows'
|
||||
shell: powershell
|
||||
run: |
|
||||
$scratch = Join-Path $env:RUNNER_TEMP ("reverse-skill-offline-" + [guid]::NewGuid().ToString('n'))
|
||||
New-Item -ItemType Directory -Force -Path $scratch | Out-Null
|
||||
$sample = Join-Path $scratch 'sample.apk'
|
||||
Set-Content -Path $sample -Value 'fixture' -Encoding ASCII
|
||||
|
||||
./skills/scripts/case-init.ps1 `
|
||||
-Hint "offline apk" `
|
||||
-CaseName "offline-sample" `
|
||||
-ProjectRoot $scratch `
|
||||
-Preset offline-sample `
|
||||
-Sample $sample
|
||||
$scope = Join-Path $scratch 'work/offline-sample/scope.md'
|
||||
$raw = Get-Content $scope -Raw
|
||||
if ($raw -notmatch '(?m)^- mode: offline\r?$') { throw 'offline sample did not keep offline network mode' }
|
||||
if ($raw -notmatch '(?m)^- ready_for_act: true\r?$') { throw 'offline sample did not become ready_for_act' }
|
||||
./skills/scripts/case-guard.ps1 -CaseRoot (Join-Path $scratch 'work/offline-sample')
|
||||
|
||||
try {
|
||||
./skills/scripts/case-init.ps1 `
|
||||
-Hint "missing offline apk" `
|
||||
-CaseName "missing-sample" `
|
||||
-ProjectRoot $scratch `
|
||||
-Preset offline-sample `
|
||||
-Sample (Join-Path $scratch 'missing.apk')
|
||||
throw 'missing offline sample was accepted'
|
||||
} catch {
|
||||
if ($_.Exception.Message -eq 'missing offline sample was accepted') { throw }
|
||||
}
|
||||
|
||||
./skills/scripts/case-init.ps1 `
|
||||
-Hint "pending offline apk" `
|
||||
-CaseName "force-auth" `
|
||||
-ProjectRoot $scratch `
|
||||
-Sample $sample
|
||||
& powershell -NoProfile -ExecutionPolicy Bypass -File ./skills/scripts/case-guard.ps1 `
|
||||
-CaseRoot (Join-Path $scratch 'work/force-auth') `
|
||||
-Force
|
||||
$guardExit = $LASTEXITCODE
|
||||
if ($guardExit -eq 0) { throw '-Force bypassed auth.status hard gate' }
|
||||
$global:LASTEXITCODE = 0
|
||||
|
||||
- name: Smoke (verify + parse + quick route)
|
||||
shell: pwsh
|
||||
run: ./skills/scripts/smoke.ps1
|
||||
@@ -94,6 +139,47 @@ jobs:
|
||||
scratch="$(mktemp -d)"
|
||||
trap 'rm -rf "$scratch"' EXIT
|
||||
|
||||
# Fresh Linux journey: no pwsh required, artifacts stay in caller project.
|
||||
caller="$scratch/caller-project"
|
||||
mkdir -p "$caller"
|
||||
printf 'fixture' > "$scratch/sample.apk"
|
||||
(
|
||||
cd "$caller"
|
||||
bash "$GITHUB_WORKSPACE/skills/scripts/master-route.sh" --hint "offline apk"
|
||||
bash "$GITHUB_WORKSPACE/skills/scripts/case-init.sh" \
|
||||
--hint "offline apk" \
|
||||
--case-name "caller-default" \
|
||||
--preset offline-sample \
|
||||
--sample "$scratch/sample.apk"
|
||||
)
|
||||
test -f "$caller/work/caller-default/scope.md"
|
||||
grep -Eq '^- project_root: .*/caller-project$' "$caller/work/caller-default/scope.md"
|
||||
grep -Eq '^- mode: offline$' "$caller/work/caller-default/scope.md"
|
||||
grep -Eq '^- ready_for_act: true$' "$caller/work/caller-default/scope.md"
|
||||
bash skills/scripts/case-guard.sh --case-root "$caller/work/caller-default"
|
||||
test ! -e "$GITHUB_WORKSPACE/work/caller-default"
|
||||
|
||||
if bash skills/scripts/case-init.sh \
|
||||
--hint "missing offline apk" \
|
||||
--case-name "missing-sample" \
|
||||
--project-root "$caller" \
|
||||
--preset offline-sample \
|
||||
--sample "$scratch/missing.apk"; then
|
||||
echo "missing offline sample was accepted" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Compatibility: legacy --package-root still pins the work root.
|
||||
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"
|
||||
|
||||
if bash skills/scripts/case-init.sh \
|
||||
--hint "offline apk" \
|
||||
--case-name "../case-escape" \
|
||||
@@ -115,16 +201,6 @@ jobs:
|
||||
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" \
|
||||
@@ -151,6 +227,19 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --force is compatibility-only and must not bypass the hard auth gate.
|
||||
(
|
||||
cd "$caller"
|
||||
bash "$GITHUB_WORKSPACE/skills/scripts/case-init.sh" \
|
||||
--hint "pending offline apk" \
|
||||
--case-name "force-auth" \
|
||||
--sample "$scratch/sample.apk"
|
||||
)
|
||||
if bash skills/scripts/case-guard.sh --case-root "$caller/work/force-auth" --force; then
|
||||
echo "case-guard --force bypassed auth.status hard gate" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: PowerShell syntax check (PSParser, all tracked .ps1)
|
||||
shell: pwsh
|
||||
run: |
|
||||
|
||||
@@ -6,37 +6,44 @@
|
||||
|
||||
用户任务命中安全/逆向关键词时:
|
||||
|
||||
1. `skills/MASTER-ROUTING.md` 或 `powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/master-route.ps1 -Hint "<任务>"` → PRIMARY
|
||||
1. `skills/MASTER-ROUTING.md` 或平台对应入口 → PRIMARY:
|
||||
- Windows:`powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/master-route.ps1 -Hint "<任务>"`
|
||||
- Linux / macOS / Kali:`bash skills/scripts/master-route.sh --hint "<任务>"`
|
||||
2. 歧义时读 `skills/routing.md` 全矩阵(三轴:目标类型 / 用户意图 / 工具链)
|
||||
3. 路由规则唯一事实源:`skills/config/routing.json`(改路由只改这里)
|
||||
|
||||
## 授权门禁(硬性)
|
||||
|
||||
- 对任何目标动手前:`powershell -File skills/scripts/case-init.ps1 -Hint "<任务>"` 生成 `work/<case>/scope.md`
|
||||
- `auth.status=granted` + `network_profile` 就绪前**禁止 ACT**
|
||||
- 对任何目标动手前,按平台初始化当前分析项目的 `work/<case>/scope.md`:
|
||||
- Windows:`powershell -File skills/scripts/case-init.ps1 -Hint "<任务>"`
|
||||
- Linux / macOS / Kali:`bash skills/scripts/case-init.sh --hint "<任务>"`
|
||||
- 本地离线样本可使用 `offline-sample` preset;`auth.status=granted` + 明确 sample 才可进入 ACT。
|
||||
- `auth.status=granted` + 合法 `network_profile` / offline sample 就绪前**禁止 ACT**;`case-guard --force` / `-Force` 不得绕过这个硬门。
|
||||
- 证据链:`skills/ops/evidence-finding-path.md`;角色:`skills/ops/role-map.md`
|
||||
|
||||
## 首次运行
|
||||
|
||||
`skills/tool-index.md` 是 gitignored 的生成文件,首次使用前运行:
|
||||
`skills/tool-index.md` 是 gitignored 的生成文件,首次使用前按平台运行:
|
||||
|
||||
```powershell
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/refresh-tool-index.ps1
|
||||
```text
|
||||
Windows: powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/refresh-tool-index.ps1
|
||||
Linux / macOS: bash skills/scripts/refresh-tool-index.sh
|
||||
Kali: bash kali/scripts/refresh-tool-index.sh
|
||||
```
|
||||
|
||||
缺工具 → `skills/scripts/bootstrap-reverse.ps1`(清单能力,禁止猜路径)。
|
||||
缺工具 → 使用同平台 bootstrap:Windows `skills/scripts/bootstrap-reverse.ps1`;Linux / macOS `skills/scripts/bootstrap-reverse.sh`;Kali `kali/scripts/bootstrap-reverse.sh`(清单能力,禁止猜路径)。
|
||||
|
||||
## 测试(改动后必跑)
|
||||
|
||||
```powershell
|
||||
# 路由回归(routing-benchmark.json,修改 routing.json 后必跑)
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/test-routing.ps1
|
||||
```text
|
||||
Windows / PowerShell(路由回归读取 routing-benchmark.json):
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/test-routing.ps1
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/verify-routing-coherence.ps1
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/smoke.ps1
|
||||
|
||||
# 结构一致性 + 供应链 pin gate
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/verify-routing-coherence.ps1
|
||||
|
||||
# 冒烟(verify + 脚本解析 + 快速路由)
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File skills/scripts/smoke.ps1
|
||||
Linux / macOS routing parity:
|
||||
bash skills/scripts/test-routing.sh
|
||||
bash skills/scripts/test-bootstrap-manifest.sh
|
||||
```
|
||||
|
||||
## 客户端边界
|
||||
|
||||
+55
-30
@@ -24,7 +24,7 @@ AI Community: https://linux.do
|
||||
### Automatic Configuration Process
|
||||
|
||||
```text
|
||||
0. ⚠️ Run refresh-tool-index first to generate skills/tool-index.md (see warning above)
|
||||
0. ⚠️ Run the platform-native refresh-tool-index first to generate skills/tool-index.md (see warning above)
|
||||
1. Detect the actual installation path of this package (derived from the location of this file, i.e., the directory containing README.md)
|
||||
2. Detect the local operating system and distribution:
|
||||
- Windows → continue with this README and the PowerShell script path
|
||||
@@ -33,13 +33,15 @@ AI Community: https://linux.do
|
||||
- macOS → read docs/platforms/macos.md
|
||||
- Other / unknown → read docs/PLATFORMS.md and choose the closest deployment path
|
||||
3. Follow the platform-specific deployment document to check toolchains, script entry points, MCP configuration, and path conventions
|
||||
4. If the current system supports Bash, prefer the parity bootstrap entry: bash skills/scripts/bootstrap-reverse.sh <capability>; for index refresh only, run: bash skills/scripts/refresh-tool-index.sh
|
||||
4. Use the native bootstrap entry for the current platform; Linux/macOS do not require PowerShell for the core routing/case flow
|
||||
5. Read RULES.md → execute all instructions inside it (CRITICAL block, global injection, precedent-auth, routing)
|
||||
6. Route via skills/MASTER-ROUTING.md or:
|
||||
- Windows: `powershell -File skills/scripts/master-route.ps1 -Hint "<task>"`
|
||||
- Linux/macOS/Kali: open MASTER-ROUTING.md (or run the same script under pwsh if available)
|
||||
7. **Ops gate (MUST):** `powershell -File skills/scripts/case-init.ps1 -Hint "<task>"` (or hand-write `work/<case>/scope.md` per `skills/ops/scope-contract.md`).
|
||||
Set `auth.status=granted` + `network_profile` before any target ACT. Evidence chain: `skills/ops/evidence-finding-path.md`. Roles: `skills/ops/role-map.md`. Identity: `skills/ops/IDENTITY.md`.
|
||||
- Linux/macOS/Kali: `bash skills/scripts/master-route.sh --hint "<task>"`
|
||||
7. **Ops gate (MUST):** initialize the case using the native platform entry:
|
||||
- Windows: `powershell -File skills/scripts/case-init.ps1 -Hint "<task>"`
|
||||
- Linux/macOS/Kali: `bash skills/scripts/case-init.sh --hint "<task>"`
|
||||
Both default case artifacts to the caller analysis project's `work/<case>/`. Set `auth.status=granted` + a valid network profile before target ACT. An authorized local sample may remain `offline` when an explicit sample is supplied through the `offline-sample` preset. `-Force`/`--force` never bypasses the scope hard gate. Evidence chain: `skills/ops/evidence-finding-path.md`. Roles: `skills/ops/role-map.md`. Identity: `skills/ops/IDENTITY.md`.
|
||||
8. Open PRIMARY SKILL.md → execute ACTION REQUIRED. Append timeline/workitems under the case dir.
|
||||
9. Before report handoff, run `python3 skills/case-review/scripts/review_case.py work/<case> --verify-hashes --strict` and resolve every error.
|
||||
10. Continue the behavior chain → report via docs-generator + field-journal.
|
||||
@@ -49,10 +51,10 @@ AI Community: https://linux.do
|
||||
|
||||
| Detection result | Signal | Required deployment document | Detection / deployment entry |
|
||||
|---|---|---|---|
|
||||
| Windows | PowerShell, `$env:OS`, Windows paths | `README_AI.md` | `skills/scripts/*.ps1` |
|
||||
| Kali Linux | `/etc/os-release` contains `kali` | `kali/README-kali.md` | `kali/scripts/bootstrap-reverse.sh` / `kali/scripts/refresh-tool-index.sh` |
|
||||
| Ubuntu / Debian / Mint / Pop!_OS | `/etc/os-release` contains the distro ID | `docs/platforms/linux.md` | `skills/scripts/bootstrap-reverse.sh` / `skills/scripts/refresh-tool-index.sh` |
|
||||
| macOS | `uname -s` = `Darwin` | `docs/platforms/macos.md` | `skills/scripts/bootstrap-reverse.sh` / `skills/scripts/refresh-tool-index.sh` |
|
||||
| Windows | PowerShell, `$env:OS`, Windows paths | `README_AI.md` | `skills/scripts/master-route.ps1` / `case-init.ps1` / `bootstrap-reverse.ps1` / `refresh-tool-index.ps1` |
|
||||
| Kali Linux | `/etc/os-release` contains `kali` | `kali/README-kali.md` | `skills/scripts/master-route.sh` / `case-init.sh`; Kali bootstrap/refresh under `kali/scripts/` |
|
||||
| Ubuntu / Debian / Mint / Pop!_OS | `/etc/os-release` contains the distro ID | `docs/platforms/linux.md` | `skills/scripts/master-route.sh` / `case-init.sh` / `bootstrap-reverse.sh` / `refresh-tool-index.sh` |
|
||||
| macOS | `uname -s` = `Darwin` | `docs/platforms/macos.md` | `skills/scripts/master-route.sh` / `case-init.sh` / `bootstrap-reverse.sh` / `refresh-tool-index.sh` |
|
||||
| Other / unknown | Cannot identify confidently | `docs/PLATFORMS.md` | Choose the closest platform, then continue |
|
||||
|
||||
> RULES.md contains the full behavior chain (steps 0–14). After reading this file, first complete OS detection and platform-document routing, then read RULES.md and start executing. Do not stop at "configuration completed."
|
||||
@@ -74,7 +76,7 @@ AI Community: https://linux.do
|
||||
**Tool index**: <tool-index.md / tool-index.json path>
|
||||
**Rules written to**: <write location>
|
||||
**Note**: Future reverse-engineering / penetration-testing / security tasks will be routed automatically. Missing tools will be installed automatically when needed.
|
||||
**Ops**: Before target ACT, ensure case scope (`case-init` / `ops/scope-contract`) has auth granted + network_profile.
|
||||
**Ops**: Before target ACT, ensure case scope (`case-init` / `ops/scope-contract`) has auth granted + a valid network/offline-sample profile.
|
||||
```
|
||||
|
||||
---
|
||||
@@ -92,18 +94,21 @@ It solves two problems:
|
||||
|
||||
| Platform | Status | Entry |
|
||||
|---|---|---|
|
||||
| Windows | Full primary path | `README_AI.md`, PowerShell scripts |
|
||||
| Kali Linux | Specialized support | `kali/README-kali.md`, `kali/scripts/bootstrap-reverse.sh`, `kali/scripts/refresh-tool-index.sh` |
|
||||
| Ubuntu / Debian Linux | Generic support | `docs/platforms/linux.md`, `skills/scripts/bootstrap-reverse.sh`, `skills/scripts/refresh-tool-index.sh` |
|
||||
| macOS | Generic support | `docs/platforms/macos.md`, `skills/scripts/bootstrap-reverse.sh`, `skills/scripts/refresh-tool-index.sh` |
|
||||
| Windows | Full primary path | `README_AI.md`, `skills/scripts/master-route.ps1`, `case-init.ps1`, PowerShell bootstrap/refresh |
|
||||
| Kali Linux | Specialized support | `skills/scripts/master-route.sh`, `case-init.sh`, `kali/README-kali.md`, Kali bootstrap/refresh |
|
||||
| Ubuntu / Debian Linux | Generic support | `docs/platforms/linux.md`, `skills/scripts/master-route.sh`, `case-init.sh`, Bash bootstrap/refresh |
|
||||
| macOS | Generic support | `docs/platforms/macos.md`, `skills/scripts/master-route.sh`, `case-init.sh`, Bash bootstrap/refresh |
|
||||
|
||||
Generic Linux/macOS users can list bootstrap capabilities with:
|
||||
Generic Linux/macOS users can run the core routing/case path without installing PowerShell:
|
||||
|
||||
```bash
|
||||
bash skills/scripts/master-route.sh --hint "offline apk"
|
||||
bash skills/scripts/case-init.sh --hint "offline apk" --case-name my-sample --preset offline-sample --sample ./app.apk
|
||||
bash skills/scripts/case-guard.sh --case-root work/my-sample
|
||||
bash skills/scripts/bootstrap-reverse.sh --list
|
||||
```
|
||||
|
||||
Kali users should use the dedicated Kali entrypoint:
|
||||
Kali users should use the dedicated Kali bootstrap entrypoint:
|
||||
|
||||
```bash
|
||||
bash kali/scripts/bootstrap-reverse.sh
|
||||
@@ -272,10 +277,12 @@ Full dependency table with paths in the original [README.md](README.md).
|
||||
|
||||
### Refresh the Tool Index
|
||||
|
||||
Do not trust someone else's scan result for long. After migrating to a new machine, refresh it first:
|
||||
Do not trust someone else's scan result for long. After migrating to a new machine, refresh it first with the native platform entry:
|
||||
|
||||
```powershell
|
||||
powershell -File "<SKILL_ROOT>\skills\scripts\refresh-tool-index.ps1"
|
||||
```text
|
||||
Windows: powershell -File "<SKILL_ROOT>\skills\scripts\refresh-tool-index.ps1"
|
||||
Linux / macOS: bash <SKILL_ROOT>/skills/scripts/refresh-tool-index.sh
|
||||
Kali: bash <SKILL_ROOT>/kali/scripts/refresh-tool-index.sh
|
||||
```
|
||||
|
||||
After success, check:
|
||||
@@ -403,19 +410,23 @@ The key is to inject: package path, key entry files, MCP addresses, and "route f
|
||||
If you have configured `.claude\settings.local.json` or `.claude\scripts\route-reverse.ps1`, update all old paths after migration.
|
||||
|
||||
### Tool Index
|
||||
After migration, run again:
|
||||
```powershell
|
||||
powershell -File "<your skill root>\skills\scripts\refresh-tool-index.ps1"
|
||||
After migration, run the native refresh command again:
|
||||
|
||||
```text
|
||||
Windows: powershell -File "<your skill root>\skills\scripts\refresh-tool-index.ps1"
|
||||
Linux / macOS: bash <your skill root>/skills/scripts/refresh-tool-index.sh
|
||||
Kali: bash <your skill root>/kali/scripts/refresh-tool-index.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Recommended Verification Checklist
|
||||
|
||||
```powershell
|
||||
Core runtime checks:
|
||||
|
||||
```text
|
||||
java -version
|
||||
python --version
|
||||
pip --version
|
||||
python --version # or python3 --version
|
||||
node -v
|
||||
npx -v
|
||||
jadx --version
|
||||
@@ -424,14 +435,28 @@ adb version
|
||||
frida-ps -U
|
||||
```
|
||||
|
||||
IDA chain:
|
||||
Core routing/case contract:
|
||||
|
||||
```text
|
||||
Windows:
|
||||
powershell -File skills/scripts/master-route.ps1 -Hint "offline apk"
|
||||
powershell -File skills/scripts/case-init.ps1 -Hint "offline apk" -CaseName verify-sample -Preset offline-sample -Sample ".\sample.apk"
|
||||
|
||||
Linux / macOS / Kali:
|
||||
bash skills/scripts/master-route.sh --hint "offline apk"
|
||||
bash skills/scripts/case-init.sh --hint "offline apk" --case-name verify-sample --preset offline-sample --sample ./sample.apk
|
||||
```
|
||||
|
||||
IDA chain on Windows:
|
||||
```powershell
|
||||
powershell -File "<your skill root>\ida-reverse\scripts\start.ps1"
|
||||
```
|
||||
|
||||
Tool index:
|
||||
```powershell
|
||||
powershell -File "<your skill root>\skills\scripts\refresh-tool-index.ps1"
|
||||
```text
|
||||
Windows: powershell -File "<your skill root>\skills\scripts\refresh-tool-index.ps1"
|
||||
Linux / macOS: bash <your skill root>/skills/scripts/refresh-tool-index.sh
|
||||
Kali: bash <your skill root>/kali/scripts/refresh-tool-index.sh
|
||||
```
|
||||
|
||||
---
|
||||
@@ -512,7 +537,7 @@ When the AI tries to auto-complete installation and still fails, it **must not s
|
||||
### AI Failure-Handling Flow
|
||||
|
||||
```text
|
||||
1. Call bootstrap-reverse.ps1 to attempt automatic installation
|
||||
1. Call the platform-native bootstrap (`bootstrap-reverse.ps1` on Windows, `bootstrap-reverse.sh` on Linux/macOS, Kali bootstrap under `kali/scripts/`)
|
||||
2. Verify whether the tool is usable after installation
|
||||
3. If it is still unavailable → do not retry → immediately output structured guidance
|
||||
```
|
||||
@@ -577,4 +602,4 @@ This project (`reverse-skill`) is primarily licensed under the **MIT License**.
|
||||
This package is intended only for legally authorized security research, learning, and CTF competitions.
|
||||
- Users must ensure all operations are within legal boundaries
|
||||
- Unauthorized penetration testing against other people's systems is illegal
|
||||
- The package author is not responsible for misuse
|
||||
- The package author is not responsible for misuse
|
||||
@@ -12,11 +12,13 @@
|
||||
|
||||
After reading this file, you MUST NOW (immediately) execute:
|
||||
|
||||
```
|
||||
```text
|
||||
1. NOW: This file's directory is the package root
|
||||
2. NOW: Run skills/scripts/master-route.ps1 -Hint "<task>" → PRIMARY (SSoT: skills/config/routing.json)
|
||||
3. NEXT: case-init.ps1 until scope.md has auth.status=granted and a legal network_profile. Mentioning a target is NOT granted.
|
||||
4. ACT: Open PRIMARY SKILL.md and execute ACTION REQUIRED. Tools only from tool-index.md; missing → bootstrap-reverse.ps1
|
||||
2. NOW: Run the platform-native router → PRIMARY (SSoT: skills/config/routing.json)
|
||||
- Windows: powershell -File skills/scripts/master-route.ps1 -Hint "<task>"
|
||||
- Linux/macOS/Kali: bash skills/scripts/master-route.sh --hint "<task>"
|
||||
3. NEXT: Run the platform-native case-init until scope.md has auth.status=granted plus a legal network_profile, or an explicitly authorized offline-sample scope is ready. Mentioning a target is NOT granted. -Force/--force never bypasses the gate.
|
||||
4. ACT: Open PRIMARY SKILL.md and execute ACTION REQUIRED. Tools only from tool-index.md; missing → platform-native bootstrap.
|
||||
|
||||
Optional later (do NOT preload):
|
||||
- Ambiguous PRIMARY → skills/routing.md (advisory matrix only)
|
||||
@@ -27,7 +29,7 @@ Optional later (do NOT preload):
|
||||
IMPORTANT — Shared installation:
|
||||
- tool-index.md is the SINGLE SOURCE OF TRUTH for tool availability
|
||||
- If another CLI already installed tools (tool-index shows "yes"), DO NOT reinstall
|
||||
- Only run refresh-tool-index.ps1 if you suspect tool-index is stale (e.g., user says "I just installed X")
|
||||
- Only run the platform-native refresh-tool-index if you suspect tool-index is stale (e.g., user says "I just installed X")
|
||||
- Only run bootstrap for tools that are BOTH needed AND marked "no"
|
||||
|
||||
Conditional reads (load only when needed, do NOT preload):
|
||||
@@ -147,19 +149,19 @@ Hot path only:
|
||||
|
||||
## Canonical Behavior Chain (All other files reference THIS version)
|
||||
|
||||
```
|
||||
```text
|
||||
1. Identify task as security/reverse type → trigger this routing rule
|
||||
2. Detect package root path (derive from this file's location)
|
||||
3. master-route.ps1 -Hint → PRIMARY from skills/config/routing.json
|
||||
4. case-init.ps1 / scope.md (ops/scope-contract) — auth.status=granted + network_profile before any target ACT. precedent-auth.md does not grant.
|
||||
3. Platform-native master-route (`.ps1` Windows / `.sh` Linux, macOS, Kali) → PRIMARY from skills/config/routing.json; use routing.md only when ambiguous
|
||||
4. Platform-native case-init / scope.md (ops/scope-contract) — auth.status=granted + valid network profile, or explicit authorized offline sample, before any target ACT; Force never bypasses the hard gate
|
||||
5. Open PRIMARY SKILL.md ACTION REQUIRED
|
||||
6. Route not matched → propose new skill (edit routing.json + benchmark; do not hand-edit routing.md as SSoT)
|
||||
7. tool-index.md → real paths; missing (first run) → template + refresh-tool-index
|
||||
8. Missing tools → platform bootstrap (Windows ps1 / Linux sh / Kali sh)
|
||||
9. Execute PRIMARY workflow (timeline/workitems; Evidence→Finding→Path)
|
||||
7. Read tool-index.md → confirm local tool status. If missing (first run) → template + platform-native refresh-tool-index
|
||||
8. Missing tools → platform bootstrap + refresh (Windows ps1 / Linux sh / Kali sh)
|
||||
9. Enter skill workflow → execute (timeline/workitems; Evidence→Finding→Path per ops/)
|
||||
10. Continuously report progress (do NOT go silent)
|
||||
13. Task complete → Completion Checklist (report must include Evidence chain)
|
||||
14. Output final results
|
||||
11. Task complete → Completion Checklist (report must include Evidence chain)
|
||||
12. Output final results
|
||||
```
|
||||
|
||||
---
|
||||
@@ -225,7 +227,6 @@ After task completion (vulnerability verified / reverse complete / flag captured
|
||||
| "IAT repair keeps failing; I'll grind more static unpackers" | **IAT repair iron rule:** try auto/semi-auto repair first; on tool error or unreable binary after repair, STOP static IAT, record E-iat-repair-fail, switch to dynamic API breakpoints. FORBIDDEN infinite static IAT thrash. |
|
||||
| "No import table (.NET) so the hard gate does not apply" | **Equivalent anchor still MUST:** .NET → dnSpy/IL/metadata summary into E-imports slot; DLL/SYS → E-exports alongside imports. FORBIDDEN to skip the gate. |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Self-Audit Before Claiming "Complete"
|
||||
@@ -271,7 +272,7 @@ Before saying "task complete" or "done", MUST self-check:
|
||||
## Context Window Layout Rules (Attention Optimization)
|
||||
|
||||
LLM attention distribution (high→low):
|
||||
```
|
||||
```text
|
||||
[First 10%] ████████████ ← Highest attention — put "immediate action" instructions here
|
||||
[Middle 80%] ████░░░░░░░░ ← Attention decays — put reference materials here
|
||||
[Last 10%] ████████████ ← Attention recovers — put "MUST NOT skip" and Checklist here
|
||||
@@ -291,7 +292,7 @@ When tool parameters MUST be passed exactly as given, use opaque identifiers (co
|
||||
- **MUST NOT**: Let Agent freely rewrite semantic parameters (e.g., changing strict/deny to lenient synonyms)
|
||||
|
||||
Example:
|
||||
```
|
||||
```text
|
||||
alpha -> --scope authorized-only
|
||||
beta -> --approval required
|
||||
gamma -> --destructive false
|
||||
@@ -383,15 +384,17 @@ bash <SKILL_ROOT>/kali/scripts/refresh-tool-index.sh
|
||||
|
||||
### Post-Trigger Execution (Compact — do NOT re-run first-time setup!)
|
||||
|
||||
```
|
||||
1. NOW: Run <SKILL_ROOT>/skills/scripts/master-route.ps1 -Hint "<task>" → PRIMARY
|
||||
2. NEXT: case-init.ps1 / scope.md — auth.status=granted + network_profile; MUST NOT ACT against targets until ready
|
||||
3. ACT: Open PRIMARY SKILL.md
|
||||
```text
|
||||
1. NOW: Run the platform-native master-route (.ps1 on Windows / .sh on Linux, macOS, Kali) → PRIMARY from routing.json
|
||||
2. NEXT: If ambiguous, open <SKILL_ROOT>/skills/routing.md
|
||||
3. NEXT: Use platform-native case-init / scope.md — set auth.status=granted + valid network profile, or an explicit authorized offline-sample scope; Force never bypasses the hard gate
|
||||
4. ACT: Open PRIMARY SKILL.md; timeline/workitems + Evidence→Finding→Path (ops/*)
|
||||
```
|
||||
|
||||
### Core Rules (Compact)
|
||||
|
||||
- **MUST**: case scope (case-init / ops/scope-contract) before ACT; auth.status=granted + network_profile required
|
||||
- **MUST**: case scope (platform-native case-init / ops/scope-contract) before ACT; auth.status=granted + valid network/offline-sample scope required
|
||||
- **MUST**: `-Force` / `--force` never bypasses authorization, scope, network, or readiness gates
|
||||
- **MUST**: Missing tools → bootstrap, NEVER guess paths
|
||||
- **MUST NOT**: Treat precedent-auth.md or "user named a target" as granted
|
||||
- **MUST NOT**: Reply "understood, tell me your task" after reading rules
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# reverse-skill PRIMARY 快路径
|
||||
|
||||
> 与 `scripts/master-route.ps1` 保持一致。
|
||||
> `scripts/master-route.ps1` 与 `scripts/master-route.sh` 必须保持相同路由契约;平台只改变执行入口,不改变 routing semantics。
|
||||
|
||||
## 执行契约
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
8. 未命中 → 读 routing.md 全表或提议新 skill
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
```powershell
|
||||
powershell -File skills\scripts\master-route.ps1 -Hint "<用户任务>"
|
||||
# 默认写出当前项目的 work/master-route-<ts>/route-scope.md;从其他目录调用时显式指定项目根
|
||||
@@ -24,15 +26,36 @@ powershell -File skills\scripts\case-init.ps1 -Hint "<用户任务>" -CaseName "
|
||||
powershell -File skills\scripts\case-init.ps1 -Hint "<用户任务>" -CaseName "my-case" -ProjectRoot "C:\path\to\analysis-project"
|
||||
# 一次成型可 ACT(授权 + 目标 + 网络档):
|
||||
powershell -File skills\scripts\case-init.ps1 -Hint "<任务>" -CaseName "my-case" -AuthGranted -TargetUrl "https://target/" -NetworkProfile authorized_target_only
|
||||
# 本地离线样本:
|
||||
powershell -File skills\scripts\case-init.ps1 -Hint "offline apk" -CaseName "my-sample" -Preset offline-sample -Sample ".\app.apk"
|
||||
# 冒烟:verify + 脚本解析 + 路由矩阵(含中文 Hint)
|
||||
powershell -File skills\scripts\smoke.ps1
|
||||
# ACT 前轻量 scope 门禁(未就绪 exit 2;-Force 仅警告)
|
||||
# ACT 前轻量 scope 门禁(未就绪 exit 2;-Force 为兼容参数,不能绕过硬门)
|
||||
powershell -File skills\scripts\case-guard.ps1 -CaseRoot work\my-case
|
||||
# Evidence 追加
|
||||
powershell -File skills\scripts\append-evidence.ps1 -CaseRoot work\my-case -Id E-001 -Title "..." -ReproCommand "..."
|
||||
python3 skills/case-review/scripts/review_case.py work/<case> --verify-hashes --strict
|
||||
```
|
||||
|
||||
### Linux / macOS / Kali
|
||||
|
||||
不要求为了核心 route/case 流程安装 PowerShell:
|
||||
|
||||
```bash
|
||||
bash skills/scripts/master-route.sh --hint "<用户任务>"
|
||||
bash skills/scripts/master-route.sh --hint "<用户任务>" --project-root "/path/to/analysis-project"
|
||||
bash skills/scripts/case-init.sh --hint "<用户任务>" --case-name "my-case"
|
||||
bash skills/scripts/case-init.sh --hint "<用户任务>" --case-name "my-case" --project-root "/path/to/analysis-project"
|
||||
# 本地离线样本:
|
||||
bash skills/scripts/case-init.sh --hint "offline apk" --case-name "my-sample" --preset offline-sample --sample ./app.apk
|
||||
# ACT 前轻量 scope 门禁(--force 为兼容参数,不能绕过硬门):
|
||||
bash skills/scripts/case-guard.sh --case-root work/my-sample
|
||||
# 路由 parity:
|
||||
bash skills/scripts/test-routing.sh
|
||||
bash skills/scripts/test-bootstrap-manifest.sh
|
||||
python3 skills/case-review/scripts/review_case.py work/<case> --verify-hashes --strict
|
||||
```
|
||||
|
||||
## 作战契约(ops)
|
||||
|
||||
| 文档 | 用途 |
|
||||
|
||||
+18
-7
@@ -10,10 +10,10 @@ description: Routes reverse engineering, exploitation, penetration testing, malw
|
||||
|
||||
读完本文件后,不允许只回复“已读/已理解”。必须按顺序执行:
|
||||
|
||||
1. `NOW`:跑 `scripts/master-route.ps1 -Hint "..."`(SSoT:`config/routing.json`)定 PRIMARY。
|
||||
2. `NOW`:`scripts/case-init.ps1` 落地 `work/<case>/scope.md`;**auth 未 granted 禁止对目标 ACT**。点名目标 ≠ granted。
|
||||
1. `NOW`:跑平台原生 router(Windows `scripts/master-route.ps1`;Linux/macOS/Kali `scripts/master-route.sh`),从 `config/routing.json` 定 PRIMARY;疑难再读 `routing.md` 三轴附录。
|
||||
2. `NOW`:平台原生 `case-init` 落地当前分析项目的 `work/<case>/scope.md`;**auth 未 granted 禁止对目标 ACT**。本地离线样本使用 `offline-sample` preset + explicit sample;Force 不得绕过硬门。
|
||||
3. `ACT`:立即打开 PRIMARY `SKILL.md` 执行 ACTION REQUIRED。
|
||||
4. `NEXT`:工具路径只认 `tool-index.md`;缺工具 → `bootstrap-reverse.ps1`(仅 manifest)。
|
||||
4. `NEXT`:工具路径只认 `tool-index.md`;缺工具 → 平台原生 bootstrap(仅 manifest)。
|
||||
5. 结论用 Evidence→Finding→Path。报告/journal 是 SHOULD,除非用户要交付物。
|
||||
|
||||
**身份**:见 `ops/IDENTITY.md`(轻量路由包 + 工具自举 + journal;**不是** Z3r0 式平台)。
|
||||
@@ -82,10 +82,10 @@ description: Routes reverse engineering, exploitation, penetration testing, malw
|
||||
|
||||
遇到逆向、CTF、抓包、前端签名、APK 改包、二进制分析类任务时,先按这个顺序进入:
|
||||
|
||||
1. `scripts/master-route.ps1` → PRIMARY(`config/routing.json`)
|
||||
2. `case-init.ps1` → `scope.md`
|
||||
1. 平台原生 router(Windows `scripts/master-route.ps1`;Linux/macOS/Kali `scripts/master-route.sh`)→ PRIMARY(`config/routing.json`)
|
||||
2. 平台原生 `case-init` → `scope.md`
|
||||
3. 打开 PRIMARY `SKILL.md`
|
||||
4. 需要本机路径时再读 `tool-index.md`
|
||||
4. 疑难时读 `routing.md`,需要本机路径时读 `tool-index.md`
|
||||
|
||||
## 工作思路
|
||||
|
||||
@@ -136,12 +136,23 @@ description: Routes reverse engineering, exploitation, penetration testing, malw
|
||||
|
||||
## 按需自举
|
||||
|
||||
当 workflow 发现缺少工具时,不要直接报错。统一调用:
|
||||
当 workflow 发现缺少工具时,不要直接报错。统一调用平台原生 bootstrap:
|
||||
|
||||
Windows:
|
||||
```powershell
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File "<skill-root>\scripts\bootstrap-reverse.ps1" -Capability @('工具名') -StartServices
|
||||
```
|
||||
|
||||
Linux / macOS:
|
||||
```bash
|
||||
bash <skill-root>/scripts/bootstrap-reverse.sh 工具名 --start-services
|
||||
```
|
||||
|
||||
Kali:
|
||||
```bash
|
||||
bash <package-root>/kali/scripts/bootstrap-reverse.sh 工具名 --start-services
|
||||
```
|
||||
|
||||
支持的能力(以 `scripts/bootstrap-manifest.json` 为准):jadx、apktool、jeb-pro、frida、frida-ps、idalib-mcp、reqable-mcp、jshookmcp、anything-analyzer、idapro、r2、rabin2、adb、agent-browser、ghidra-mcp、seclists、proxycat、burpsuite-mcp、nmap、pentestswarm、binwalk、yara、pwntools、bkcrack
|
||||
|
||||
> JEB Pro 已登记为**手动许可安装**能力:bootstrap 只输出指引,绝不下载或规避商业许可。Reqable MCP 仅登记固定版本的官方运行时,仍需要用户自行安装 Reqable 桌面客户端。
|
||||
|
||||
@@ -1,17 +1,38 @@
|
||||
# 通用 Scope 契约(任务启动硬门槛)
|
||||
|
||||
> **MUST**:任何安全/逆向/渗透任务在 **ACT 之前** 在用户项目或 `work/<case>/` 落地 `scope.md`。
|
||||
> 无 scope → 只允许读文档/路由,**禁止** 对目标主动扫描、Hook、利用。
|
||||
> **MUST**:任何安全/逆向/渗透任务在 **ACT 之前** 在当前用户分析项目的 `work/<case>/` 落地 `scope.md`。
|
||||
> 无 scope → 只允许读文档/路由,**禁止** 对目标主动扫描、Hook、利用。
|
||||
> 模板可复制;字段名保持英文键,便于脚本校验。
|
||||
|
||||
## 如何初始化
|
||||
|
||||
Windows:
|
||||
|
||||
```powershell
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File skills\scripts\case-init.ps1 -Hint "<任务一句话>" -CaseName "my-case"
|
||||
# 默认产出:当前分析项目的 work/<case>/scope.md 等
|
||||
# 从其他目录调用 skill 时显式指定:-ProjectRoot "C:\path\to\analysis-project"
|
||||
|
||||
# 合法本地离线样本:auth granted + offline + explicit sample → ready_for_act=true
|
||||
powershell -NoProfile -ExecutionPolicy Bypass -File skills\scripts\case-init.ps1 `
|
||||
-Hint "offline apk" -CaseName "my-sample" -Preset offline-sample -Sample ".\app.apk"
|
||||
```
|
||||
|
||||
Linux / macOS / Kali:
|
||||
|
||||
```bash
|
||||
bash skills/scripts/case-init.sh --hint "<任务一句话>" --case-name "my-case"
|
||||
# 默认产出:caller 当前分析项目的 work/<case>/scope.md 等
|
||||
# 从其他目录调用时显式指定:--project-root "/path/to/analysis-project"
|
||||
|
||||
# 合法本地离线样本
|
||||
bash skills/scripts/case-init.sh \
|
||||
--hint "offline apk" --case-name "my-sample" \
|
||||
--preset offline-sample --sample ./app.apk
|
||||
```
|
||||
|
||||
`-PackageRoot` / `--package-root` 保留为兼容参数;新流程应以 `ProjectRoot` / `--project-root` 表示 case artifact 的归属项目。
|
||||
|
||||
## scope.md 完整模板
|
||||
|
||||
```markdown
|
||||
@@ -21,6 +42,7 @@ powershell -NoProfile -ExecutionPolicy Bypass -File skills\scripts\case-init.ps1
|
||||
- case_id: {YYYYMMDD-short}
|
||||
- created: {ISO-8601}
|
||||
- operator: {name or local}
|
||||
- project_root: {caller analysis project}
|
||||
- primary_skill: {from master-route}
|
||||
- lead_role: lead # see ops/role-map.md
|
||||
- specialist_roles: [] # e.g. cie, cpe, cre
|
||||
@@ -73,11 +95,13 @@ powershell -NoProfile -ExecutionPolicy Bypass -File skills\scripts\case-init.ps1
|
||||
```text
|
||||
RULES / MASTER-ROUTING / SKILL:
|
||||
1) master-route → PRIMARY
|
||||
2) case-init 或手写 scope.md
|
||||
2) 平台原生 case-init 或手写 scope.md
|
||||
3) auth 未 granted → STOP,只允许补授权材料
|
||||
4) ready_for_act = true → 打开 PRIMARY SKILL.md → ACT
|
||||
```
|
||||
|
||||
`case-guard -Force` / `case-guard --force` 是兼容参数,**不得**绕过 `auth.status`、合法 scope、network profile 或 `ready_for_act` 硬门。
|
||||
|
||||
## network_profile 速查
|
||||
|
||||
| mode | 允许 | 禁止 |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Lightweight scope gate before ACT. Exit 0 = ok, 2 = not ready, 1 = usage/error.
|
||||
# Usage:
|
||||
# powershell -File skills/scripts/case-guard.ps1 -CaseRoot work\my-case
|
||||
# powershell -File skills/scripts/case-guard.ps1 -CaseRoot work\my-case -Force # warn but exit 0
|
||||
# powershell -File skills/scripts/case-guard.ps1 -CaseRoot work\my-case -Force # compatibility flag; never bypasses scope hard gates
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string] $CaseRoot,
|
||||
@@ -94,9 +94,8 @@ Write-Host ("CASE-GUARD NOT READY: {0}" -f $CaseRoot) -ForegroundColor Yellow
|
||||
foreach ($i in $issues) { Write-Host (" - {0}" -f $i) -ForegroundColor Yellow }
|
||||
|
||||
if ($Force) {
|
||||
Write-Host 'CASE-GUARD: -Force set; continuing with warnings only.' -ForegroundColor Yellow
|
||||
exit 0
|
||||
Write-Host 'CASE-GUARD: -Force does not bypass scope hard gates.' -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
Write-Host 'Fix scope (or re-run case-init -AuthGranted -TargetUrl ...) or pass -Force.' -ForegroundColor Yellow
|
||||
Write-Host 'Fix scope (or re-run case-init -AuthGranted -TargetUrl ...).' -ForegroundColor Yellow
|
||||
exit 2
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Lightweight scope gate before ACT. Exit 0=ok, 2=not ready, 1=usage/error.
|
||||
# Usage:
|
||||
# bash skills/scripts/case-guard.sh --case-root work/my-case
|
||||
# bash skills/scripts/case-guard.sh --case-root work/my-case --force
|
||||
# bash skills/scripts/case-guard.sh --case-root work/my-case --force # compatibility flag; never bypasses scope hard gates
|
||||
set -euo pipefail
|
||||
|
||||
CASE_ROOT=""
|
||||
@@ -120,9 +120,8 @@ echo "CASE-GUARD NOT READY: $CASE_ROOT"
|
||||
for i in "${ISSUES[@]}"; do echo " - $i"; done
|
||||
|
||||
if [[ $FORCE -eq 1 ]]; then
|
||||
echo "CASE-GUARD: --force set; continuing with warnings only."
|
||||
exit 0
|
||||
echo "CASE-GUARD: --force does not bypass scope hard gates."
|
||||
fi
|
||||
|
||||
echo "Fix scope (or re-run case-init with --auth-granted --target-url ...) or pass --force."
|
||||
echo "Fix scope (or re-run case-init with --auth-granted --target-url ...)."
|
||||
exit 2
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# Ready-to-act example:
|
||||
# powershell -File skills/scripts/case-init.ps1 -Hint "web pentest" -CaseName my-case `
|
||||
# -AuthGranted -TargetUrl "https://app.example/" -NetworkProfile authorized_target_only
|
||||
# Offline sample ready-to-act example:
|
||||
# powershell -File skills/scripts/case-init.ps1 -Hint "offline apk" -CaseName my-sample `
|
||||
# -Preset offline-sample -Sample ".\app.apk"
|
||||
param(
|
||||
[string] $Hint = '',
|
||||
[string] $CaseName = '',
|
||||
@@ -15,6 +18,8 @@ param(
|
||||
[string] $AuthBasis = 'own_system',
|
||||
[string] $EvidenceOfAuth = '',
|
||||
[string] $TargetUrl = '',
|
||||
[string] $Sample = '',
|
||||
[string] $Preset = '',
|
||||
[string[]] $InScopeAssets = @(),
|
||||
[string] $NetworkProfile = '',
|
||||
[switch] $ReadyForAct
|
||||
@@ -37,6 +42,43 @@ $requestedProjectRoot = if (-not [string]::IsNullOrWhiteSpace($ProjectRoot)) {
|
||||
}
|
||||
$projectRoot = Resolve-ReverseProjectRoot -RequestedRoot $requestedProjectRoot
|
||||
|
||||
if (-not [string]::IsNullOrWhiteSpace($Sample)) {
|
||||
try {
|
||||
$Sample = [System.IO.Path]::GetFullPath($Sample)
|
||||
} catch {
|
||||
throw "Invalid -Sample path '$Sample': $($_.Exception.Message)"
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $Sample -PathType Leaf)) {
|
||||
throw "Local -Sample file not found: $Sample"
|
||||
}
|
||||
}
|
||||
|
||||
# Cross-platform case presets. Keep semantics aligned with case-init.sh.
|
||||
$presetNormalized = $Preset.Trim().ToLowerInvariant()
|
||||
if ($presetNormalized -in @('offline-sample', 'own-sample', 'local-sample')) {
|
||||
$AuthGranted = $true
|
||||
$AuthStatus = 'granted'
|
||||
$AuthBasis = 'own_system'
|
||||
if ([string]::IsNullOrWhiteSpace($NetworkProfile)) { $NetworkProfile = 'offline' }
|
||||
if ([string]::IsNullOrWhiteSpace($EvidenceOfAuth)) {
|
||||
$EvidenceOfAuth = 'preset:offline-sample (owner-operated local file)'
|
||||
}
|
||||
} elseif ($presetNormalized -in @('ctf-public', 'ctf')) {
|
||||
$AuthGranted = $true
|
||||
$AuthStatus = 'granted'
|
||||
$AuthBasis = 'ctf_public'
|
||||
if ([string]::IsNullOrWhiteSpace($NetworkProfile)) { $NetworkProfile = 'authorized_target_only' }
|
||||
if ([string]::IsNullOrWhiteSpace($EvidenceOfAuth)) { $EvidenceOfAuth = 'preset:ctf-public' }
|
||||
} elseif ($presetNormalized -in @('own-system', 'lab-only')) {
|
||||
$AuthGranted = $true
|
||||
$AuthStatus = 'granted'
|
||||
$AuthBasis = 'own_system'
|
||||
if ([string]::IsNullOrWhiteSpace($NetworkProfile)) { $NetworkProfile = 'lab_only' }
|
||||
if ([string]::IsNullOrWhiteSpace($EvidenceOfAuth)) { $EvidenceOfAuth = 'preset:own-system/lab' }
|
||||
} elseif (-not [string]::IsNullOrWhiteSpace($Preset)) {
|
||||
Write-Host ("WARN: unknown -Preset '{0}' (allowed: offline-sample|ctf-public|own-system)" -f $Preset) -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
if (-not $CaseName) {
|
||||
$slug = if ($Hint) {
|
||||
($Hint.ToLowerInvariant() -replace '[^a-z0-9]+', '-').Trim('-')
|
||||
@@ -92,6 +134,9 @@ $evidenceAuth = if (-not [string]::IsNullOrWhiteSpace($EvidenceOfAuth)) {
|
||||
|
||||
$assets = New-Object System.Collections.Generic.List[string]
|
||||
if (-not [string]::IsNullOrWhiteSpace($TargetUrl)) { [void]$assets.Add($TargetUrl.Trim()) }
|
||||
if (-not [string]::IsNullOrWhiteSpace($Sample) -and -not $assets.Contains($Sample.Trim())) {
|
||||
[void]$assets.Add($Sample.Trim())
|
||||
}
|
||||
foreach ($a in @($InScopeAssets)) {
|
||||
if (-not [string]::IsNullOrWhiteSpace($a) -and -not $assets.Contains($a.Trim())) {
|
||||
[void]$assets.Add($a.Trim())
|
||||
@@ -105,8 +150,8 @@ if ($assets.Count -eq 0 -and $Hint -match 'https?://([^\s/]+)') {
|
||||
$networkMode = 'offline'
|
||||
if (-not [string]::IsNullOrWhiteSpace($NetworkProfile)) {
|
||||
$networkMode = $NetworkProfile.Trim()
|
||||
} elseif ($assets.Count -gt 0 -and $authStatusResolved -eq 'granted') {
|
||||
# training labs / intentional vulns often use lab_only; default authorized_target_only
|
||||
} elseif ($assets.Count -gt 0 -and $authStatusResolved -eq 'granted' -and [string]::IsNullOrWhiteSpace($Sample)) {
|
||||
# Authorized network targets default to target-only. Explicit local samples remain offline.
|
||||
$networkMode = 'authorized_target_only'
|
||||
}
|
||||
# normalize common aliases
|
||||
@@ -124,19 +169,21 @@ if ($networkMode -notin $allowedNetworkModes) {
|
||||
throw "Invalid -NetworkProfile '$NetworkProfile'. Allowed: offline, lab_only, authorized_target_only, unrestricted_lab (aliases: lab, authorized, auth, offline_only)."
|
||||
}
|
||||
|
||||
# ready_for_act requires auth granted + assets + non-offline network.
|
||||
# -ReadyForAct cannot skip auth (would bypass hard gate).
|
||||
# ready_for_act requires auth granted + assets. Network targets need a non-offline
|
||||
# profile; an explicit local sample is valid in offline mode. -ReadyForAct never
|
||||
# bypasses auth or scope.
|
||||
$ready = $false
|
||||
$netAllowsAct = ($networkMode -ne 'offline' -and -not [string]::IsNullOrWhiteSpace($networkMode))
|
||||
if ($authStatusResolved -eq 'granted' -and $assets.Count -gt 0 -and $netAllowsAct) {
|
||||
$offlineSampleReady = ($networkMode -eq 'offline' -and -not [string]::IsNullOrWhiteSpace($Sample) -and $assets.Count -gt 0)
|
||||
if ($authStatusResolved -eq 'granted' -and $assets.Count -gt 0 -and ($netAllowsAct -or $offlineSampleReady)) {
|
||||
$ready = $true
|
||||
} elseif ($ReadyForAct) {
|
||||
if ($authStatusResolved -ne 'granted') {
|
||||
Write-Host 'WARN: -ReadyForAct ignored because auth.status is not granted' -ForegroundColor Yellow
|
||||
} elseif ($assets.Count -eq 0) {
|
||||
Write-Host 'WARN: -ReadyForAct ignored because in_scope.assets is empty' -ForegroundColor Yellow
|
||||
} elseif (-not $netAllowsAct) {
|
||||
Write-Host 'WARN: -ReadyForAct ignored because network_profile is offline/empty' -ForegroundColor Yellow
|
||||
} elseif (-not $netAllowsAct -and -not $offlineSampleReady) {
|
||||
Write-Host 'WARN: -ReadyForAct ignored because offline mode requires an explicit -Sample' -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +244,7 @@ $scope = @"
|
||||
- lead_role: lead
|
||||
- specialist_roles: []
|
||||
- hint: $Hint
|
||||
- preset: $(if ([string]::IsNullOrWhiteSpace($Preset)) { 'none' } else { $Preset })
|
||||
|
||||
## auth
|
||||
- status: $authStatusResolved
|
||||
@@ -297,7 +345,9 @@ $readmeNext = if ($ready) {
|
||||
"@
|
||||
} else {
|
||||
@"
|
||||
1. Edit ``scope.md`` — set auth.status=granted and in_scope (or re-run with -AuthGranted -TargetUrl)
|
||||
1. Edit ``scope.md`` — set auth.status=granted and in_scope
|
||||
- network target: re-run with ``-AuthGranted -TargetUrl <url>``
|
||||
- local sample: re-run with ``-Preset offline-sample -Sample <path>``
|
||||
2. Set ready_for_act when checklist complete
|
||||
3. Open primary skill: skills/$primary
|
||||
4. Append ``timeline.md``; update ``workitems.md``
|
||||
|
||||
@@ -9,6 +9,8 @@ set -euo pipefail
|
||||
HINT=""
|
||||
CASE_NAME=""
|
||||
PACKAGE_ROOT=""
|
||||
PROJECT_ROOT=""
|
||||
PACKAGE_ROOT_BOUND=0
|
||||
AUTH_STATUS=""
|
||||
AUTH_GRANTED=0
|
||||
AUTH_BASIS="unknown"
|
||||
@@ -23,7 +25,8 @@ while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-Hint|--hint) HINT="${2:-}"; shift 2 ;;
|
||||
-CaseName|--case-name) CASE_NAME="${2:-}"; shift 2 ;;
|
||||
-PackageRoot|--package-root) PACKAGE_ROOT="${2:-}"; shift 2 ;;
|
||||
-PackageRoot|--package-root) PACKAGE_ROOT="${2:-}"; PACKAGE_ROOT_BOUND=1; shift 2 ;;
|
||||
-ProjectRoot|--project-root) PROJECT_ROOT="${2:-}"; shift 2 ;;
|
||||
-AuthStatus|--auth-status) AUTH_STATUS="${2:-}"; shift 2 ;;
|
||||
-AuthGranted|--auth-granted) AUTH_GRANTED=1; shift ;;
|
||||
-AuthBasis|--auth-basis) AUTH_BASIS="${2:-}"; shift 2 ;;
|
||||
@@ -46,6 +49,22 @@ SKILLS_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
if [[ -z "$PACKAGE_ROOT" ]]; then
|
||||
PACKAGE_ROOT="$(cd "$SKILLS_ROOT/.." && pwd)"
|
||||
fi
|
||||
if [[ -z "$PROJECT_ROOT" ]]; then
|
||||
if [[ $PACKAGE_ROOT_BOUND -eq 1 ]]; then
|
||||
PROJECT_ROOT="$PACKAGE_ROOT"
|
||||
else
|
||||
PROJECT_ROOT="$(pwd -P)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "$SAMPLE" ]]; then
|
||||
if [[ ! -f "$SAMPLE" ]]; then
|
||||
echo "Local --sample file not found: $SAMPLE" >&2
|
||||
exit 2
|
||||
fi
|
||||
sample_dir="$(cd "$(dirname "$SAMPLE")" && pwd -P)"
|
||||
SAMPLE="$sample_dir/$(basename "$SAMPLE")"
|
||||
fi
|
||||
|
||||
# Presets: reduce "AI refuses to work" friction for legitimate local/CTF work.
|
||||
case "$PRESET" in
|
||||
@@ -104,7 +123,7 @@ if [[ -n "$NETWORK_PROFILE" ]]; then
|
||||
esac
|
||||
fi
|
||||
|
||||
CASE_ROOT="$PACKAGE_ROOT/work/$CASE_NAME"
|
||||
CASE_ROOT="$PROJECT_ROOT/work/$CASE_NAME"
|
||||
mkdir -p "$CASE_ROOT/evidence" "$CASE_ROOT/notes" "$CASE_ROOT/report"
|
||||
|
||||
auth_status_resolved="pending"
|
||||
@@ -165,7 +184,7 @@ primary="reverse-engineering/SKILL.md"
|
||||
primary_id="R0"
|
||||
if [[ -f "$SCRIPT_DIR/master-route.sh" ]]; then
|
||||
set +e
|
||||
bash "$SCRIPT_DIR/master-route.sh" --hint "$HINT" --out-dir "$ROUTE_TMP" >/dev/null 2>&1
|
||||
bash "$SCRIPT_DIR/master-route.sh" --hint "$HINT" --project-root "$PROJECT_ROOT" --out-dir "$ROUTE_TMP" >/dev/null 2>&1
|
||||
set -e
|
||||
if [[ -f "$ROUTE_TMP/route-scope.md" ]]; then
|
||||
rt="$(cat "$ROUTE_TMP/route-scope.md")"
|
||||
@@ -215,6 +234,7 @@ cat > "$CASE_ROOT/scope.md" <<EOF
|
||||
- case_id: $CASE_NAME
|
||||
- created: $created
|
||||
- operator: local
|
||||
- project_root: $PROJECT_ROOT
|
||||
- primary_skill: $primary
|
||||
- primary_id: $primary_id
|
||||
- lead_role: lead
|
||||
|
||||
@@ -148,7 +148,7 @@ foreach ($zc in $zhCases) {
|
||||
else { Bad ("zh route miss {0}: {1}" -f $zc.Expect, ($raw.Substring(0, [Math]::Min(120, $raw.Length)))) }
|
||||
}
|
||||
|
||||
# 9) case-guard: ready case exits 0; bare pending exits 2
|
||||
# 9) case-guard: ready case exits 0; bare pending exits 2 even with -Force
|
||||
$cg = Join-Path $scriptDir 'case-guard.ps1'
|
||||
& $HostExe -NoProfile -ExecutionPolicy Bypass -File $cg -CaseRoot $caseRoot 2>&1 | Out-Null
|
||||
if ($LASTEXITCODE -eq 0) { Ok 'case-guard ready exit 0' } else { Bad "case-guard ready exit $LASTEXITCODE" }
|
||||
@@ -156,7 +156,7 @@ $bareRoot = Join-Path $PackageRoot ("work\{0}" -f $bareName)
|
||||
& $HostExe -NoProfile -ExecutionPolicy Bypass -File $cg -CaseRoot $bareRoot 2>&1 | Out-Null
|
||||
if ($LASTEXITCODE -eq 2) { Ok 'case-guard pending exit 2' } else { Bad "case-guard pending expected 2 got $LASTEXITCODE" }
|
||||
& $HostExe -NoProfile -ExecutionPolicy Bypass -File $cg -CaseRoot $bareRoot -Force 2>&1 | Out-Null
|
||||
if ($LASTEXITCODE -eq 0) { Ok 'case-guard -Force exit 0' } else { Bad "case-guard -Force exit $LASTEXITCODE" }
|
||||
if ($LASTEXITCODE -eq 2) { Ok 'case-guard -Force cannot bypass hard gate' } else { Bad "case-guard -Force expected 2 got $LASTEXITCODE" }
|
||||
|
||||
# 10) AuthGranted must not be clobbered by junk AuthStatus / multi-asset lab init
|
||||
# Note: -ProjectRoot is passed explicitly to prevent the -InScopeAssets array
|
||||
|
||||
Reference in New Issue
Block a user