Classic Vulnerable Default Security Recipes
Start with the classic vulnerable defaults remediation guide when you need the decision model. That guide explains why these patterns belong together, when to mitigate versus uplift, and which cross-cutting guardrails apply. This page is the companion collection of executable, agent-ready security recipes.
Each prompt below is agent-runnable: a developer, a security partner, or a security-team agentic workflow can pick it up against a single call site and produce a reviewer-ready PR (or a triage note). All of them follow the same outline — read the call site, classify, mitigate or uplift, prove behaviour preservation, open a PR.
Anatomy of a recipe
Every recipe has:
- When to use it — how to choose this recipe over a broader audit.
- Pattern — the exact call shape it targets.
- Why it matters — what the unsafe default does to a real attack.
- Mitigation — how to harden the existing call without removing it (typically a monkey-patch, a config flag, or a filter).
- Uplift — how to replace the call with a safer construct.
- Behaviour-preservation test — the round-trip test the PR must include.
- The prompt — what the agent runs.
- Watch for — the failure modes to call out in the PR body.
Catalogue
The catalogue below is auto-discovered from the recipe
files in this section. Drop a new markdown file with the
standard prompt frontmatter (title, description,
maturity, model, tags, team, author, weight) and
it will appear here on the next build — no edits to this
hub or to site config required.
Python pickle / dill on untrusted input
developmentReplace pickle on untrusted input; mitigate via a restricted unpickler with an explicit class allowlist.
PyYAML `yaml.load` without a safe Loader
developmentDefault to `yaml.safe_load`; install an import-time shim that defaults the loader for legacy callers.
Java ObjectInputStream and friends
developmentReplace with JSON serializers; mitigate via JEP 290 deserialization filters with a strict class allowlist.
XML external entities (XXE) — parser defaults
developmentPer-language parser hardening: defusedxml for Python, factory feature flags for Java, libxml entity-loading off in PHP.
JWT — `alg: none` and algorithm confusion
developmentForce an explicit algorithm allowlist on every verify call; reject `none` at the import boundary.
JavaScript `eval()` / `new Function()` on untrusted input
developmentReplace with parsers or restricted evaluators; add a CSP `script-src` ban on `unsafe-eval` for browser code.
Disabled TLS verification — `verify=False` and friends
developmentInstall the right CA bundle; add a fail-closed shim that refuses `verify=False` outside an opt-in test environment.
PHP object deserialization — `unserialize` on untrusted data
developmentReplace unsafe `unserialize` usage with JSON or strict allowed-class deserialization; add tests that preserve payload behavior.
Prototype pollution — `merge`, `assign`, and friends
developmentFilter `__proto__` / `constructor` / `prototype` keys at parse boundaries; replace hand-rolled merges with vetted utilities.
Ruby unsafe deserialization — `Marshal.load` / `YAML.load`
developmentReplace `Marshal.load` and unsafe YAML loading with safe parsers, typed coercion, and strict migration tests.
This list grows. Submissions land via the same review path as any other prompt — see Contribute.
When to use these prompts
- A pattern hunt or manual review surfaced a call site of one of the catalogued shapes.
- A SAST rule fired on the same shape (Semgrep / CodeQL rules for these defaults are well-established).
- A new repo or migration brought legacy code into a project where the default used to be acceptable and is no longer.
- An incident-response finding traced a breach back to one of these calls.
When not to use these prompts
- The unsafe call is on a path that genuinely consumes trusted-only data (a checkpoint loader for an internal training pipeline, a config parser run only on local files). Flag and document; don’t auto-replace.
- The uplift would force a coordinated, multi-repo migration the program owner hasn’t sequenced. Mitigate now, schedule the uplift.
- The repo has no test coverage on the call path. The PR needs a behaviour-preservation test before any change ships.
Cross-cutting guardrails
- Behaviour-preservation test. Every PR adds a round-trip test that exercises the old payload format under the new code path. No test, no PR.
- No silent compat shims. When the uplift requires reading legacy data via the old call, the legacy read-path is named explicitly and dated for removal.
- Audit the rejections. Mitigations log every rejection so attackers and false-positives are both visible.
- One pattern, one PR. A repo with three different classic-default findings produces three PRs.