fix(p0): align powershell offline sample case readiness
This commit is contained in:
@@ -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
|
||||
@@ -35,6 +40,32 @@ $requestedProjectRoot = if (-not [string]::IsNullOrWhiteSpace($ProjectRoot)) {
|
||||
}
|
||||
$projectRoot = Resolve-ReverseProjectRoot -RequestedRoot $requestedProjectRoot
|
||||
|
||||
# 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('-')
|
||||
@@ -90,6 +121,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())
|
||||
@@ -103,8 +137,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
|
||||
@@ -122,19 +156,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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,6 +229,7 @@ $scope = @"
|
||||
- lead_role: lead
|
||||
- specialist_roles: []
|
||||
- hint: $Hint
|
||||
- preset: $(if ([string]::IsNullOrWhiteSpace($Preset)) { 'none' } else { $Preset })
|
||||
|
||||
## auth
|
||||
- status: $authStatusResolved
|
||||
@@ -293,7 +330,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``
|
||||
|
||||
Reference in New Issue
Block a user