Use this skill to fuzz open source JVM projects (Java, Kotlin, Scala, etc.) using Jazzer.
npx skills add https://github.com/google/oss-fuzz --skill fuzzing-jvm-expert
This skill provides the agent with the knowledge and tools to write, build, and
validate fuzz targets for JVM-based projects (Java, Kotlin, Scala, Groovy)
integrated into OSS-Fuzz. JVM fuzzing uses
Jazzer, which wraps
libFuzzer and instruments JVM bytecode for coverage guidance.
JVM projects must use the JVM base builder image:
FROM gcr.io/oss-fuzz-base/base-builder-jvm
Set language: jvm in project.yaml.
The simplest Jazzer harness receives raw bytes via fuzzerTestOneInput:
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
public class MyTargetFuzzer {
public static void fuzzerTestOneInput(byte[] data) {
try {
MyLibrary.parse(data);
} catch (ExpectedExceptionType e) {
// Ignore expected exceptions; they are not bugs.
}
}
}
FuzzedDataProvider splits the raw byte stream into typed values, which is
essential for targets that require structured input:
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
public class MyTargetFuzzer {
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
String header = data.consumeString(64);
int version = data.consumeInt();
byte[] payload = data.consumeRemainingAsBytes();
try {
MyLibrary.process(header, version, payload);
} catch (IllegalArgumentException | IOException e) {
// Expected — not a finding.
}
}
}
Useful FuzzedDataProvider methods:
| Method | Description |
|---|---|
| consumeBytes(n) | byte[] of length n |
| consumeRemainingAsBytes() | all remaining bytes |
| consumeString(maxLen) | arbitrary String |
| consumeAsciiString(maxLen) | ASCII-only String |
| consumeInt() / consumeInt(min, max) | int |
| consumeLong() | long |
| consumeBoolean() | boolean |
| consumeDouble() | double |
| pickValue(collection) | random element |
fuzzerInitializeIf initialisation is expensive (loading config, creating DB connections, etc.),
put it in an optional static method that Jazzer calls once before fuzzing:
public class MyTargetFuzzer {
private static MyClient client;
public static void fuzzerInitialize() {
client = new MyClient(/* static config */);
}
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
client.process(data.consumeRemainingAsBytes());
}
}
The build.sh pattern for Maven projects:
# Build the project JARs.
$MVN package -DskipTests -Dmaven.javadoc.skip=true
# Collect JARs needed at runtime.
ALL_JARS="mylib-1.0.jar"
BUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "$OUT/%s:"):$JAZZER_API_PATH
RUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- "\$this_dir/%s:"):\$this_dir
for fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do
fuzzer_basename=$(basename -s .java "$fuzzer")
javac -cp $BUILD_CLASSPATH "$fuzzer"
cp $SRC/$fuzzer_basename.class $OUT/
# Wrapper script that launches jazzer_driver with the right arguments.
echo "#!/bin/bash
this_dir=\$(dirname \"\$0\")
if [[ \"\$@\" =~ (^| )-runs=[0-9]+($| ) ]]; then
mem_settings='-Xmx1900m:-Xss900k'
else
mem_settings='-Xmx2048m:-Xss1024k'
fi
LD_LIBRARY_PATH=\"$JVM_LD_LIBRARY_PATH\":\$this_dir \\
\$this_dir/jazzer_driver --agent_path=\$this_dir/jazzer_agent_deploy.jar \\
--instrumentation_includes=com.example.** \\
--cp=$RUNTIME_CLASSPATH \\
--target_class=$fuzzer_basename \\
--jvm_args=\"\$mem_settings\" \\
\$@" > $OUT/$fuzzer_basename
chmod u+x $OUT/$fuzzer_basename
done
For Gradle projects replace $MVN package with the appropriate Gradle command
and adjust JAR paths accordingly.
$OUT/<fuzzer_name>_seed_corpus.zip.$OUT/<fuzzer_name>.dict.beats hand-picking a few files — random mutation rarely passes the parser's
early checks. See the [structured seed generation
reference](../oss-fuzz-engineer/references/structured_seed_generation.md).
custom binary formats), network protocol handlers, template engines, and
any API that accepts untrusted bytes or strings.
try/catch for alldocumented exception types. Only unexpected exceptions and crashes are
findings.
FuzzedDataProvider for structured input rather than passing rawbytes to methods that expect well-formed data.
fuzzerInitialize: client connections,parsers with complex configuration, and loaded schemas should be set up once.
Math.random(), no System.currentTimeMillis()in the fuzzing path, no thread spawning.
--instrumentation_includes to the package prefix of the targetlibrary in the wrapper script — without this Jazzer cannot guide fuzzing.
mem_settings patternshown above to avoid OOM kills during runs vs. crash reproduction.
OutOfMemoryError, StackOverflowError, andNullPointerException on invalid input are usually expected — decide which
are genuine bugs for this project.
NullPointerException, ArrayIndexOutOfBoundsException,ClassCastException, NumberFormatException on paths that should not throw.
that fail on adversarial input.
filenames, SSRF via crafted URLs — depends on the library.
Jazzer can also detect:
Runtime.exec hooks) python3 infra/helper.py build_fuzzers <project>
python3 infra/helper.py check_build <project>
python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30
uncaught expected exception — check check_build output carefully.
mvn package orgradle build) to ensure the project itself compiles cleanly.
RUN git clone to COPY to avoid network round-trips.
Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, edit, or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy.
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
Replace with description of the skill and when Claude should use it.
Use when facing 2+ independent tasks that can be worked on without shared state or sequential dependencies
This skill should be used when the user wants to "create a skill", "add a skill to plugin", "write a new skill", "improve skill description", "organize skill content", or needs guidance on skill structure, progressive disclosure, or skill development best practices for Claude Code plugins.
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
Use when creating new skills, editing existing skills, or verifying skills work before deployment
Take google/fuzzing-jvm-expert from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.