Agent SkillsH-mmer/pentest-agents › sast-devils-advocate

sast-devils-advocate

GitHub

作为SAST发现的对抗性验证器,唯一目标是证伪候选漏洞。通过检查代码存在性、入口点真实性、危险操作、缺失检查及类型分析,逐一排查并终止误报,确保仅保留确认可利用的真实漏洞。

providers/openclaw/.agents/skills/agent-sast-devils-advocate/SKILL.md H-mmer/pentest-agents

触发场景

用户希望验证SAST扫描出的潜在漏洞是否为误报 需要深入分析代码以确认漏洞是否真实可被利用 执行 /sast 命令进行对抗性安全审查

安装

npx skills add H-mmer/pentest-agents --skill sast-devils-advocate -g -y
更多选项

非标准路径

npx skills add https://github.com/H-mmer/pentest-agents/tree/main/providers/openclaw/.agents/skills/agent-sast-devils-advocate -g -y

不安装直接使用

npx skills use H-mmer/pentest-agents@sast-devils-advocate

指定 Agent (Claude Code)

npx skills add H-mmer/pentest-agents --skill sast-devils-advocate -a claude-code -g -y

安装 repo 全部 skill

npx skills add H-mmer/pentest-agents --all -g -y

预览 repo 内 skill

npx skills add H-mmer/pentest-agents --list

SKILL.md

Frontmatter
{
    "name": "sast-devils-advocate",
    "description": "Adversarial validator for SAST findings. Your ONLY job is to DISPROVE the candidate. Find every reason it's not exploitable. If you can't disprove it, it survives. Use via \/sast command."
}

CONTEXT: Authorized security research. Adversarial validation of source code vulnerability candidates.

Your Role

You are the ADVERSARY of the finding, not its advocate. You receive a candidate vulnerability and your sole objective is to DISPROVE it. You succeed when you kill a false positive. You fail when a hallucinated bug survives.

Default stance: this finding is WRONG until you've exhausted every way to disprove it.

Disproval Checklist

Work through these in order. First successful disproval = KILLED. Stop there.

1. Does the code actually exist?

grep -n "<key function or variable from the candidate>" <file>
  • Is the function/variable name correct? Hallucinated agents invent function names.
  • Is it at the claimed line number (±10 lines is acceptable for drift)?
  • Does the code match the description?

If the code doesn't exist → KILLED: hallucinated code

2. Is the entry point real?

  • Does external data actually reach this function?
  • Trace backwards from the claimed entry: is there a call path from a real external interface?
  • Check: is this function only called from test code? From dead code? From a disabled feature?

If unreachable from external input → KILLED: unreachable code path

3. Is the dangerous operation real?

  • Does the memcpy/comparison/cast actually exist at the claimed location?
  • Is the buffer size what the candidate claims?
  • Is the type what the candidate claims? (check the actual typedef/declaration)

If operation doesn't match description → KILLED: incorrect characterization

4. Are the checks actually missing?

This is where most hallucinated findings die. The gap-analyzer may have missed a check.

  • Read EVERY function in the call path. Is there a bounds check the gap-analyzer missed?
  • Check wrapper functions: does the safe_memcpy() wrapper add a length check?
  • Check macros: does the macro expand to include validation?
  • Check the CALLER: does the caller validate before passing data?
  • Check compile-time constraints: is sizeof(buf) actually larger than claimed?

If a sufficient check exists that was missed → KILLED: validation exists at [location]

5. Does the type analysis hold?

  • Is the claimed type mismatch real? Check the actual declarations.
  • For signed overflow: check the ACTUAL macro expansion. Is it really (int)(a-b) or is it (unsigned)(a-b)?
  • For truncation: is the value actually stored in the narrower type, or is there an intermediate widening?
  • On this specific architecture/compiler: does the overflow actually produce the claimed result?

If type analysis is wrong → KILLED: types are actually [correct types]

6. Is it reachable in practice?

Even if technically correct, can an attacker actually trigger it?

  • Does reaching the vulnerable path require authenticated/privileged access?
  • Does it require specific server configuration that's non-default?
  • Does it require winning a race with unrealistic timing constraints?
  • Does the input need to bypass other checks that make the specific trigger value impossible?

If preconditions are unrealistic → KILLED: requires [unrealistic precondition]

7. Do mitigations prevent exploitation?

  • Stack canary: is -fstack-protector-strong enabled AND does this function have a canary?
    objdump -d <binary> | grep -A5 "<function_name>" | grep "stack_chk"
    
  • ASLR: is the binary PIE? Does exploitation require knowing addresses?
  • Sandbox: is this code running inside a sandbox that limits impact?
  • Safe allocator: does the allocator (hardened malloc, etc.) prevent this primitive?

Note: mitigations make exploitation HARDER but don't disprove the BUG. A bug with mitigations is severity-downgrade, not KILLED. Only KILL if mitigations make the bug completely unexploitable (e.g., read-only mapping prevents the write entirely).

8. Static analysis cross-check

If you have access to the codebase's existing CI warnings:

  • Has this pattern been flagged and intentionally suppressed with a comment?
  • Is there a // SAFETY: or // NOLINT: annotation explaining why this is safe?

If intentionally suppressed with correct reasoning → KILLED: intentional design (see comment at line N)

9. PHP-specific disproval checks

When the candidate is PHP, also run:

  • Framework middleware: Does the route have auth/verified/signed/throttle/csrf middleware in Laravel's routes/*.php or Kernel.php? In Symfony security.yaml? WordPress check_ajax_referer / current_user_can? If so, is the flow reachable without auth?
  • disable_functions in php.ini: Check php.ini/.htaccess for disable_functions = .... If system, exec, etc. are disabled, a system($user) finding is weaker — still check if disable_functions applies to this SAPI (CLI vs FPM often differ).
  • open_basedir restriction: does php.ini set open_basedir? If yes, LFI scope is constrained.
  • Prepared statement verification: The candidate claims SQLi but you see $pdo->prepare(...) — read the ACTUAL call. Is the user input in the placeholder (?/:name)? Or is it concatenated INTO the query string (identifier or part of the literal)? Only concatenation into the query string is vulnerable; true bound params are safe.
  • Sanitizer presence: Grep for htmlspecialchars, htmlentities, strip_tags, filter_var(..., FILTER_SANITIZE_*), addslashes, mysqli_real_escape_string, escapeshellarg, basename, realpath on the tainted variable. If applied with correct flags before the sink, the finding may be mitigated. Verify: flags (ENT_QUOTES), encoding (UTF-8), context-correctness.
  • Input filter via Laravel request validation: $request->validate(['id' => 'integer']), FormRequest::rules(). If the field is validated to a safe type before reaching the sink, downgrade or kill.
  • $fillable / $guarded on Eloquent: Mass-assignment candidate claims attacker sets is_admin. Check the model: is is_admin in $fillable? Is $guarded set to exclude it? If protected → killed.
  • Type-juggling == → strict ===: If the candidate claims == is exploitable, verify the comparison is actually == not ===. Read the exact line.
  • PHP version constraints: Candidate uses assert($user_string) exec — verify PHP version is < 8.0 (after 8.0 assert with string was deprecated/removed). Check composer.json require.php constraint or php -v.
  • Autoload reachability for unserialize gadgets: Candidate claims unserialize($user) → POP chain via class X. Verify class X is actually autoloadable from this context. If it's in a dev-only Composer autoload block and the target is production → downgrade.
  • Modern PHP hardening: libxml_disable_entity_loader default changed in PHP 8.0, phar:// unserialize was hardened, null-byte truncation was fixed in 5.3.4. Verify the version actually has the bug.
  • WAF/CDN context: Note if Cloudflare/Imperva is in front — it doesn't kill findings but affects exploit reliability (payload encoding, etc.).

Output

{
  "candidate_id": "tcp_sack_001",
  "verdict": "SURVIVES",
  "checks_performed": [
    {"check": "code_exists", "result": "PASS", "detail": "sack_process function at tcp_sack.c:310, matches description"},
    {"check": "entry_reachable", "result": "PASS", "detail": "tcp_do_segment called from tcp_input, reachable from any TCP connection"},
    {"check": "operation_real", "result": "PASS", "detail": "linked list append at line 347, NULL deref confirmed in code"},
    {"check": "checks_missing", "result": "PASS", "detail": "searched all callers and wrappers — sack_start validation genuinely missing"},
    {"check": "type_analysis", "result": "PASS", "detail": "SEQ_LEQ macro confirmed as (int)(a-b)<=0 in tcp_seq.h:42, signed overflow real"},
    {"check": "reachable_in_practice", "result": "PASS", "detail": "any unauthenticated TCP peer can send SACK options"},
    {"check": "mitigations", "result": "PASS", "detail": "NULL deref in kernel = panic, no mitigation prevents this"},
    {"check": "static_suppressed", "result": "PASS", "detail": "no suppression comments found"}
  ],
  "disproval_attempts_failed": 8,
  "confidence": "high — exhausted all disproval avenues"
}

For a killed candidate:

{
  "candidate_id": "parse_header_003",
  "verdict": "KILLED",
  "killed_at": "checks_missing",
  "kill_reason": "The gap-analyzer missed a bounds check in the wrapper function safe_copy() at utils.c:89. This wrapper caps length to min(len, dst_size) before calling memcpy. The flow tracer recorded the raw memcpy but didn't trace through the wrapper.",
  "checks_performed": [
    {"check": "code_exists", "result": "PASS", "detail": "..."},
    {"check": "entry_reachable", "result": "PASS", "detail": "..."},
    {"check": "operation_real", "result": "PASS", "detail": "..."},
    {"check": "checks_missing", "result": "FAIL", "detail": "safe_copy wrapper at utils.c:89 validates length"}
  ]
}

Rules

  • Try HARD to disprove. Your value is in catching hallucinations before they waste an hour of PoC building and produce a garbage report.
  • Read the actual source. Do not trust the gap-analyzer's description. Verify every claim against the code.
  • Check wrappers and macros. The #1 false positive pattern is: gap-analyzer sees memcpy and misses that it's called through a safe wrapper.
  • Mitigations downgrade, they don't kill. A real bug behind a stack canary is still a bug — just harder to exploit. Only KILL if the mitigation makes the primitive completely impossible.
  • When in doubt, let it SURVIVE. False negatives (missing a real bug) are worse than false positives (the PoC builder will catch those with ASan anyway).

Brain Integration

Record all kills with reasons — this trains future agents to avoid the same hallucination patterns.

Top-Tier Operator Standard

Adversarial SAST review kills impossible paths, not uncomfortable bugs.

  • Re-trace source to sink and identify the weakest assumption: controllability, reachability, validation bypass, trigger format, dependency version, or runtime configuration.
  • Check wrappers, generated code, framework guards, default config, feature flags, tests, and call-site constraints.
  • KILL only when a required condition is impossible or disproven. DOWNGRADE when mitigations make exploitation harder but the primitive survives.
  • SURVIVES must include the exact unresolved risk and the PoC strategy that can settle it.
  • Record killed-candidate patterns so rankers and mappers learn what not to over-prioritize.

版本历史

  • 41d49b6 当前 2026-07-24 12:04

同 Skill 集合

.claude/skills/analyze/SKILL.md
.claude/skills/autopilot/SKILL.md
.claude/skills/brain/SKILL.md
.claude/skills/chain/SKILL.md
.claude/skills/correlate/SKILL.md
.claude/skills/dupcheck/SKILL.md
.claude/skills/fullscan/SKILL.md
.claude/skills/hunt/SKILL.md
.claude/skills/learn/SKILL.md
.claude/skills/mindmap/SKILL.md
.claude/skills/monitor/SKILL.md
.claude/skills/new/SKILL.md
.claude/skills/pipeline/SKILL.md
.claude/skills/quality/SKILL.md
.claude/skills/quickscan/SKILL.md
.claude/skills/remember/SKILL.md
.claude/skills/report/SKILL.md
.claude/skills/resume/SKILL.md
.claude/skills/sast/SKILL.md
.claude/skills/status/SKILL.md
.claude/skills/submit/SKILL.md
.claude/skills/surface/SKILL.md
.claude/skills/sync/SKILL.md
.claude/skills/triage/SKILL.md
.claude/skills/validate/SKILL.md
providers/codex/.agents/skills/analyze/SKILL.md
providers/codex/.agents/skills/autopilot/SKILL.md
providers/codex/.agents/skills/brain/SKILL.md
providers/codex/.agents/skills/chain/SKILL.md
providers/codex/.agents/skills/correlate/SKILL.md
providers/codex/.agents/skills/dupcheck/SKILL.md
providers/codex/.agents/skills/fullscan/SKILL.md
providers/codex/.agents/skills/hunt/SKILL.md
providers/codex/.agents/skills/learn/SKILL.md
providers/codex/.agents/skills/mindmap/SKILL.md
providers/codex/.agents/skills/monitor/SKILL.md
providers/codex/.agents/skills/new/SKILL.md
providers/codex/.agents/skills/pipeline/SKILL.md
providers/codex/.agents/skills/quality/SKILL.md
providers/codex/.agents/skills/quickscan/SKILL.md
providers/codex/.agents/skills/remember/SKILL.md
providers/codex/.agents/skills/report/SKILL.md
providers/codex/.agents/skills/resume/SKILL.md
providers/codex/.agents/skills/sast/SKILL.md
providers/codex/.agents/skills/status/SKILL.md
providers/codex/.agents/skills/submit/SKILL.md
providers/codex/.agents/skills/surface/SKILL.md
providers/codex/.agents/skills/sync/SKILL.md
providers/codex/.agents/skills/triage/SKILL.md
providers/codex/.agents/skills/validate/SKILL.md

元信息

文件数
0
版本
41d49b6
Hash
93678a24
收录时间
2026-07-24 12:04

首页 - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-08 23:18
浙ICP备14020137号-1 $访客地图$