Classic Vulnerable Defaults
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:
- 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 hugo.yaml 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.
Prototype pollution — `merge`, `assign`, and friends
developmentFilter `__proto__` / `constructor` / `prototype` keys at parse boundaries; replace hand-rolled merges with vetted utilities.
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.