- phpcs-scan.sh: WordPress-Extra 标准扫描,提取安全发现输出 JSON - 报告生成器集成 PHPCS 维度(高危: SQL注入/CSRF, 中危: 输出未转义) - acceptance-criteria.json 新增 phpcs 阈值,整体门槛调整为 8/10 - Justfile 新增 phpcs-scan 独立任务,test-plugin 流程自动集成 - plugin-check.sh: PCP 自动化脚本(Playground 集成,待完善) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
69 lines
2.1 KiB
Bash
Executable file
69 lines
2.1 KiB
Bash
Executable file
#!/usr/bin/env bash
|
||
# PHPCS WordPress 安全 + 编码规范扫描
|
||
# 用法: phpcs-scan.sh <plugin-dir> <output-dir>
|
||
set -euo pipefail
|
||
|
||
PLUGIN_DIR="${1:?用法: $0 <plugin-dir> <output-dir>}"
|
||
OUTPUT_DIR="${2:?用法: $0 <plugin-dir> <output-dir>}"
|
||
|
||
mkdir -p "$OUTPUT_DIR"
|
||
|
||
echo "[phpcs] 扫描: $PLUGIN_DIR"
|
||
|
||
# 完整扫描(JSON 格式)
|
||
phpcs --standard=WordPress-Extra \
|
||
--extensions=php \
|
||
--report=json \
|
||
-s -n \
|
||
"$PLUGIN_DIR" \
|
||
> "$OUTPUT_DIR/phpcs-full.json" 2>/dev/null || true
|
||
|
||
# 提取安全相关发现
|
||
python3 -c "
|
||
import json, sys
|
||
with open('$OUTPUT_DIR/phpcs-full.json') as f:
|
||
data = json.load(f)
|
||
|
||
security_rules = ['Security', 'PreparedSQL']
|
||
security = []
|
||
summary = {'errors': data['totals']['errors'], 'warnings': data['totals']['warnings'], 'files': len(data['files'])}
|
||
by_rule = {}
|
||
|
||
for fpath, info in data['files'].items():
|
||
short = fpath.split('/')
|
||
# 取插件目录后的相对路径
|
||
try:
|
||
idx = next(i for i, p in enumerate(short) if p in ('includes','modules','templates','assets')) - 1
|
||
rel = '/'.join(short[idx:])
|
||
except StopIteration:
|
||
rel = '/'.join(short[-2:])
|
||
|
||
for msg in info['messages']:
|
||
src = msg.get('source', '')
|
||
is_security = any(r in src for r in security_rules)
|
||
if is_security:
|
||
security.append({
|
||
'file': rel,
|
||
'line': msg['line'],
|
||
'rule': src,
|
||
'severity': 'high' if 'PreparedSQL' in src or 'NonceVerification' in src else 'medium',
|
||
'message': msg['message'][:150]
|
||
})
|
||
by_rule[src] = by_rule.get(src, 0) + 1
|
||
|
||
result = {
|
||
'tool': 'phpcs + WordPress-Extra',
|
||
'summary': summary,
|
||
'securityFindings': len(security),
|
||
'byRule': by_rule,
|
||
'findings': security
|
||
}
|
||
|
||
with open('$OUTPUT_DIR/phpcs-security.json', 'w') as f:
|
||
json.dump(result, f, indent=2, ensure_ascii=False)
|
||
|
||
print(f'[phpcs] {summary[\"files\"]} 文件, {summary[\"errors\"]} 错误, {summary[\"warnings\"]} 警告')
|
||
print(f'[phpcs] 安全发现: {len(security)} 条')
|
||
for rule, count in sorted(by_rule.items(), key=lambda x: -x[1]):
|
||
print(f' {rule}: {count}')
|
||
"
|