bundled-skills/sharp-edges/SKILL.md
sharp-edges
npx skillsauth add FrancoStino/opencode-skills-antigravity sharp-edgesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Evaluates whether APIs, configurations, and interfaces are resistant to developer misuse. Identifies designs where the "easy path" leads to insecurity.
The pit of success: Secure usage should be the path of least resistance. If developers must understand cryptography, read documentation carefully, or remember special rules to avoid vulnerabilities, the API has failed.
| Rationalization | Why It's Wrong | Required Action | |-----------------|----------------|-----------------| | "It's documented" | Developers don't read docs under deadline pressure | Make the secure choice the default or only option | | "Advanced users need flexibility" | Flexibility creates footguns; most "advanced" usage is copy-paste | Provide safe high-level APIs; hide primitives | | "It's the developer's responsibility" | Blame-shifting; you designed the footgun | Remove the footgun or make it impossible to misuse | | "Nobody would actually do that" | Developers do everything imaginable under pressure | Assume maximum developer confusion | | "It's just a configuration option" | Config is code; wrong configs ship to production | Validate configs; reject dangerous combinations | | "We need backwards compatibility" | Insecure defaults can't be grandfather-claused | Deprecate loudly; force migration |
APIs that let developers choose algorithms invite choosing wrong ones.
The JWT Pattern (canonical example):
"alg": "none" to bypass signaturesDetection patterns:
algorithm, mode, cipher, hash_typeExample - PHP password_hash allowing weak algorithms:
// DANGEROUS: allows crc32, md5, sha1
password_hash($password, PASSWORD_DEFAULT); // Good - no choice
hash($algorithm, $password); // BAD: accepts "crc32"
Defaults that are insecure, or zero/empty values that disable security.
The OTP Lifetime Pattern:
# What happens when lifetime=0?
def verify_otp(code, lifetime=300): # 300 seconds default
if lifetime == 0:
return True # OOPS: 0 means "accept all"?
# Or does it mean "expired immediately"?
Detection patterns:
Questions to ask:
timeout=0? max_attempts=0? key=""?APIs that expose raw bytes instead of meaningful types invite type confusion.
The Libsodium vs. Halite Pattern:
// Libsodium (primitives): bytes are bytes
sodium_crypto_box($message, $nonce, $keypair);
// Easy to: swap nonce/keypair, reuse nonces, use wrong key type
// Halite (semantic): types enforce correct usage
Crypto::seal($message, new EncryptionPublicKey($key));
// Wrong key type = type error, not silent failure
Detection patterns:
bytes, string, []byte for distinct security conceptsThe comparison footgun:
// Timing-safe comparison looks identical to unsafe
if hmac == expected { } // BAD: timing attack
if hmac.Equal(mac, expected) { } // Good: constant-time
// Same types, different security properties
One wrong setting creates catastrophic failure, with no warning.
Detection patterns:
Examples:
# One typo = disaster
verify_ssl: fasle # Typo silently accepted as truthy?
# Magic values
session_timeout: -1 # Does this mean "never expire"?
# Dangerous combinations accepted silently
auth_required: true
bypass_auth_for_health_checks: true
health_check_path: "/" # Oops
// Sensible default doesn't protect against bad callers
public function __construct(
public string $hashAlgo = 'sha256', // Good default...
public int $otpLifetime = 120, // ...but accepts md5, 0, etc.
) {}
See config-patterns.md for detailed patterns.
Errors that don't surface, or success that masks failure.
Detection patterns:
Examples:
# Silent bypass
def verify_signature(sig, data, key):
if not key:
return True # No key = skip verification?!
# Return value ignored
signature.verify(data, sig) # Throws on failure
crypto.verify(data, sig) # Returns False on failure
# Developer forgets to check return value
Security-critical values as plain strings enable injection and confusion.
Detection patterns:
The permission accumulation footgun:
permissions = "read,write"
permissions += ",admin" # Too easy to escalate
# vs. type-safe
permissions = {Permission.READ, Permission.WRITE}
permissions.add(Permission.ADMIN) # At least it's explicit
For each choice point, ask:
0, "", null, []?-1 mean? Infinite? Error?Consider three adversaries:
The Scoundrel: Actively malicious developer or attacker controlling config
The Lazy Developer: Copy-pastes examples, skips documentation
The Confused Developer: Misunderstands the API
For each identified sharp edge:
If a finding seems questionable, return to Phase 2 and probe more edge cases.
| Severity | Criteria | Examples |
|----------|----------|----------|
| Critical | Default or obvious usage is insecure | verify: false default; empty password allowed |
| High | Easy misconfiguration breaks security | Algorithm parameter accepts "none" |
| Medium | Unusual but possible misconfiguration | Negative timeout has unexpected meaning |
| Low | Requires deliberate misuse | Obscure parameter combination |
By category:
By language (general footguns, not crypto-specific):
| Language | Guide | |----------|-------| | C/C++ | references/lang-c.md | | Go | references/lang-go.md | | Rust | references/lang-rust.md | | Swift | references/lang-swift.md | | Java | references/lang-java.md | | Kotlin | references/lang-kotlin.md | | C# | references/lang-csharp.md | | PHP | references/lang-php.md | | JavaScript/TypeScript | references/lang-javascript.md | | Python | references/lang-python.md | | Ruby | references/lang-ruby.md |
See also references/language-specific.md for a combined quick reference.
Before concluding analysis:
data-ai
Snapshot a site's SEO state and detect ranking, indexation, metadata, canonical, robots, schema, and on-page regressions over time.
development
Coordinate focused subagents on substantial work, keep their ownership non-overlapping, and integrate verified results. Use for large-scope Codex tasks; keep trivial work with the coordinator.
data-ai
Use when an owner asks to find a cofounder or project partner. Assess only that agent's own owner and rank only approved profiles other agents posted for their own owners.
devops
Install, configure, verify, repair, update, and uninstall Hyprland on Fedora Linux with GPU-aware detection (NVIDIA/AMD/Intel).