Identifies error-prone APIs, dangerous configurations, and footgun designs that enable security mistakes. Use when reviewing API designs, configuration schemas, cryptographic library ergonomics, or evaluating whether code follows 'secure by default' and 'pit of success' principles. Triggers: footgun, misuse-resistant, secure defaults, API usability, dangerous configuration.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Identifies error-prone APIs, dangerous configurations, and footgun designs that enable security mistakes. Use when reviewing API designs, configuration schemas, cryptographic library ergonomics, or evaluating whether code follows 'secure by default' and 'pit of success' principles. Triggers: footgun, misuse-resistant, secure defaults, API usability, dangerous configuration.
allowed-tools
["Read","Grep","Glob"]
Sharp Edges Analysis
Evaluates whether APIs, configurations, and interfaces are resistant to developer misuse. Identifies designs where the "easy path" leads to insecurity.
When to Use
Reviewing API or library design decisions
Auditing configuration schemas for dangerous options
Evaluating cryptographic API ergonomics
Assessing authentication/authorization interfaces
Reviewing any code that exposes security-relevant choices to developers
When NOT to Use
Implementation bugs (use standard code review)
Business logic flaws (use domain-specific analysis)
Performance optimization (different concern)
Core Principle
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.
Rationalizations to Reject
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
Sharp Edge Categories
1. Algorithm/Mode Selection Footguns
APIs that let developers choose algorithms invite choosing wrong ones.
The JWT Pattern (canonical example):
Header specifies algorithm: attacker can set "alg": "none" to bypass signatures
Algorithm confusion: RSA public key used as HMAC secret when switching RS256→HS256
Root cause: Letting untrusted input control security-critical decisions
Detection patterns:
Function parameters like algorithm, mode, cipher, hash_type
Enums/strings selecting cryptographic primitives
Configuration options for security mechanisms
Example - PHP password_hash allowing weak algorithms:
// DANGEROUS: allows crc32, md5, sha1password_hash($password, PASSWORD_DEFAULT); // Good - no choicehash($algorithm, $password); // BAD: accepts "crc32"
2. Dangerous Defaults
Defaults that are insecure, or zero/empty values that disable security.
The OTP Lifetime Pattern:
# What happens when lifetime=0?defverify_otp(code, lifetime=300): # 300 seconds defaultif lifetime == 0:
returnTrue# OOPS: 0 means "accept all"?# Or does it mean "expired immediately"?
Detection patterns:
Timeouts/lifetimes that accept 0 (infinite? immediate expiry?)
Empty strings that bypass checks
Null values that skip validation
Boolean defaults that disable security features
Negative values with undefined semantics
Questions to ask:
What happens with timeout=0? max_attempts=0? key=""?
Is the default the most secure option?
Can any default value disable security entirely?
3. Primitive vs. Semantic APIs
APIs that expose raw bytes instead of meaningful types invite type confusion.
The Libsodium vs. Halite Pattern:
// Libsodium (primitives): bytes are bytessodium_crypto_box($message, $nonce, $keypair);
// Easy to: swap nonce/keypair, reuse nonces, use wrong key type// Halite (semantic): types enforce correct usageCrypto::seal($message, newEncryptionPublicKey($key));
// Wrong key type = type error, not silent failure
Detection patterns:
Functions taking bytes, string, []byte for distinct security concepts
Parameters that could be swapped without type errors
Same type used for keys, nonces, ciphertexts, signatures
The comparison footgun:
// Timing-safe comparison looks identical to unsafeif hmac == expected { } // BAD: timing attackif hmac.Equal(mac, expected) { } // Good: constant-time// Same types, different security properties
4. Configuration Cliffs
One wrong setting creates catastrophic failure, with no warning.
Detection patterns:
Boolean flags that disable security entirely
String configs that aren't validated
Combinations of settings that interact dangerously
Environment variables that override security settings
Constructor parameters with sensible defaults but no validation (callers can override with insecure values)
Examples:
# One typo = disasterverify_ssl:fasle# Typo silently accepted as truthy?# Magic valuessession_timeout:-1# Does this mean "never expire"?# Dangerous combinations accepted silentlyauth_required:truebypass_auth_for_health_checks:truehealth_check_path:"/"# Oops
// Sensible default doesn't protect against bad callerspublicfunction__construct(publicstring$hashAlgo = 'sha256', // Good default...
publicint$otpLifetime = 120, // ...but accepts md5, 0, etc.
) {}
Errors that don't surface, or success that masks failure.
Detection patterns:
Functions returning booleans instead of throwing on security failures
Empty catch blocks around security operations
Default values substituted on parse errors
Verification functions that "succeed" on malformed input
Examples:
# Silent bypassdefverify_signature(sig, data, key):
ifnot key:
returnTrue# 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
6. Stringly-Typed Security
Security-critical values as plain strings enable injection and confusion.
Detection patterns:
SQL/commands built from string concatenation
Permissions as comma-separated strings
Roles/scopes as arbitrary strings instead of enums
URLs constructed by joining strings
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