中文译文
AST-Grep 代码分析
AST 模式匹配通过结构识别而非逐行阅读来发现代码问题。代码结构会揭示表面检查所遗漏的隐藏关系、漏洞和反模式。
配置
- 目标语言:${language:javascript}
- 分析重点:${analysis_focus:security}
- 严重级别:${severity_level:ERROR}
- 框架:${framework:React}
- 最大嵌套深度:${max_nesting:3}
前置条件
# Install ast-grep (if not available)
npm install -g @ast-grep/cli
# Or: mise install -g ast-grep
决策树:何时使用 AST 分析
Code review needed?
|
+-- Simple code (<${simple_code_lines:50} lines, obvious structure) --> Manual review
|
+-- Complex code (nested, multi-file, abstraction layers)
|
+-- Security review required? --> Use security patterns
+-- Performance analysis? --> Use performance patterns
+-- Structural quality? --> Use structure patterns
+-- Cross-file patterns? --> Run with --include glob
模式类别
| 类别 | 关注点 | 常见发现 |
|---|---|---|
| 安全 | 加密函数、认证流程 | 硬编码密钥、弱令牌 |
| 性能 | Hook、循环、异步 | 无限重渲染、内存泄漏 |
| 结构 | 嵌套、复杂度 | 深层条件判断、可维护性 |
核心模式
安全:硬编码密钥
# sg-rules/security/hardcoded-secrets.yml
id: hardcoded-secrets
language: ${language:javascript}
rule:
pattern: |
const $VAR = '$LITERAL';
$FUNC($VAR, ...)
meta:
severity: ${severity_level:ERROR}
message: "Potential hardcoded secret detected"
安全:不安全的令牌生成
# sg-rules/security/insecure-tokens.yml
id: insecure-token-generation
language: ${language:javascript}
rule:
pattern: |
btoa(JSON.stringify($OBJ) + '.' + $SECRET)
meta:
severity: ${severity_level:ERROR}
message: "Insecure token generation using base64"
性能:${framework:React} Hook 依赖项
# sg-rules/performance/react-hook-deps.yml
id: react-hook-dependency-array
language: typescript
rule:
pattern: |
useEffect(() => {
$BODY
}, [$FUNC])
meta:
severity: WARNING
message: "Function dependency may cause infinite re-renders"
结构:深层嵌套
# sg-rules/structure/deep-nesting.yml
id: deep-nesting
language: ${language:javascript}
rule:
any:
- pattern: |
if ($COND1) {
if ($COND2) {
if ($COND3) {
$BODY
}
}
}
- pattern: |
for ($INIT) {
for ($INIT2) {
for ($INIT3) {
$BODY
}
}
}
meta:
severity: WARNING
message: "Deep nesting (>${max_nesting:3} levels) - consider refactoring"
运行分析
# Security scan
ast-grep run -r sg-rules/security/
# Performance scan on ${framework:React} files
ast-grep run -r sg-rules/performance/ --include="*.tsx,*.jsx"
# Full scan with JSON output
ast-grep run -r sg-rules/ --format=json > analysis-report.json
# Interactive mode for investigation
ast-grep run -r sg-rules/ --interactive
模式编写检查清单
- 模式匹配特定的反模式,而非通用代码
- 使用
inside或has进行上下文约束 - 包含
not约束以减少误报 - 按语言分别制定规则(JS 与 TS)
- 适当的严重级别(${severity_level:ERROR}/WARNING/INFO)
常见错误
| 错误 | 症状 | 修复方法 |
|---|---|---|
| 模式过于宽泛 | 大量误报 | 添加上下文约束 |
缺少 inside |
匹配到错误位置 | 用父级上下文限定范围 |
没有 not 子句 |
匹配到合法模式 | 排除已知无害的情况 |
| 在 TS 上使用 JS 模式 | 类型注解导致匹配失败 | 创建针对特定语言的规则 |
验证步骤
- 测试模式准确性:在已知存在漏洞的代码样本上运行
- 检查误报率:手动审查前 ${sample_size:10} 个匹配结果
- 验证严重级别:确认 ${severity_level:ERROR} 级别的发现是可操作的
- 跨文件覆盖:验证模式在预期范围内运行
示例输出
$ ast-grep run -r sg-rules/
src/components/UserProfile.jsx:15: ${severity_level:ERROR} [insecure-tokens] Insecure token generation
src/hooks/useAuth.js:8: ${severity_level:ERROR} [hardcoded-secrets] Potential hardcoded secret
src/components/Dashboard.tsx:23: WARNING [react-hook-deps] Function dependency
src/utils/processData.js:45: WARNING [deep-nesting] Deep nesting detected
Found 4 issues (2 errors, 2 warnings)
项目设置
# Initialize ast-grep in project
ast-grep init
# Create rule directories
mkdir -p sg-rules/{security,performance,structure}
# Add to CI pipeline
# .github/workflows/lint.yml
# - run: ast-grep run -r sg-rules/ --format=json
自定义模式模板
${framework:React} 特定模式
# Missing key in list rendering
id: missing-list-key
language: typescript
rule:
pattern: |
$ARRAY.map(($ITEM) => <$COMPONENT $$$PROPS />)
constraints:
$PROPS:
not:
has:
pattern: 'key={$_}'
meta:
severity: WARNING
message: "Missing key prop in list rendering"
异步/等待模式
# Missing error handling in async
id: unhandled-async
language: ${language:javascript}
rule:
pattern: |
async function $NAME($$$) {
$$$BODY
}
constraints:
$BODY:
not:
has:
pattern: 'try { $$$ } catch'
meta:
severity: WARNING
message: "Async function without try-catch error handling"
与 CI/CD 的集成
# GitHub Actions example
name: AST Analysis
on: [push, pull_request]
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install ast-grep
run: npm install -g @ast-grep/cli
- name: Run analysis
run: |
ast-grep run -r sg-rules/ --format=json > report.json
if grep -q '"severity": "${severity_level:ERROR}"' report.json; then
echo "Critical issues found!"
exit 1
fi
English original
AST-Grep Code Analysis
AST pattern matching identifies code issues through structural recognition rather than line-by-line reading. Code structure reveals hidden relationships, vulnerabilities, and anti-patterns that surface inspection misses.
Configuration
- Target Language: ${language:javascript}
- Analysis Focus: ${analysis_focus:security}
- Severity Level: ${severity_level:ERROR}
- Framework: ${framework:React}
- Max Nesting Depth: ${max_nesting:3}
Prerequisites
# Install ast-grep (if not available)
npm install -g @ast-grep/cli
# Or: mise install -g ast-grep
Decision Tree: When to Use AST Analysis
Code review needed?
|
+-- Simple code (<${simple_code_lines:50} lines, obvious structure) --> Manual review
|
+-- Complex code (nested, multi-file, abstraction layers)
|
+-- Security review required? --> Use security patterns
+-- Performance analysis? --> Use performance patterns
+-- Structural quality? --> Use structure patterns
+-- Cross-file patterns? --> Run with --include glob
Pattern Categories
| Category | Focus | Common Findings |
|---|---|---|
| Security | Crypto functions, auth flows | Hardcoded secrets, weak tokens |
| Performance | Hooks, loops, async | Infinite re-renders, memory leaks |
| Structure | Nesting, complexity | Deep conditionals, maintainability |
Essential Patterns
Security: Hardcoded Secrets
# sg-rules/security/hardcoded-secrets.yml
id: hardcoded-secrets
language: ${language:javascript}
rule:
pattern: |
const $VAR = '$LITERAL';
$FUNC($VAR, ...)
meta:
severity: ${severity_level:ERROR}
message: "Potential hardcoded secret detected"
Security: Insecure Token Generation
# sg-rules/security/insecure-tokens.yml
id: insecure-token-generation
language: ${language:javascript}
rule:
pattern: |
btoa(JSON.stringify($OBJ) + '.' + $SECRET)
meta:
severity: ${severity_level:ERROR}
message: "Insecure token generation using base64"
Performance: ${framework:React} Hook Dependencies
# sg-rules/performance/react-hook-deps.yml
id: react-hook-dependency-array
language: typescript
rule:
pattern: |
useEffect(() => {
$BODY
}, [$FUNC])
meta:
severity: WARNING
message: "Function dependency may cause infinite re-renders"
Structure: Deep Nesting
# sg-rules/structure/deep-nesting.yml
id: deep-nesting
language: ${language:javascript}
rule:
any:
- pattern: |
if ($COND1) {
if ($COND2) {
if ($COND3) {
$BODY
}
}
}
- pattern: |
for ($INIT) {
for ($INIT2) {
for ($INIT3) {
$BODY
}
}
}
meta:
severity: WARNING
message: "Deep nesting (>${max_nesting:3} levels) - consider refactoring"
Running Analysis
# Security scan
ast-grep run -r sg-rules/security/
# Performance scan on ${framework:React} files
ast-grep run -r sg-rules/performance/ --include="*.tsx,*.jsx"
# Full scan with JSON output
ast-grep run -r sg-rules/ --format=json > analysis-report.json
# Interactive mode for investigation
ast-grep run -r sg-rules/ --interactive
Pattern Writing Checklist
- Pattern matches specific anti-pattern, not general code
- Uses
insideorhasfor context constraints - Includes
notconstraints to reduce false positives - Separate rules per language (JS vs TS)
- Appropriate severity (${severity_level:ERROR}/WARNING/INFO)
Common Mistakes
| Mistake | Symptom | Fix |
|---|---|---|
| Too generic patterns | Many false positives | Add context constraints |
Missing inside |
Matches wrong locations | Scope with parent context |
No not clauses |
Matches valid patterns | Exclude known-good cases |
| JS patterns on TS | Type annotations break match | Create language-specific rules |
Verification Steps
- Test pattern accuracy: Run on known-vulnerable code samples
- Check false positive rate: Review first ${sample_size:10} matches manually
- Validate severity: Confirm ${severity_level:ERROR}-level findings are actionable
- Cross-file coverage: Verify pattern runs across intended scope
Example Output
$ ast-grep run -r sg-rules/
src/components/UserProfile.jsx:15: ${severity_level:ERROR} [insecure-tokens] Insecure token generation
src/hooks/useAuth.js:8: ${severity_level:ERROR} [hardcoded-secrets] Potential hardcoded secret
src/components/Dashboard.tsx:23: WARNING [react-hook-deps] Function dependency
src/utils/processData.js:45: WARNING [deep-nesting] Deep nesting detected
Found 4 issues (2 errors, 2 warnings)
Project Setup
# Initialize ast-grep in project
ast-grep init
# Create rule directories
mkdir -p sg-rules/{security,performance,structure}
# Add to CI pipeline
# .github/workflows/lint.yml
# - run: ast-grep run -r sg-rules/ --format=json
Custom Pattern Templates
${framework:React} Specific Patterns
# Missing key in list rendering
id: missing-list-key
language: typescript
rule:
pattern: |
$ARRAY.map(($ITEM) => <$COMPONENT $$$PROPS />)
constraints:
$PROPS:
not:
has:
pattern: 'key={$_}'
meta:
severity: WARNING
message: "Missing key prop in list rendering"
Async/Await Patterns
# Missing error handling in async
id: unhandled-async
language: ${language:javascript}
rule:
pattern: |
async function $NAME($$$) {
$$$BODY
}
constraints:
$BODY:
not:
has:
pattern: 'try { $$$ } catch'
meta:
severity: WARNING
message: "Async function without try-catch error handling"
Integration with CI/CD
# GitHub Actions example
name: AST Analysis
on: [push, pull_request]
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install ast-grep
run: npm install -g @ast-grep/cli
- name: Run analysis
run: |
ast-grep run -r sg-rules/ --format=json > report.json
if grep -q '"severity": "${severity_level:ERROR}"' report.json; then
echo "Critical issues found!"
exit 1
fi