sharp-edges

Identify dangerous API footguns, surprising default behaviors, and sharp edges in codebases and dependencies. Adapted from Trail of Bits. Use during code review to catch APIs that are easy to misuse, configurations that surprise, and abstractions that leak.

422 stars

Best use case

sharp-edges is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Identify dangerous API footguns, surprising default behaviors, and sharp edges in codebases and dependencies. Adapted from Trail of Bits. Use during code review to catch APIs that are easy to misuse, configurations that surprise, and abstractions that leak.

Teams using sharp-edges should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/sharp-edges/SKILL.md --create-dirs "https://raw.githubusercontent.com/vibeeval/vibecosystem/main/skills/sharp-edges/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/sharp-edges/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How sharp-edges Compares

Feature / Agentsharp-edgesStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Identify dangerous API footguns, surprising default behaviors, and sharp edges in codebases and dependencies. Adapted from Trail of Bits. Use during code review to catch APIs that are easy to misuse, configurations that surprise, and abstractions that leak.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Sharp Edges Detection

Sharp edges are APIs, configurations, and patterns that are easy to use incorrectly. They work in the happy path but break in subtle, dangerous ways.

## Three Adversary Types

When evaluating sharp edges, consider three types of users:

### 1. The Naive Developer
- Uses the API without reading docs carefully
- Copies examples from Stack Overflow
- Assumes defaults are safe
- **Question**: "Will this API hurt someone who doesn't know its quirks?"

### 2. The Malicious User
- Intentionally sends unexpected input
- Exploits race conditions and edge cases
- Chains small issues into big exploits
- **Question**: "Can someone deliberately trigger the bad behavior?"

### 3. The Future Maintainer
- Modifies code without full context
- Refactors without understanding invariants
- Doesn't know why something was done a certain way
- **Question**: "Will a reasonable change to this code introduce a bug?"

## Sharp Edge Categories

### 1. Surprising Default Behavior

APIs whose defaults do something unexpected:

```typescript
// SHARP: parseInt without radix
parseInt("08")    // 0 in old engines (octal), 8 in modern
parseInt("08", 10)  // Always 8

// SHARP: Array.sort() without comparator
[10, 2, 1].sort()  // [1, 10, 2] -- sorts as strings!
[10, 2, 1].sort((a, b) => a - b)  // [1, 2, 10]

// SHARP: JSON.parse reviver runs bottom-up
JSON.parse('{"a": {"b": 1}}', (key, val) => {
  // 'b' fires before 'a' -- counterintuitive
})

// SHARP: fetch() doesn't reject on HTTP errors
const res = await fetch('/api')  // 404 doesn't throw!
if (!res.ok) throw new Error(`HTTP ${res.status}`)
```

### 2. Silent Failures

Operations that fail without telling you:

```typescript
// SHARP: Object.freeze is shallow
const obj = Object.freeze({ nested: { value: 1 } })
obj.nested.value = 2  // Succeeds! Only top level is frozen

// SHARP: Map vs Object key coercion
const map = new Map()
map.set(1, 'number')
map.set('1', 'string')
map.get(1)   // 'number' -- Map preserves key types
// But:
const obj = {}
obj[1] = 'number'
obj['1'] = 'string'
obj[1]  // 'string' -- Object coerces keys to strings

// SHARP: Promise.all fails fast
Promise.all([p1, p2, p3])  // If p1 fails, p2/p3 results are lost
Promise.allSettled([p1, p2, p3])  // Always returns all results
```

### 3. Type Coercion Traps

```typescript
// SHARP: == vs ===
null == undefined   // true
0 == ''            // true
false == '0'       // true
// Always use ===

// SHARP: typeof null
typeof null  // 'object' -- historical bug, never fixed

// SHARP: NaN
NaN === NaN  // false
Number.isNaN(x)  // Use this instead of x === NaN
```

### 4. Concurrency Sharp Edges

```typescript
// SHARP: async forEach doesn't await
[1, 2, 3].forEach(async (item) => {
  await processItem(item)  // Fires all at once, doesn't wait
})
// Use for...of instead
for (const item of [1, 2, 3]) {
  await processItem(item)
}

// SHARP: Race condition in check-then-act
const exists = await db.findOne({ email })
if (!exists) {
  await db.create({ email })  // Another request might create it between check and act
}
// Use upsert or unique constraint instead
```

### 5. Security Sharp Edges

```typescript
// SHARP: URL parsing inconsistencies
new URL('http://evil.com\\@good.com')  // Different browsers parse differently

// SHARP: RegExp without anchors
/admin/.test('not-admin-page')  // true! No ^ or $

// SHARP: Timing attacks on string comparison
if (userToken === storedToken) { }  // Vulnerable to timing attack
// Use crypto.timingSafeEqual instead

// SHARP: Path traversal via join
path.join('/uploads', userInput)  // '../../../etc/passwd' works!
path.resolve('/uploads', userInput)  // Still dangerous
// Validate that result starts with base directory
```

### 6. Database Sharp Edges

```typescript
// SHARP: MongoDB operator injection
db.users.find({ username: req.body.username })
// If req.body.username = { "$ne": "" }, returns all users!
// Sanitize: validate input is a string

// SHARP: SQL LIKE injection
db.query(`SELECT * FROM users WHERE name LIKE '%${input}%'`)
// Input: "%" returns all, "_" matches any char
// Use parameterized queries with ESCAPE clause

// SHARP: ORM lazy loading in loops (N+1)
const users = await User.findAll()
for (const user of users) {
  const posts = await user.getPosts()  // N+1 queries!
}
// Use eager loading: User.findAll({ include: Post })
```

### 7. Framework Sharp Edges

```typescript
// SHARP: React useEffect cleanup race
useEffect(() => {
  let cancelled = false
  fetchData().then(data => {
    if (!cancelled) setState(data)  // Without this, stale updates
  })
  return () => { cancelled = true }
}, [])

// SHARP: Express middleware order matters
app.use(cors())
app.use(helmet())
app.use(authMiddleware)
app.use(rateLimiter)
// If rateLimiter is AFTER auth, unauthenticated requests aren't limited

// SHARP: Next.js revalidate: 0 is NOT "no cache"
// revalidate: 0 means "revalidate on every request" (still caches)
// Use { cache: 'no-store' } for truly no cache
```

## Detection Checklist

```
For each API/function/config in review:
[ ] What happens with empty/null/undefined input?
[ ] What happens with extremely large input?
[ ] What happens with concurrent access?
[ ] What happens when the network is slow/down?
[ ] What are the default values? Are they safe?
[ ] Does it fail silently or loudly?
[ ] Is the error message helpful or misleading?
[ ] Will a future developer understand the constraints?
[ ] Is there a safer alternative API?
```

## Documentation Pattern

When you find a sharp edge, document it:

```
SHARP EDGE: [API/pattern name]
SURPRISE: [What happens that developers don't expect]
DANGER: [What can go wrong -- security, data loss, correctness]
FIX: [The safe alternative]
AFFECTED: [Which files/modules in this codebase use it]
```

## Integration with vibecosystem

- **code-reviewer agent**: Check for known sharp edges during review
- **security-reviewer agent**: Focus on security sharp edges
- **self-learner agent**: When a sharp edge causes a bug, learn and add to detection
- **tdd-guide agent**: Write tests that exercise sharp edge behavior

Inspired by [Trail of Bits](https://github.com/trailofbits/skills) sharp-edges plugin.

Related Skills

workflow-router

422
from vibeeval/vibecosystem

Goal-based workflow orchestration - routes tasks to specialist agents based on user goals

wiring

422
from vibeeval/vibecosystem

Wiring Verification

websocket-patterns

422
from vibeeval/vibecosystem

Connection management, room patterns, reconnection strategies, message buffering, and binary protocol design.

visual-verdict

422
from vibeeval/vibecosystem

Screenshot comparison QA for frontend development. Takes a screenshot of the current implementation, scores it across multiple visual dimensions, and returns a structured PASS/REVISE/FAIL verdict with concrete fixes. Use when implementing UI from a design reference or verifying visual correctness.

verification-loop

422
from vibeeval/vibecosystem

Comprehensive verification system covering build, types, lint, tests, security, and diff review before a PR.

vector-db-patterns

422
from vibeeval/vibecosystem

Embedding strategies, ANN algorithms, hybrid search, RAG chunking strategies, and reranking for semantic search and retrieval.

variant-analysis

422
from vibeeval/vibecosystem

Find similar vulnerabilities across a codebase after discovering one instance. Uses pattern matching, AST search, Semgrep/CodeQL queries, and manual tracing to propagate findings. Adapted from Trail of Bits. Use after finding a bug to check if the same pattern exists elsewhere.

validate-agent

422
from vibeeval/vibecosystem

Validation agent that validates plan tech choices against current best practices

tracing-patterns

422
from vibeeval/vibecosystem

OpenTelemetry setup, span context propagation, sampling strategies, Jaeger queries

tour

422
from vibeeval/vibecosystem

Friendly onboarding tour of Claude Code capabilities for users asking what it can do.

tldr-stats

422
from vibeeval/vibecosystem

Show full session token usage, costs, TLDR savings, and hook activity

tldr-router

422
from vibeeval/vibecosystem

Map code questions to the optimal tldr command by detecting intent and routing to the right analysis layer.