用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/SocketDev/socket-btm --skill property-and-fuzz-testing命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | property-and-fuzz-testing |
| description | Pick a property/fuzz tier and harness for parsers, decoders, and native addons. |
| metadata | {"internal":true} |
Three tiers, each for a different shape of bug. Pick the tier by what you're testing, then open the per-language reference for the harness.
| Testing… | Tier | Why |
|---|---|---|
| A pure function with an invariant ("always/never") | property (Tier 1) | Generated inputs + shrinking to a minimal counterexample |
| Any untrusted-input boundary — parser, decoder, config/manifest loader, wire-format reader, or native C++/Rust module — that must not crash/hang/corrupt on any input | coverage-guided fuzzing (Tier 2) | Finds crash / memory-safety / security inputs with no spec; replayable corpus |
A stateful SUT invariant over synthetic worlds (cascade parity, check↔fix idempotence) | hand-rolled seeded (Tier 3) | Drives the real SUTs over generated repo trees; deterministic replay |
Property/fuzz tests complement example tests — they don't replace them.
Keep a few concrete test('…') cases as living documentation; add a property
or fuzz test for the "for all inputs" claim.
Correctness vs safety are different fuzzers, both wanted. A property test checks correctness against a property you write (finds wrong answers); a coverage-guided fuzzer finds crashes / memory / security violations with no spec, using coverage feedback to reach deep paths random sampling misses. A function can be crash-free but wrong (property catches) or correct-on-samples but crash on a deep-path input (fuzzer catches). For a native parser do both: libFuzzer + ASan on the native code (memory safety) AND a JS-surface fuzz through the boundary (the integration contract).
Each reference carries the tool, file layout, run commands, escalation to stronger engines, and CI/gate wiring for that ecosystem. The Rust lane is the canonical reference where a surface is implemented in several languages (see "Lock-step" below).
| Language | Tier 1 (property) | Tier 2 (coverage-guided) | Reference |
|---|---|---|---|
| JS / TS | fast-check | vitiate (SWC-instrumented) | references/javascript-typescript.md |
| Rust | proptest / quickcheck | cargo-fuzz (libFuzzer) + ASan/UBSan | references/rust.md |
| Go | table props / testing/quick | go test -fuzz (native) | references/go.md |
| C++ | assertion harness | libFuzzer + -fsanitize=address,fuzzer,undefined | references/cpp.md |
"A bug here = red CI everywhere" surfaces. Property/fuzz them first:
compareSemver, extractPinVersion, derivePins,
applyPins (sync-package-manager-pins.mts), majorBoundedRange.
Properties: total order; derivePins always yields a valid >=x <y;
applyPins is idempotent.readSocketWheelhouseConfig,
validateBundleBlock. Property: never throws on arbitrary input; accepts iff
genuinely valid.check ↔ fix idempotence (Tier 3) — for arbitrary synthetic
trees: collectFindings(applyFixes(x)) is clean (a fix never leaves a
fixable finding), applyFixes∘applyFixes = applyFixes, and a fixer never
mutates a path outside its finding's scope.acorn JS/TS parser (every lane), envrypt's .env parse
pipeline + ECIES decrypt, decmpfs's compression reader, and abitious's hybrid
.node reader. A native module is the top priority — a crafted input can
overflow/UAF the C++/Rust, which a JS-level test never sees — so fuzz the
native code directly with libFuzzer/cargo-fuzz + ASan/UBSan, not only through
the JS boundary.When ONE surface is implemented in several languages (acorn's parser: Rust /
Go / C++ / TS), the fuzzers are lock-step, exactly like the parsers: Rust is
the canonical fuzzer and the source of truth; the other lanes are ports. The
shared contract — corpus format, adversarial dictionary, classification
taxonomy, repro-dump shape — is defined ONCE at the package level and every
lane's harness points at it, so a seed added for one lane is a seed for all.
The reference implementation is packages/acorn/fuzz/ (the shared substrate)
with per-lane harnesses under lang/<lang>/fuzz/. Any accept-here /
reject-there split across lanes is a divergence finding, not a silent fixup.
A single-language surface (envrypt, decmpfs, abitious, sdxgen) needs no shared
substrate — its one lane's fuzz/ tree IS the source of truth.
The natives above (cargo-fuzz, go test -fuzz, libFuzzer) are the right
DEFAULT — lowest friction, lock-step across lanes, replayable corpus. Escalate
only for a proven need; each reference names the concrete tool + when:
arbitrary (already used), libprotobuf-mutator (C++),
fuzzed-typed Go harnesses. Reaches valid-but-adversarial inputs a byte
mutator wastes cycles rediscovering.FUZZ_SEED / FUZZ_ITERS for seeded
harnesses; -max_total_time / -fuzztime / --fuzz-time for the native
fuzzers).0 = clean, a crash code = fail + upload the minimized artifact, a timeout
code = hang. Never treat "exit 1 = crash found" — the codes are tool- and
version-specific.