{"owner":"google","repo":"oss-fuzz","hasSkills":true,"totalSkillsCount":20,"totalTokensCount":38374,"categories":["anthropic-skill","root-instruction","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":["infra/experimental/agent-skills/fuzzing-jvm-expert/SKILL.md","infra/experimental/agent-skills/fuzzing-go-expert/SKILL.md","infra/experimental/agent-skills/fuzzing-rust-expert/SKILL.md","tools/vscode-extension/.eslintrc.json","AGENTS.md","tools/vscode-extension/README.md","tools/vscode-extension/package.json","tools/vscode-extension/tsconfig.json","tools/vscode-extension/package-lock.json","infra/experimental/agent-skills/fuzzing-python-expert/SKILL.md","infra/experimental/agent-skills/oss-fuzz-engineer/SKILL.md","infra/experimental/agent-skills/fuzzing-memory-unsafe-expert/SKILL.md","tools/vscode-extension/.vscode/extensions.json","tools/vscode-extension/.vscode/launch.json","tools/vscode-extension/.vscode/settings.json","tools/vscode-extension/.vscode/tasks.json","infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md","infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md","infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md","infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md"],"skills":{"infra/experimental/agent-skills/fuzzing-jvm-expert/SKILL.md":"---\nname: fuzzing-jvm-expert\ndescription:\n  Use this skill to fuzz open source JVM projects (Java, Kotlin, Scala, etc.)\n  using Jazzer.\n---\n\n# Fuzzing JVM expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for JVM-based projects (Java, Kotlin, Scala, Groovy)\nintegrated into OSS-Fuzz. JVM fuzzing uses\n[Jazzer](https://github.com/CodeIntelligenceTesting/jazzer), which wraps\nlibFuzzer and instruments JVM bytecode for coverage guidance.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nJVM projects must use the JVM base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-jvm\n```\n\nSet `language: jvm` in `project.yaml`.\n\n### Harness structure — raw bytes\n\nThe simplest Jazzer harness receives raw bytes via `fuzzerTestOneInput`:\n\n```java\nimport com.code_intelligence.jazzer.api.FuzzedDataProvider;\n\npublic class MyTargetFuzzer {\n    public static void fuzzerTestOneInput(byte[] data) {\n        try {\n            MyLibrary.parse(data);\n        } catch (ExpectedExceptionType e) {\n            // Ignore expected exceptions; they are not bugs.\n        }\n    }\n}\n```\n\n### Harness structure — typed input via FuzzedDataProvider\n\n`FuzzedDataProvider` splits the raw byte stream into typed values, which is\nessential for targets that require structured input:\n\n```java\nimport com.code_intelligence.jazzer.api.FuzzedDataProvider;\n\npublic class MyTargetFuzzer {\n    public static void fuzzerTestOneInput(FuzzedDataProvider data) {\n        String header    = data.consumeString(64);\n        int    version   = data.consumeInt();\n        byte[] payload   = data.consumeRemainingAsBytes();\n\n        try {\n            MyLibrary.process(header, version, payload);\n        } catch (IllegalArgumentException | IOException e) {\n            // Expected — not a finding.\n        }\n    }\n}\n```\n\nUseful `FuzzedDataProvider` methods:\n\n| Method | Description |\n|---|---|\n| `consumeBytes(n)` | `byte[]` of length n |\n| `consumeRemainingAsBytes()` | all remaining bytes |\n| `consumeString(maxLen)` | arbitrary String |\n| `consumeAsciiString(maxLen)` | ASCII-only String |\n| `consumeInt()` / `consumeInt(min, max)` | int |\n| `consumeLong()` | long |\n| `consumeBoolean()` | boolean |\n| `consumeDouble()` | double |\n| `pickValue(collection)` | random element |\n\n### One-time setup with `fuzzerInitialize`\n\nIf initialisation is expensive (loading config, creating DB connections, etc.),\nput it in an optional static method that Jazzer calls once before fuzzing:\n\n```java\npublic class MyTargetFuzzer {\n    private static MyClient client;\n\n    public static void fuzzerInitialize() {\n        client = new MyClient(/* static config */);\n    }\n\n    public static void fuzzerTestOneInput(FuzzedDataProvider data) {\n        client.process(data.consumeRemainingAsBytes());\n    }\n}\n```\n\n### Building in OSS-Fuzz\n\nThe `build.sh` pattern for Maven projects:\n\n```bash\n# Build the project JARs.\n$MVN package -DskipTests -Dmaven.javadoc.skip=true\n\n# Collect JARs needed at runtime.\nALL_JARS=\"mylib-1.0.jar\"\nBUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- \"$OUT/%s:\"):$JAZZER_API_PATH\nRUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- \"\\$this_dir/%s:\"):\\$this_dir\n\nfor fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do\n    fuzzer_basename=$(basename -s .java \"$fuzzer\")\n    javac -cp $BUILD_CLASSPATH \"$fuzzer\"\n    cp $SRC/$fuzzer_basename.class $OUT/\n\n    # Wrapper script that launches jazzer_driver with the right arguments.\n    echo \"#!/bin/bash\nthis_dir=\\$(dirname \\\"\\$0\\\")\nif [[ \\\"\\$@\\\" =~ (^| )-runs=[0-9]+($| ) ]]; then\n  mem_settings='-Xmx1900m:-Xss900k'\nelse\n  mem_settings='-Xmx2048m:-Xss1024k'\nfi\nLD_LIBRARY_PATH=\\\"$JVM_LD_LIBRARY_PATH\\\":\\$this_dir \\\\\n\\$this_dir/jazzer_driver --agent_path=\\$this_dir/jazzer_agent_deploy.jar \\\\\n--instrumentation_includes=com.example.** \\\\\n--cp=$RUNTIME_CLASSPATH \\\\\n--target_class=$fuzzer_basename \\\\\n--jvm_args=\\\"\\$mem_settings\\\" \\\\\n\\$@\" > $OUT/$fuzzer_basename\n    chmod u+x $OUT/$fuzzer_basename\ndone\n```\n\nFor Gradle projects replace `$MVN package` with the appropriate Gradle command\nand adjust JAR paths accordingly.\n\n### Seed corpus and dictionaries\n\n- Zip seed files to `$OUT/<fuzzer_name>_seed_corpus.zip`.\n- Place dictionaries at `$OUT/<fuzzer_name>.dict`.\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks. See the [structured seed generation\n  reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good JVM fuzzing harnesses\n\n1. **Targets attack surface**: parsers, deserializers (JSON, XML, Protobuf,\n   custom binary formats), network protocol handlers, template engines, and\n   any API that accepts untrusted bytes or strings.\n2. **Catches expected exceptions**: wrap calls in `try/catch` for all\n   documented exception types. Only unexpected exceptions and crashes are\n   findings.\n3. **Uses `FuzzedDataProvider`** for structured input rather than passing raw\n   bytes to methods that expect well-formed data.\n4. **Initialises heavy state in `fuzzerInitialize`**: client connections,\n   parsers with complex configuration, and loaded schemas should be set up once.\n5. **Avoids non-determinism**: no `Math.random()`, no `System.currentTimeMillis()`\n   in the fuzzing path, no thread spawning.\n6. **Sets `--instrumentation_includes`** to the package prefix of the target\n   library in the wrapper script — without this Jazzer cannot guide fuzzing.\n7. **Configures JVM memory appropriately**: use the `mem_settings` pattern\n   shown above to avoid OOM kills during runs vs. crash reproduction.\n8. **Avoids false positives**: `OutOfMemoryError`, `StackOverflowError`, and\n   `NullPointerException` on invalid input are usually expected — decide which\n   are genuine bugs for this project.\n\n## What JVM fuzzing finds\n\n- **Unexpected exceptions**: `NullPointerException`, `ArrayIndexOutOfBoundsException`,\n  `ClassCastException`, `NumberFormatException` on paths that should not throw.\n- **Assertion errors and contract violations**: internal consistency checks\n  that fail on adversarial input.\n- **Hang / infinite loops**: detected by OSS-Fuzz's timeout.\n- **Security bugs**: deserialization gadgets, path traversal via crafted\n  filenames, SSRF via crafted URLs — depends on the library.\n- **Logic bugs**: incorrect output for valid-ish input.\n\nJazzer can also detect:\n- SQL injection (via JDBC hooks)\n- Path traversal (via file API hooks)\n- Command injection (via `Runtime.exec` hooks)\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash usually means a missing JAR on the classpath or an\n  uncaught expected exception — check `check_build` output carefully.\n- Build the project outside the fuzzing harness first (`mvn package` or\n  `gradle build`) to ensure the project itself compiles cleanly.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- Document why each entry point was chosen and what class of bugs it may find.\n","infra/experimental/agent-skills/fuzzing-go-expert/SKILL.md":"---\nname: fuzzing-go-expert\ndescription:\n  Use this skill to fuzz open source Go software projects.\n---\n\n# Fuzzing Go expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for Go projects integrated into OSS-Fuzz. Go fuzzing uses\nthe native Go fuzzing framework introduced in Go 1.18, which OSS-Fuzz drives\nvia libFuzzer under the hood using `compile_native_go_fuzzer`.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nGo projects must use the Go base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-go\n```\n\nSet `language: go` in `project.yaml`.\n\n### Harness structure\n\nGo fuzz targets are standard Go test functions with the prefix `Fuzz`, placed\nin `_test.go` files (or plain `.go` files that import the testing package):\n\n```go\npackage mypkg\n\nimport (\n    \"testing\"\n    _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\" // required for OSS-Fuzz native fuzzing\n)\n\nfunc FuzzMyTarget(f *testing.F) {\n    // Seed corpus: add representative valid inputs so the fuzzer starts\n    // from a meaningful state rather than empty bytes.\n    f.Add([]byte(\"example input\"))\n    f.Add([]byte(\"another seed\"))\n\n    f.Fuzz(func(t *testing.T, data []byte) {\n        // Call into the target. Ignore expected errors; let unexpected\n        // panics surface as findings.\n        _, _ = ParseSomething(data)\n    })\n}\n```\n\nThe inner `f.Fuzz` callback signature can use typed parameters instead of\n`[]byte` when the target expects structured input:\n\n```go\nf.Fuzz(func(t *testing.T, s string, n int, b bool) {\n    _ = ProcessRecord(s, n, b)\n})\n```\n\n### Building in OSS-Fuzz\n\nUse the `compile_native_go_fuzzer` helper in `build.sh`. It takes the package\nimport path, the function name, and the output binary name:\n\n```bash\n# build.sh\ncp $SRC/fuzz_test.go ./          # copy harness into the module if needed\nprintf \"package mypkg\\nimport _ \\\"github.com/AdamKorcz/go-118-fuzz-build/testing\\\"\\n\" \\\n    > register.go                # required registration shim\ngo mod tidy\ncompile_native_go_fuzzer github.com/owner/repo/pkg FuzzMyTarget fuzz_my_target\n```\n\nFor projects with multiple packages or multiple fuzz targets repeat the call:\n\n```bash\ncompile_native_go_fuzzer github.com/owner/repo/pkg1 FuzzFoo fuzz_foo\ncompile_native_go_fuzzer github.com/owner/repo/pkg2 FuzzBar fuzz_bar\n```\n\n### Seed corpus and dictionaries\n\n- Seed corpus entries go in `$OUT/<fuzzer_name>_seed_corpus/` as individual\n  files, or as a zip at `$OUT/<fuzzer_name>_seed_corpus.zip`.\n- Dictionaries go in `$OUT/<fuzzer_name>.dict` as plaintext token files.\n- Alternatively, add seeds directly via `f.Add(...)` in the harness — these\n  are compiled in and used as the initial corpus.\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks. See the [structured seed generation\n  reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good Go fuzzing harnesses\n\n1. **Targets attack surface**: focus on parsers, decoders, protocol handlers,\n   serialisation/deserialisation, and any API that accepts untrusted bytes or\n   strings.\n2. **Handles expected errors gracefully**: wrap calls in error checks and ignore\n   expected error returns. Only genuine panics and unexpected behaviour are\n   findings.\n3. **Uses typed fuzz parameters** when the target is not purely byte-oriented —\n   Go's fuzzer can mutate `string`, `int`, `bool`, `float64`, etc. directly.\n4. **Avoids non-determinism**: do not use random sources, time, goroutines, or\n   global state that persists between calls.\n5. **Keeps the callback fast**: expensive setup (e.g. parsing config, opening\n   files) belongs outside `f.Fuzz(...)`, not inside the inner function.\n6. **Provides meaningful seeds**: `f.Add(...)` entries should be valid\n   representative inputs so coverage grows from the start.\n7. **Does not get stuck**: avoid code paths that busy-loop or block on I/O\n   inside the fuzz function.\n8. **Includes the registration shim**: the `import _\n   \"github.com/AdamKorcz/go-118-fuzz-build/testing\"` blank import is required\n   for OSS-Fuzz to hook into native Go fuzzing — never omit it.\n\n## What Go fuzzing finds\n\nGo is memory-safe, so the focus shifts from memory-corruption bugs to:\n\n- **Panics**: index out of range, nil pointer dereference, type assertion\n  failures, stack overflows — any unrecovered `panic` is a crash.\n- **Logic bugs**: incorrect parsing, silent data corruption, wrong output for\n  valid input.\n- **Infinite loops / hangs**: code that never returns on certain inputs\n  (detected by OSS-Fuzz's timeout).\n- **Incorrect error handling**: code that should return an error but panics\n  instead, or vice versa.\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash almost always means the harness itself is wrong (e.g.\n  missing error handling, bad seed, wrong package path).\n- Run `go vet ./...` and `go build ./...` inside the module before wrapping in\n  an OSS-Fuzz build to catch compile errors early.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- Document why each entry point was chosen and what class of bugs it may find.\n","infra/experimental/agent-skills/fuzzing-rust-expert/SKILL.md":"---\nname: fuzzing-rust-expert\ndescription:\n  Use this skill to fuzz open source Rust software projects.\n---\n\n# Fuzzing Rust expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for Rust projects integrated into OSS-Fuzz. Rust fuzzing\nuses cargo-fuzz with the `libfuzzer_sys` crate, which drives libFuzzer.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nRust projects must use the Rust base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-rust\n```\n\nSet `language: rust` in `project.yaml`.\n\n### Harness structure\n\nRust fuzz targets live in `fuzz/fuzz_targets/<name>.rs` within the crate being\nfuzzed. The minimal harness using raw bytes:\n\n```rust\n#![no_main]\nuse libfuzzer_sys::fuzz_target;\n\nfuzz_target!(|data: &[u8]| {\n    // Call into the target. The fuzzer will mutate `data` on every iteration.\n    let _ = my_crate::parse(data);\n});\n```\n\nFor structured fuzzing using the `arbitrary` crate (preferred when the target\nexpects typed input):\n\n```rust\n#![no_main]\nuse libfuzzer_sys::fuzz_target;\nuse arbitrary::Arbitrary;\n\n#[derive(Debug, Arbitrary)]\nstruct MyInput {\n    header: u8,\n    payload: Vec<u8>,\n    flags: u32,\n}\n\nfuzz_target!(|input: MyInput| {\n    let _ = my_crate::process(input.header, &input.payload, input.flags);\n});\n```\n\nThe `Cargo.toml` for the fuzz directory must declare dependencies:\n\n```toml\n# fuzz/Cargo.toml\n[package]\nname = \"my-crate-fuzz\"\nversion = \"0.0.0\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nlibfuzzer-sys = \"0.4\"\narbitrary = { version = \"1\", features = [\"derive\"] }   # only if using structured fuzzing\n\n[dependencies.my-crate]\npath = \"..\"\n\n[[bin]]\nname = \"fuzz_target_name\"\npath = \"fuzz_targets/fuzz_target_name.rs\"\ntest = false\ndoc = false\n```\n\n### Building in OSS-Fuzz\n\n`build.sh` uses `cargo fuzz build` and then copies binaries to `$OUT`:\n\n```bash\n# build.sh\ncd $SRC/<crate-dir>\ncargo fuzz build -O   # -O enables release optimisations; important for performance\n\nFUZZ_TARGET_OUTPUT_DIR=$SRC/<crate-dir>/target/x86_64-unknown-linux-gnu/release\nfor f in fuzz/fuzz_targets/*.rs; do\n    name=$(basename \"${f%.*}\")\n    cp \"$FUZZ_TARGET_OUTPUT_DIR/$name\" \"$OUT/\"\ndone\n```\n\nIf the project requires a nightly toolchain, set it in the Dockerfile:\n\n```dockerfile\nENV RUSTUP_TOOLCHAIN=nightly\n```\n\nOr pin to a specific nightly for reproducibility:\n\n```dockerfile\nENV RUSTUP_TOOLCHAIN=nightly-2025-07-03\n```\n\n### Seed corpus and dictionaries\n\n- Place seed files in `fuzz/corpus/<target_name>/` within the repo; they are\n  automatically picked up by cargo-fuzz and can be zipped for OSS-Fuzz.\n- To ship a corpus with OSS-Fuzz copy a zip to `$OUT/<target_name>_seed_corpus.zip`.\n- Dictionaries go to `$OUT/<target_name>.dict`.\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks (note: cargo-fuzz's `arbitrary` is the better route when the\n  target takes typed data rather than a byte format). See the [structured seed\n  generation reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good Rust fuzzing harnesses\n\n1. **Targets attack surface**: parsers, deserializers, protocol implementations,\n   unsafe blocks, and any API that processes untrusted bytes.\n2. **Uses structured fuzzing** (`arbitrary`) when the target expects typed data\n   rather than raw bytes — this dramatically improves coverage.\n3. **Handles expected errors**: `Result` and `Option` should be let-bound and\n   ignored (`let _ = ...`). Only actual panics are findings.\n4. **Avoids panicking on every input**: do not use `.unwrap()` or `.expect()`\n   on fallible operations driven by fuzz input — these create false positives.\n5. **Avoids non-determinism**: no `rand`, no system time, no thread spawning\n   inside the fuzz callback.\n6. **Is fast**: avoid I/O, heavy allocations, or expensive setup inside the\n   callback; do those outside the `fuzz_target!` macro if needed with\n   `LazyLock` / `OnceLock`.\n7. **Considers `unsafe` code**: if the crate has `unsafe` blocks, write\n   harnesses that exercise those paths — this is where memory bugs can still\n   occur in Rust.\n8. **Builds in release mode** (`-O`): fuzzing in debug mode is much slower.\n\n## What Rust fuzzing finds\n\nRust's ownership model prevents most memory-corruption bugs, but fuzzing still\nfinds:\n\n- **Panics**: `unwrap`/`expect` on `None`/`Err`, index out of bounds,\n  arithmetic overflow in debug mode, explicit `panic!` calls.\n- **`unsafe` bugs**: use-after-free, out-of-bounds reads/writes, undefined\n  behaviour in `unsafe` blocks — these are real memory bugs.\n- **Logic errors**: incorrect parsing, data corruption, wrong output.\n- **Hangs**: infinite loops triggered by crafted input.\n- **Stack overflows**: deep recursion on adversarial input.\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash usually means a `panic!` on every input — check for\n  `.unwrap()` calls on fuzz-driven paths and replace with `if let` or `?`.\n- Run `cargo build` and `cargo test` inside the crate before adding the fuzz\n  harness to catch pre-existing compilation errors.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- If the crate uses `no_std`, use `libfuzzer-sys`'s `no_std` feature and ensure\n  the harness does not rely on `std`.\n- Document why each entry point was chosen and what class of bugs it may find.\n","tools/vscode-extension/.eslintrc.json":"{\n  \"extends\": \"./node_modules/gts/\"\n}\n","AGENTS.md":"* Use python3 infra/helper.py to build projects and run fuzzers.\n* If doing development on infra/ you should use a venv and if it doesn't already exist, install deps from infra/ci/requirements.txt build/functions/requirements.txt with pip.\n* If doing development on infra/ run python infra/presubmit.py to format, lint and run tests.\n","tools/vscode-extension/README.md":"# OSS-Fuzz VSCode extension\n\n[OSS-Fuzz](https://github.com/google/oss-fuzz) is a fuzzing toolkit and service for fuzzing open source projects. This VSCode extension provides features and capabilities for interacting with the OSS-Fuzz toolkit and also to compare local changes to the OSS-Fuzz cloud database by way of [Open source fuzz introspection](https://introspector.oss-fuzz.com).\n\n## Features\n\nThe VSCode extension is largely driven by commands at this point. The featues of these commands includes:\n\n- Easily setting up OSS-Fuzz\n- Templates for easily setting up a new OSS-Fuzz project\n- Building arbitrary projects from OSS-Fuzz\n- Modify a project from VSCode and test changes in OSS-Fuzz\n- Easily extract code coverage of fuzzers, including local-only fuzzers\n- Compare local code coverage to what is currently achieved by OSS-Fuzz\n- Auto-generation of fuzzer templates\n\nFor a full list of commands and their features, please check the commands page.","tools/vscode-extension/package.json":"{\n  \"name\": \"OSS-Fuzz\",\n  \"displayName\": \"OSS-Fuzz\",\n  \"description\": \"\",\n  \"version\": \"0.0.5\",\n  \"publisher\": \"OSS-FuzzMaintainers\",\n  \"icon\": \"images/thumbnail.png\",\n  \"engines\": {\n    \"vscode\": \"^1.76.0\"\n  },\n  \"repository\": \"https://github.com/google/oss-fuzz\",\n  \"categories\": [\n    \"Other\"\n  ],\n  \"extensionDependencies\": [\n    \"mindaro-dev.file-downloader\"\n  ],\n  \"activationEvents\": [],\n  \"main\": \"./build/src/extension.js\",\n  \"contributes\": {\n    \"configurations\": [\n      {\n        \"id\": \"OSS-Fuzz-Base\",\n        \"title\": \"Base path to OSS-Fuzz\",\n        \"properties\": {\n          \"oss-fuzz.OSS.Path\": {\n            \"type\": \"string\"\n          }\n        }\n      }\n    ],\n    \"viewsWelcome\": [\n      {\n        \"view\": \"workbench.explorer.emptyView\",\n        \"contents\": \"You can have paragraphs of text here. You can have [links](https://code.visualstudio.com) to external sources or [internal commands](command:welcome-view-content-sample.hello).\\nUse new lines to have new paragraphs.\\nPlace a link alone in a paragraph to make it a button\\n[Hello](command:welcome-view-content-sample.hello)\"\n      }\n    ],\n    \"commands\": [\n      {\n        \"command\": \"oss-fuzz.SetUp\",\n        \"title\": \"OSS-Fuzz: Set Up OSS-Fuzz\",\n        \"description\": \"Downloads the OSS-Fuzz repository and places it under /tmp/oss-fuzz. This will then be the OSS-Fuzz repository used by vscode.\"\n      },\n      {\n        \"command\": \"oss-fuzz.RunFuzzer\",\n        \"title\": \"OSS-Fuzz: Run Fuzzer\",\n        \"description\": \"Runs a single fuzzer from a given project. The fuzzer must already be build, meaning the project should be build first.\"\n      },\n      {\n        \"command\": \"oss-fuzz.ListFuzzers\",\n        \"title\": \"OSS-Fuzz: List Fuzzers\",\n        \"description\": \"Lists the fuzzers built for a given project. The project must be build first.\"\n      },\n      {\n        \"command\": \"oss-fuzz.GetCodeCoverage\",\n        \"title\": \"OSS-Fuzz: Display Code Coverage (Python only)\",\n        \"description\": \"Downloads the latest code coverage from OSS-Fuzz's cloud data (can find at https://introspector.oss-fuzz.com).\"\n      },\n      {\n        \"command\": \"oss-fuzz.ClearCodeCoverage\",\n        \"title\": \"OSS-Fuzz: Clear Code Coverage\",\n        \"description\": \"Clears code coverage visualization in the editor.\"\n      },\n      {\n        \"command\": \"oss-fuzz.CreateOSSFuzzSetup\",\n        \"title\": \"OSS-Fuzz: Initialize OSS-Fuzz Set Up\",\n        \"description\": \"Creates the relevant files using templates to set up an OSS-Fuzz project. Uses minor heuristics e.g. detection of language.\"\n      },\n      {\n        \"command\": \"oss-fuzz.WSBuildFuzzers\",\n        \"title\": \"OSS-Fuzz: Build Fuzzers In Workspace\",\n        \"description\": \"Builds the fuzzers from the project in the current VSCode workspace.\"\n      },\n      {\n        \"command\": \"oss-fuzz.SetupCIFuzz\",\n        \"title\": \"OSS-Fuzz: Set up CIFuzz\",\n        \"description\": \"Creates the files necessary for a CIFuzz set up.\"\n      },\n      {\n        \"command\": \"oss-fuzz.testFuzzer\",\n        \"title\": \"OSS-Fuzz: Test Specific Fuzzer\",\n        \"description\": \"Tests if a given fuzzer works by running it for 10 seconds.\"\n      },\n      {\n        \"command\": \"oss-fuzz.testCodeCoverage\",\n        \"title\": \"OSS-Fuzz: End-To-End Code Coverage Generation\",\n        \"description\": \"Builds the fuzzers in a ASAN mode for a project, collects corpus using the ASAN fuzzers and then generates an HTLM code coverage report using the generated corpus.\"\n      },\n      {\n        \"command\": \"oss-fuzz.Redo\",\n        \"title\": \"OSS-Fuzz: Redo Previous Command\",\n        \"description\": \"Performs the exact same command as the most recent one. Will provide the same input to the command as the previous one. This is efficient when e.g. continuously generating code coverage reports while working on improving a fuzzing set up.\"\n      },\n      {\n        \"command\": \"oss-fuzz.Template\",\n        \"title\": \"OSS-Fuzz: Fuzzer Creation Using Templates\",\n        \"description\": \"Creates a template fuzzer file using a catalogue of templates available.\"\n      },\n      {\n        \"command\": \"oss-fuzz.GenerateClusterfuzzLite\",\n        \"title\": \"OSS-Fuzz: [CFLite] Generate ClusterfuzzLite setup\",\n        \"description\": \"Creates the files needed for ClusterfuzzLite integration.\"\n      },\n      {\n        \"command\": \"oss-fuzz.WSBuildFuzzersCFLite\",\n        \"title\": \"OSS-Fuzz: [CFLite] Build Fuzzers In Workspace\",\n        \"description\": \"Builds the ClusterfuzzLite fuzzers from the project in the current VSCode workspace.\"\n      },\n      {\n        \"command\": \"oss-fuzz.testFuzzerCFLite\",\n        \"title\": \"OSS-Fuzz: [CFLite] Test running a specific fuzzer.\",\n        \"description\": \"Builds the CFLite setup and runs a fuzzer for a short period of time.\"\n      },\n      {\n        \"command\": \"oss-fuzz.setupFuzzIntrospector\",\n        \"title\": \"OSS-Fuzz: Set up Fuzz Introspector\",\n        \"description\": \"Install fuzz introspector on the system\"\n      },\n      {\n        \"command\": \"oss-fuzz.runFuzzIntrospector\",\n        \"title\": \"OSS-Fuzz: Run Full Fuzz Introspector\",\n        \"description\": \"Runs a full Fuzz Introspector\"\n      },\n      {\n        \"command\": \"oss-fuzz.GetOptimalTargets\",\n        \"title\": \"OSS-Fuzz: Get optimal targets\",\n        \"description\": \"Gets the optimal targets of this project\"\n      }\n    ],\n    \"walkthroughs\":[\n      {\n        \"id\": \"BuildAndRunExisting Project\",\n        \"title\": \"Set up OSS-Fuzz\",\n        \"description\": \"This walkthrough takes you through how to set up OSS-Fuzz in the VSCode extension and proceeding to build the fuzzers of an existing project as well as running a fuzzer from the project.\",\n        \"steps\": [\n          {\n            \"id\": \"s1\",\n            \"title\": \"Set up OSS-Fuzz\",\n            \"description\": \"This step sets up OSS-Fuzz in the folder /tmp/oss-fuzz\",\n            \"completionEvents\": [\"onCommand:oss-fuzz.SetUp\"],\n            \"media\": {\"altText\": \".\", \"image\": \"images/workflow-1-s-1\"}\n          }\n        ]\n      }\n    ]\n  },\n  \"scripts\": {\n    \"vscode:prepublish\": \"npm run compile\",\n    \"compile\": \"tsc\",\n    \"watch\": \"tsc -watch -p ./\",\n    \"pretest\": \"npm run compile\",\n    \"lint\": \"gts lint\",\n    \"clean\": \"gts clean\",\n    \"fix\": \"gts fix\",\n    \"prepare\": \"npm run compile\",\n    \"posttest\": \"npm run lint\"\n  },\n  \"devDependencies\": {\n    \"@types/glob\": \"^8.1.0\",\n    \"@types/mocha\": \"^10.0.1\",\n    \"@types/node\": \"^14.11.2\",\n    \"@types/vscode\": \"^1.76.0\",\n    \"@typescript-eslint/eslint-plugin\": \"^5.53.0\",\n    \"@typescript-eslint/parser\": \"^5.53.0\",\n    \"@vscode/test-electron\": \"^2.2.3\",\n    \"eslint\": \"^8.34.0\",\n    \"glob\": \"^8.1.0\",\n    \"mocha\": \"^10.8.2\",\n    \"typescript\": \"~4.7.0\",\n    \"gts\": \"^3.1.1\"\n  },\n  \"dependencies\": {\n    \"@microsoft/vscode-file-downloader-api\": \"^1.0.1\"\n  }\n}\n","tools/vscode-extension/tsconfig.json":"{\n  \"extends\": \"./node_modules/gts/tsconfig-google.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \".\",\n    \"outDir\": \"build\"\n  },\n  \"include\": [\n    \"src/**/*.ts\",\n    \"test/**/*.ts\"\n  ]\n}\n","tools/vscode-extension/package-lock.json":"{\n  \"name\": \"OSS-Fuzz\",\n  \"version\": \"0.0.5\",\n  \"lockfileVersion\": 2,\n  \"requires\": true,\n  \"packages\": {\n    \"\": {\n      \"name\": \"OSS-Fuzz\",\n      \"version\": \"0.0.5\",\n      \"dependencies\": {\n        \"@microsoft/vscode-file-downloader-api\": \"^1.0.1\"\n      },\n      \"devDependencies\": {\n        \"@types/glob\": \"^8.1.0\",\n        \"@types/mocha\": \"^10.0.1\",\n        \"@types/node\": \"^14.11.2\",\n        \"@types/vscode\": \"^1.76.0\",\n        \"@typescript-eslint/eslint-plugin\": \"^5.53.0\",\n        \"@typescript-eslint/parser\": \"^5.53.0\",\n        \"@vscode/test-electron\": \"^2.2.3\",\n        \"eslint\": \"^8.34.0\",\n        \"glob\": \"^8.1.0\",\n        \"gts\": \"^3.1.1\",\n        \"mocha\": \"^10.8.2\",\n        \"typescript\": \"~4.7.0\"\n      },\n      \"engines\": {\n        \"vscode\": \"^1.76.0\"\n      }\n    },\n    \"node_modules/@babel/code-frame\": {\n      \"version\": \"7.22.5\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz\",\n      \"integrity\": \"sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@babel/highlight\": \"^7.22.5\"\n      },\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@babel/helper-validator-identifier\": {\n      \"version\": \"7.22.5\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz\",\n      \"integrity\": \"sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@babel/highlight\": {\n      \"version\": \"7.22.5\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz\",\n      \"integrity\": \"sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@babel/helper-validator-identifier\": \"^7.22.5\",\n        \"chalk\": \"^2.0.0\",\n        \"js-tokens\": \"^4.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/ansi-styles\": {\n      \"version\": \"3.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz\",\n      \"integrity\": \"sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-convert\": \"^1.9.0\"\n      },\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/chalk\": {\n      \"version\": \"2.4.2\",\n      \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz\",\n      \"integrity\": \"sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ansi-styles\": \"^3.2.1\",\n        \"escape-string-regexp\": \"^1.0.5\",\n        \"supports-color\": \"^5.3.0\"\n      },\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/color-convert\": {\n      \"version\": \"1.9.3\",\n      \"resolved\": \"https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz\",\n      \"integrity\": \"sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-name\": \"1.1.3\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/color-name\": {\n      \"version\": \"1.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz\",\n      \"integrity\": \"sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==\",\n      \"dev\": true\n    },\n    \"node_modules/@babel/highlight/node_modules/escape-string-regexp\": {\n      \"version\": \"1.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz\",\n      \"integrity\": \"sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.8.0\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/has-flag\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz\",\n      \"integrity\": \"sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/supports-color\": {\n      \"version\": \"5.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz\",\n      \"integrity\": \"sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"has-flag\": \"^3.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@eslint/eslintrc\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz\",\n      \"integrity\": \"sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ajv\": \"^6.12.4\",\n        \"debug\": \"^4.3.2\",\n        \"espree\": \"^9.4.0\",\n        \"globals\": \"^13.19.0\",\n        \"ignore\": \"^5.2.0\",\n        \"import-fresh\": \"^3.2.1\",\n        \"js-yaml\": \"^4.1.0\",\n        \"minimatch\": \"^3.1.2\",\n        \"strip-json-comments\": \"^3.1.1\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://opencollective.com/eslint\"\n      }\n    },\n    \"node_modules/@eslint/js\": {\n      \"version\": \"8.35.0\",\n      \"resolved\": \"https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz\",\n      \"integrity\": \"sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      }\n    },\n    \"node_modules/@humanwhocodes/config-array\": {\n      \"version\": \"0.11.8\",\n      \"resolved\": \"https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz\",\n      \"integrity\": \"sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@humanwhocodes/object-schema\": \"^1.2.1\",\n        \"debug\": \"^4.1.1\",\n        \"minimatch\": \"^3.0.5\"\n      },\n      \"engines\": {\n        \"node\": \">=10.10.0\"\n      }\n    },\n    \"node_modules/@humanwhocodes/module-importer\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz\",\n      \"integrity\": \"sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=12.22\"\n      },\n      \"funding\": {\n        \"type\": \"github\",\n        \"url\": \"https://github.com/sponsors/nzakas\"\n      }\n    },\n    \"node_modules/@humanwhocodes/object-schema\": {\n      \"version\": \"1.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz\",\n      \"integrity\": \"sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==\",\n      \"dev\": true\n    },\n    \"node_modules/@microsoft/vscode-file-downloader-api\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/@microsoft/vscode-file-downloader-api/-/vscode-file-downloader-api-1.0.1.tgz\",\n      \"integrity\": \"sha512-cO9n/IpTMbXizz5YcEkiuRyX5r66SBY/3LnrlroyXbQXrgDdaKecfV3n4viTcvp9O//QF2AxcBfDZex2d4VSTg==\"\n    },\n    \"node_modules/@nodelib/fs.scandir\": {\n      \"version\": \"2.1.5\",\n      \"resolved\": \"https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz\",\n      \"integrity\": \"sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@nodelib/fs.stat\": \"2.0.5\",\n        \"run-parallel\": \"^1.1.9\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/@nodelib/fs.stat\": {\n      \"version\": \"2.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz\",\n      \"integrity\": \"sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/@nodelib/fs.walk\": {\n      \"version\": \"1.2.8\",\n      \"resolved\": \"https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz\",\n      \"integrity\": \"sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@nodelib/fs.scandir\": \"2.1.5\",\n        \"fastq\": \"^1.6.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/@tootallnate/once\": {\n      \"version\": \"1.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz\",\n      \"integrity\": \"sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">= 6\"\n      }\n    },\n    \"node_modules/@types/glob\": {\n      \"version\": \"8.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz\",\n      \"integrity\": \"sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@types/minimatch\": \"^5.1.2\",\n        \"@types/node\": \"*\"\n      }\n    },\n    \"node_modules/@types/json-schema\": {\n      \"version\": \"7.0.11\",\n      \"resolved\": \"https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz\",\n      \"integrity\": \"sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/minimatch\": {\n      \"version\": \"5.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz\",\n      \"integrity\": \"sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/minimist\": {\n      \"version\": \"1.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz\",\n      \"integrity\": \"sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/mocha\": {\n      \"version\": \"10.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz\",\n      \"integrity\": \"sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/node\": {\n      \"version\": \"14.18.54\",\n      \"resolved\": \"https://registry.npmjs.org/@types/node/-/node-14.18.54.tgz\",\n      \"integrity\": \"sha512-uq7O52wvo2Lggsx1x21tKZgqkJpvwCseBBPtX/nKQfpVlEsLOb11zZ1CRsWUKvJF0+lzuA9jwvA7Pr2Wt7i3xw==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/normalize-package-data\": {\n      \"version\": \"2.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz\",\n      \"integrity\": \"sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/semver\": {\n      \"version\": \"7.3.13\",\n      \"resolved\": \"https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz\",\n      \"integrity\": \"sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/vscode\": {\n      \"version\": \"1.76.0\",\n      \"resolved\": \"https://registry.npmjs.org/@types/vscode/-/vscode-1.76.0.tgz\",\n      \"integrity\": \"sha512-CQcY3+Fe5hNewHnOEAVYj4dd1do/QHliXaknAEYSXx2KEHUzFibDZSKptCon+HPgK55xx20pR+PBJjf0MomnBA==\",\n      \"dev\": true\n    },\n    \"node_modules/@typescript-eslint/eslint-plugin\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.1.tgz\",\n      \"integrity\": \"sha512-a2RQAkosH3d3ZIV08s3DcL/mcGc2M/UC528VkPULFxR9VnVPT8pBu0IyBAJJmVsCmhVfwQX1v6q+QGnmSe1bew==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/scope-manager\": \"5.54.1\",\n        \"@typescript-eslint/type-utils\": \"5.54.1\",\n        \"@typescript-eslint/utils\": \"5.54.1\",\n        \"debug\": \"^4.3.4\",\n        \"grapheme-splitter\": \"^1.0.4\",\n        \"ignore\": \"^5.2.0\",\n        \"natural-compare-lite\": \"^1.4.0\",\n        \"regexpp\": \"^3.2.0\",\n        \"semver\": \"^7.3.7\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"@typescript-eslint/parser\": \"^5.0.0\",\n        \"eslint\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz\",\n      \"integrity\": \"sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@types/json-schema\": \"^7.0.7\",\n        \"@typescript-eslint/scope-manager\": \"4.33.0\",\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"@typescript-eslint/typescript-estree\": \"4.33.0\",\n        \"eslint-scope\": \"^5.1.1\",\n        \"eslint-utils\": \"^3.0.0\"\n      },\n      \"engines\": {\n        \"node\": \"^10.12.0 || >=12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"*\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz\",\n      \"integrity\": \"sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"@typescript-eslint/visitor-keys\": \"4.33.0\"\n      },\n      \"engines\": {\n        \"node\": \"^8.10.0 || ^10.13.0 || >=11.10.1\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz\",\n      \"integrity\": \"sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \"^8.10.0 || ^10.13.0 || >=11.10.1\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz\",\n      \"integrity\": \"sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"@typescript-eslint/visitor-keys\": \"4.33.0\",\n        \"debug\": \"^4.3.1\",\n        \"globby\": \"^11.0.3\",\n        \"is-glob\": \"^4.0.1\",\n        \"semver\": \"^7.3.5\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^10.12.0 || >=12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz\",\n      \"integrity\": \"sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"eslint-visitor-keys\": \"^2.0.0\"\n      },\n      \"engines\": {\n        \"node\": \"^8.10.0 || ^10.13.0 || >=11.10.1\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-visitor-keys\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz\",\n      \"integrity\": \"sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@typescript-eslint/parser\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.1.tgz\",\n      \"integrity\": \"sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/scope-manager\": \"5.54.1\",\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/typescript-estree\": \"5.54.1\",\n        \"debug\": \"^4.3.4\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/scope-manager\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz\",\n      \"integrity\": \"sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/visitor-keys\": \"5.54.1\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/type-utils\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.1.tgz\",\n      \"integrity\": \"sha512-WREHsTz0GqVYLIbzIZYbmUUr95DKEKIXZNH57W3s+4bVnuF1TKe2jH8ZNH8rO1CeMY3U4j4UQeqPNkHMiGem3g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/typescript-estree\": \"5.54.1\",\n        \"@typescript-eslint/utils\": \"5.54.1\",\n        \"debug\": \"^4.3.4\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"*\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/types\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz\",\n      \"integrity\": \"sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/typescript-estree\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz\",\n      \"integrity\": \"sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/visitor-keys\": \"5.54.1\",\n        \"debug\": \"^4.3.4\",\n        \"globby\": \"^11.1.0\",\n        \"is-glob\": \"^4.0.3\",\n        \"semver\": \"^7.3.7\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/utils\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.1.tgz\",\n      \"integrity\": \"sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@types/json-schema\": \"^7.0.9\",\n        \"@types/semver\": \"^7.3.12\",\n        \"@typescript-eslint/scope-manager\": \"5.54.1\",\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/typescript-estree\": \"5.54.1\",\n        \"eslint-scope\": \"^5.1.1\",\n        \"eslint-utils\": \"^3.0.0\",\n        \"semver\": \"^7.3.7\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      }\n    },\n    \"node_modules/@typescript-eslint/visitor-keys\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz\",\n      \"integrity\": \"sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"eslint-visitor-keys\": \"^3.3.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@vscode/test-electron\": {\n      \"version\": \"2.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.0.tgz\",\n      \"integrity\": \"sha512-fwzA9RtazH1GT/sckYlbxu6t5e4VaMXwCVtyLv4UAG0hP6NTfnMaaG25XCfWqlVwFhBMcQXHBCy5dmz2eLUnkw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"http-proxy-agent\": \"^4.0.1\",\n        \"https-proxy-agent\": \"^5.0.0\",\n        \"jszip\": \"^3.10.1\",\n        \"semver\": \"^7.3.8\"\n      },\n      \"engines\": {\n        \"node\": \">=16\"\n      }\n    },\n    \"node_modules/acorn\": {\n      \"version\": \"8.8.2\",\n      \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz\",\n      \"integrity\": \"sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==\",\n      \"dev\": true,\n      \"bin\": {\n        \"acorn\": \"bin/acorn\"\n      },\n      \"engines\": {\n        \"node\": \">=0.4.0\"\n      }\n    },\n    \"node_modules/acorn-jsx\": {\n      \"version\": \"5.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz\",\n      \"integrity\": \"sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==\",\n      \"dev\": true,\n      \"peerDependencies\": {\n        \"acorn\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      }\n    },\n    \"node_modules/agent-base\": {\n      \"version\": \"6.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz\",\n      \"integrity\": \"sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"debug\": \"4\"\n      },\n      \"engines\": {\n        \"node\": \">= 6.0.0\"\n      }\n    },\n    \"node_modules/ajv\": {\n      \"version\": \"6.12.6\",\n      \"resolved\": \"https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz\",\n      \"integrity\": \"sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"fast-deep-equal\": \"^3.1.1\",\n        \"fast-json-stable-stringify\": \"^2.0.0\",\n        \"json-schema-traverse\": \"^0.4.1\",\n        \"uri-js\": \"^4.2.2\"\n      },\n      \"funding\": {\n        \"type\": \"github\",\n        \"url\": \"https://github.com/sponsors/epoberezkin\"\n      }\n    },\n    \"node_modules/ansi-colors\": {\n      \"version\": \"4.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz\",\n      \"integrity\": \"sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/ansi-escapes\": {\n      \"version\": \"4.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz\",\n      \"integrity\": \"sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"type-fest\": \"^0.21.3\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/ansi-escapes/node_modules/type-fest\": {\n      \"version\": \"0.21.3\",\n      \"resolved\": \"https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz\",\n      \"integrity\": \"sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/ansi-regex\": {\n      \"version\": \"5.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n      \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/ansi-styles\": {\n      \"version\": \"4.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz\",\n      \"integrity\": \"sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-convert\": \"^2.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n      }\n    },\n    \"node_modules/anymatch\": {\n      \"version\": \"3.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz\",\n      \"integrity\": \"sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"normalize-path\": \"^3.0.0\",\n        \"picomatch\": \"^2.0.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/argparse\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz\",\n      \"integrity\": \"sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==\",\n      \"dev\": true\n    },\n    \"node_modules/array-union\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz\",\n      \"integrity\": \"sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/arrify\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz\",\n      \"integrity\": \"sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/astral-regex\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz\",\n      \"integrity\": \"sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/balanced-match\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz\",\n      \"integrity\": \"sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==\",\n      \"dev\": true\n    },\n    \"node_modules/binary-extensions\": {\n      \"version\": \"2.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz\",\n      \"integrity\": \"sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/brace-expansion\": {\n      \"version\": \"1.1.11\",\n      \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz\",\n      \"integrity\": \"sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"balanced-match\": \"^1.0.0\",\n        \"concat-map\": \"0.0.1\"\n      }\n    },\n    \"node_modules/braces\": {\n      \"version\": \"3.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/braces/-/braces-3.0.3.tgz\",\n      \"integrity\": \"sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"fill-range\": \"^7.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/browser-stdout\": {\n      \"version\": \"1.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz\",\n      \"integrity\": \"sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==\",\n      \"dev\": true\n    },\n    \"node_modules/callsites\": {\n      \"version\": \"3.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz\",\n      \"integrity\": \"sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/camelcase\": {\n      \"version\": \"6.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz\",\n      \"integrity\": \"sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/camelcase-keys\": {\n      \"version\": \"6.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz\",\n      \"integrity\": \"sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"camelcase\": \"^5.3.1\",\n        \"map-obj\": \"^4.0.0\",\n        \"quick-lru\": \"^4.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/camelcase-keys/node_modules/camelcase\": {\n      \"version\": \"5.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz\",\n      \"integrity\": \"sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/chalk\": {\n      \"version\": \"4.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz\",\n      \"integrity\": \"sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ansi-styles\": \"^4.1.0\",\n        \"supports-color\": \"^7.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/chalk/chalk?sponsor=1\"\n      }\n    },\n    \"node_modules/chardet\": {\n      \"version\": \"0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz\",\n      \"integrity\": \"sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==\",\n      \"dev\": true\n    },\n    \"node_modules/chokidar\": {\n      \"version\": \"3.5.3\",\n      \"resolved\": \"https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz\",\n      \"integrity\": \"sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==\",\n      \"dev\": true,\n      \"funding\": [\n        {\n          \"type\": \"individual\",\n          \"url\": \"https://paulmillr.com/funding/\"\n        }\n      ],\n      \"dependencies\": {\n        \"anymatch\": \"~3.1.2\",\n        \"braces\": \"~3.0.2\",\n        \"glob-parent\": \"~5.1.2\",\n        \"is-binary-path\": \"~2.1.0\",\n        \"is-glob\": \"~4.0.1\",\n        \"normalize-path\": \"~3.0.0\",\n        \"readdirp\": \"~3.6.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 8.10.0\"\n      },\n      \"optionalDependencies\": {\n        \"fsevents\": \"~2.3.2\"\n      }\n    },\n    \"node_modules/chokidar/node_modules/glob-parent\": {\n      \"version\": \"5.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz\",\n      \"integrity\": \"sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"is-glob\": \"^4.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 6\"\n      }\n    },\n    \"node_modules/cli-cursor\": {\n      \"version\": \"3.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz\",\n      \"integrity\": \"sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"restore-cursor\": \"^3.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/cli-width\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz\",\n      \"integrity\": \"sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">= 10\"\n      }\n    },\n    \"node_modules/cliui\": {\n      \"version\": \"7.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz\",\n      \"integrity\": \"sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"string-width\": \"^4.2.0\",\n        \"strip-ansi\": \"^6.0.0\",\n        \"wrap-ansi\": \"^7.0.0\"\n      }\n    },\n    \"node_modules/color-convert\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz\",\n      \"integrity\": \"sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-name\": \"~1.1.4\"\n      },\n      \"engines\": {\n        \"node\": \">=7.0.0\"\n      }\n    },\n    \"node_modules/color-name\": {\n      \"version\": \"1.1.4\",\n      \"resolved\": \"https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz\",\n      \"integrity\": \"sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==\",\n      \"dev\": true\n    },\n    \"node_modules/concat-map\": {\n      \"version\": \"0.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz\",\n      \"integrity\": \"sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==\",\n      \"dev\": true\n    },\n    \"node_modules/core-util-is\": {\n      \"version\": \"1.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz\",\n      \"integrity\": \"sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==\",\n      \"dev\": true\n    },\n    \"node_modules/cross-spawn\": {\n      \"version\": \"7.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz\",\n      \"integrity\": \"sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"path-key\": \"^3.1.0\",\n        \"shebang-command\": \"^2.0.0\",\n        \"which\": \"^2.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/debug\": {\n      \"version\": \"4.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/debug/-/debug-4.4.0.tgz\",\n      \"integrity\": \"sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"ms\": \"^2.1.3\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"supports-color\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/decamelize\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz\",\n      \"integrity\": \"sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/decamelize-keys\": {\n      \"version\": \"1.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz\",\n      \"integrity\": \"sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"decamelize\": \"^1.1.0\",\n        \"map-obj\": \"^1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/decamelize-keys/node_modules/decamelize\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz\",\n      \"integrity\": \"sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/decamelize-keys/node_modules/map-obj\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz\",\n      \"integrity\": \"sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/deep-is\": {\n      \"version\": \"0.1.4\",\n      \"resolved\": \"https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz\",\n      \"integrity\": \"sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==\",\n      \"dev\": true\n    },\n    \"node_modules/diff\": {\n      \"version\": \"5.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/diff/-/diff-5.2.0.tgz\",\n      \"integrity\": \"sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==\",\n      \"dev\": true,\n      \"license\": \"BSD-3-Clause\",\n      \"engines\": {\n        \"node\": \">=0.3.1\"\n      }\n    },\n    \"node_modules/dir-glob\": {\n      \"version\": \"3.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz\",\n      \"integrity\": \"sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"path-type\": \"^4.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/doctrine\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz\",\n      \"integrity\": \"sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"esutils\": \"^2.0.2\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0.0\"\n      }\n    },\n    \"node_modules/emoji-regex\": {\n      \"version\": \"8.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n      \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n      \"dev\": true\n    },\n    \"node_modules/enquirer\": {\n      \"version\": \"2.3.6\",\n      \"resolved\": \"https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz\",\n      \"integrity\": \"sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ansi-colors\": \"^4.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8.6\"\n      }\n    },\n    \"node_modules/error-ex\": {\n      \"version\": \"1.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz\",\n      \"integrity\": \"sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"is-arrayish\": \"^0.2.1\"\n      }\n    },\n    \"node_modules/escalade\": {\n      \"version\": \"3.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz\",\n      \"integrity\": \"sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/escape-string-regexp\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz\",\n      \"integrity\": \"sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/eslint\": {\n      \"version\": \"8.35.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz\",\n      \"integrity\": \"sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@eslint/eslintrc\": \"^2.0.0\",\n        \"@eslint/js\": \"8.35.0\",\n        \"@humanwhocodes/config-array\": \"^0.11.8\",\n        \"@humanwhocodes/module-importer\": \"^1.0.1\",\n        \"@nodelib/fs.walk\": \"^1.2.8\",\n        \"ajv\": \"^6.10.0\",\n        \"chalk\": \"^4.0.0\",\n        \"cross-spawn\": \"^7.0.2\",\n        \"debug\": \"^4.3.2\",\n        \"doctrine\": \"^3.0.0\",\n        \"escape-string-regexp\": \"^4.0.0\",\n        \"eslint-scope\": \"^7.1.1\",\n        \"eslint-utils\": \"^3.0.0\",\n        \"eslint-visitor-keys\": \"^3.3.0\",\n        \"espree\": \"^9.4.0\",\n        \"esquery\": \"^1.4.2\",\n        \"esutils\": \"^2.0.2\",\n        \"fast-deep-equal\": \"^3.1.3\",\n        \"file-entry-cache\": \"^6.0.1\",\n        \"find-up\": \"^5.0.0\",\n        \"glob-parent\": \"^6.0.2\",\n        \"globals\": \"^13.19.0\",\n        \"grapheme-splitter\": \"^1.0.4\",\n        \"ignore\": \"^5.2.0\",\n        \"import-fresh\": \"^3.0.0\",\n        \"imurmurhash\": \"^0.1.4\",\n        \"is-glob\": \"^4.0.0\",\n        \"is-path-inside\": \"^3.0.3\",\n        \"js-sdsl\": \"^4.1.4\",\n        \"js-yaml\": \"^4.1.0\",\n        \"json-stable-stringify-without-jsonify\": \"^1.0.1\",\n        \"levn\": \"^0.4.1\",\n        \"lodash.merge\": \"^4.6.2\",\n        \"minimatch\": \"^3.1.2\",\n        \"natural-compare\": \"^1.4.0\",\n        \"optionator\": \"^0.9.1\",\n        \"regexpp\": \"^3.2.0\",\n        \"strip-ansi\": \"^6.0.1\",\n        \"strip-json-comments\": \"^3.1.0\",\n        \"text-table\": \"^0.2.0\"\n      },\n      \"bin\": {\n        \"eslint\": \"bin/eslint.js\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://opencollective.com/eslint\"\n      }\n    },\n    \"node_modules/eslint-config-prettier\": {\n      \"version\": \"7.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz\",\n      \"integrity\": \"sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==\",\n      \"dev\": true,\n      \"bin\": {\n        \"eslint-config-prettier\": \"bin/cli.js\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=7.0.0\"\n      }\n    },\n    \"node_modules/eslint-plugin-es\": {\n      \"version\": \"3.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz\",\n      \"integrity\": \"sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-utils\": \"^2.0.0\",\n        \"regexpp\": \"^3.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8.10.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/mysticatea\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=4.19.1\"\n      }\n    },\n    \"node_modules/eslint-plugin-es/node_modules/eslint-utils\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz\",\n      \"integrity\": \"sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-visitor-keys\": \"^1.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/mysticatea\"\n      }\n    },\n    \"node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz\",\n      \"integrity\": \"sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/eslint-plugin-node\": {\n      \"version\": \"11.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz\",\n      \"integrity\": \"sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-plugin-es\": \"^3.0.0\",\n        \"eslint-utils\": \"^2.0.0\",\n        \"ignore\": \"^5.1.1\",\n        \"minimatch\": \"^3.0.4\",\n        \"resolve\": \"^1.10.1\",\n        \"semver\": \"^6.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8.10.0\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=5.16.0\"\n      }\n    },\n    \"node_modules/eslint-plugin-node/node_modules/eslint-utils\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz\",\n      \"integrity\": \"sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-visitor-keys\": \"^1.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/mysticatea\"\n      }\n    },\n    \"node_modules/eslint-plugin-node/node_modules/eslint-visitor-keys\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz\",\n      \"integrity\": \"sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/eslint-plugin-node/node_modules/semver\": {\n      \"version\": \"6.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/semver/-/semver-6.3.1.tgz\",\n      \"integrity\": \"sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==\",\n      \"dev\": true,\n      \"bin\": {\n        \"semver\": \"bin/semver.js\"\n      }\n    },\n    \"node_modules/eslint-plugin-prettier\": {\n      \"version\": \"3.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz\",\n      \"integrity\": \"sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"prettier-linter-helpers\": \"^1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0.0\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=5.0.0\",\n        \"prettier\": \">=1.13.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"eslint-config-prettier\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/eslint-scope\": {\n      \"version\": \"5.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz\",\n      \"integrity\": \"sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"esrecurse\": \"^4.3.0\",\n        \"estraverse\": \"^4.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8.0.0\"\n      }\n    },\n    \"node_modules/eslint-utils\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz\",\n      \"integrity\": \"sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-visitor-keys\": \"^2.0.0\"\n      },\n      \"engine","infra/experimental/agent-skills/fuzzing-python-expert/SKILL.md":"---\nname: fuzzing-python-expert\ndescription:\n  Use this skill to fuzz open source Python software projects using Atheris.\n---\n\n# Fuzzing Python expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for Python projects integrated into OSS-Fuzz. Python\nfuzzing uses [Atheris](https://github.com/google/atheris), which wraps libFuzzer\nand instruments Python bytecode for coverage-guided fuzzing.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nPython projects must use the Python base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-python\n```\n\nSet `language: python` in `project.yaml`.\n\n### Harness structure\n\nA Python fuzz target is a `.py` file (named `fuzz_<target>.py` by convention)\nthat follows this pattern:\n\n```python\n#!/usr/bin/python3\nimport sys\nimport atheris\n\n# Import the module under test after atheris.instrument_imports() or within\n# the atheris.instrument_all() context so bytecode is instrumented.\n\ndef TestOneInput(data):\n    fdp = atheris.FuzzedDataProvider(data)\n    # Extract typed values from the raw fuzzer bytes.\n    value = fdp.ConsumeString(128)\n    try:\n        my_module.parse(value)\n    except (ValueError, TypeError, KeyError):\n        # Expected exceptions from invalid input are not bugs.\n        pass\n\ndef main():\n    atheris.instrument_all()   # instrument all loaded Python modules\n    atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True)\n    atheris.Fuzz()\n\nif __name__ == \"__main__\":\n    main()\n```\n\n### Instrumenting imports selectively\n\nWhen `instrument_all()` is too broad (e.g. causes conflicts with C extensions),\ninstrument specific modules using the `instrument_imports()` context manager:\n\n```python\nimport atheris\nwith atheris.instrument_imports():\n    import my_module\n    import my_module.subpackage\n```\n\n### FuzzedDataProvider reference\n\n`atheris.FuzzedDataProvider` splits the raw byte stream into typed values:\n\n| Method | Description |\n|---|---|\n| `ConsumeBytes(count)` | `bytes` of length count |\n| `ConsumeByteList(count)` | `list[int]` of length count |\n| `ConsumeString(count)` | decoded `str` (may contain surrogates) |\n| `ConsumeUnicode(count)` | `str` without surrogates |\n| `ConsumeUnicodeNoSurrogates(count)` | strict `str` |\n| `ConsumeInt(nbytes)` | signed int from nbytes |\n| `ConsumeIntInRange(min, max)` | int in range |\n| `ConsumeFloat()` | float |\n| `ConsumeBool()` | bool |\n| `ConsumeIntList(count, nbytes)` | list of ints |\n| `PickValueInList(lst)` | random element |\n| `ConsumeRemainingBytes()` | all remaining bytes |\n\n### Building in OSS-Fuzz\n\n`build.sh` installs the target package and uses the `compile_python_fuzzer`\nhelper to turn each `fuzz_*.py` file into a standalone fuzzer binary in `$OUT`:\n\n```bash\n# build.sh\n\n# Install the package under test.\npip3 install .\n\n# Compile all fuzz targets found in $SRC.\nfor fuzzer in $(find $SRC -name 'fuzz_*.py'); do\n    compile_python_fuzzer \"$fuzzer\"\ndone\n```\n\n`compile_python_fuzzer` handles linking against Atheris and libFuzzer and\nproduces an executable in `$OUT` named after the `.py` file.\n\n### Seed corpus and dictionaries\n\n- Place seed files in `$OUT/<fuzzer_name>_seed_corpus/` or zip them as\n  `$OUT/<fuzzer_name>_seed_corpus.zip`.\n- Dictionaries go to `$OUT/<fuzzer_name>.dict` — especially valuable for\n  text-format parsers (JSON, XML, YAML, CSV, etc.).\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks. See the [structured seed generation\n  reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good Python fuzzing harnesses\n\n1. **Instruments the right modules**: use `instrument_all()` for simplicity or\n   `instrument_imports()` for targeted instrumentation. Without instrumentation\n   coverage guidance is blind.\n2. **Targets attack surface**: parsers, template engines, serialisation\n   (pickle, JSON, YAML, XML), network protocol handling, and any API that\n   accepts untrusted strings or bytes.\n3. **Catches expected exceptions**: wrap target calls in `try/except` for the\n   documented exception types the target raises on bad input. Only unexpected\n   exceptions and hard crashes are findings.\n4. **Uses `FuzzedDataProvider` for structured input** rather than feeding raw\n   bytes directly to APIs that expect text — most Python APIs work on strings,\n   not bytes.\n5. **Avoids importing under test inside `TestOneInput`**: imports should happen\n   at module level (inside the `instrument_imports()` block if used) so they\n   are instrumented and not re-executed per iteration.\n6. **Is fast**: avoid file I/O, network calls, or subprocess invocations inside\n   `TestOneInput`.\n7. **Avoids non-determinism**: no `random`, no `datetime.now()`, no\n   `os.urandom()` inside the fuzz function.\n8. **Enables Python coverage**: pass `enable_python_coverage=True` to\n   `atheris.Setup` for bytecode-level coverage tracking.\n\n## What Python fuzzing finds\n\nPython is memory-safe, so the focus is on:\n\n- **Unhandled exceptions**: `ValueError`, `RecursionError`, `MemoryError`,\n  `UnicodeDecodeError`, and any exception the library should have caught and\n  converted to a clean error.\n- **`AssertionError`**: internal invariant violations triggered by crafted\n  input.\n- **Hangs / infinite loops**: detected by OSS-Fuzz's timeout.\n- **Crashes in C extensions**: Python libraries that wrap C code (e.g. lxml,\n  Pillow, cryptography) can still have memory-corruption bugs in their C layer,\n  which Atheris will surface because libFuzzer runs the whole process.\n- **Logic errors**: incorrect output, silent data corruption, wrong parsing\n  results on edge-case inputs.\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash usually means an exception is being raised on every input.\n  Run the harness locally (`python3 fuzz_target.py`) on a sample input to\n  debug before building through OSS-Fuzz.\n- Test the harness locally before the OSS-Fuzz build:\n  ```python\n  python3 fuzz_target.py <seed_file>\n  ```\n  Atheris supports running in single-input mode outside libFuzzer.\n- Install the package locally (`pip3 install .`) and iterate quickly before\n  going through the Docker build.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- Document why each entry point was chosen and what class of bugs it may find.\n","infra/experimental/agent-skills/oss-fuzz-engineer/SKILL.md":"---\nname: oss-fuzz-engineer\ndescription:\n  Use this skill to interact with the OSS-Fuzz infrastructure.\n---\n\n# OSS-Fuzz engineer\n\nThis skill guides the agent how to use the OSS-Fuzz infrastructure to find and report bugs in open source software. The agent can use this skill to integrate new projects, extend and improve the fuzzing posture of projects, run fuzzing campaigns, and fix broken existing OSS-Fuzz projects.\n\nWhen working on OSS-Fuzz tasks then you should also use any fuzzing related skills you have, such as code analysis and fuzzing harness writing skills, to achieve the best results.\n\n## Workflows\n\nThere are multiple common workflows that an OSS-Fuzz engineer might follow and we describe some imporant ones here.\n\n### Integrating a new project\n\nGiven a reference to an open source project, such as a link to a GitHub repository, the agent can follow these steps to integrate the project into OSS-Fuzz:\n1. **Assess the project**: The agent should first assess whether the project is suitable for fuzzing. This includes checking if the project is open source, has a significant user base, and contains code that can be fuzzed (e.g., C/C++ code).\n2. **Set up the environment**: The agent should set up the necessary environment for fuzzing the project. This includes:\n- A Dockerfile that defines the build environment for the project, using the OSS-Fuzz base images.\n- A build script that compiles the project with the necessary instrumentation for fuzzing.\n- A project.yaml that provides the necessary OSS-Fuzz meta data.\n3. **Write fuzz targets**: The agent should write fuzz targets for the project. Fuzz targets are small programs that call into the project's code and are used by the fuzzing engine to generate inputs and find bugs.\n4. **Test the integration**: The agent should test the integration by running the fuzz targets locally and ensuring that they work correctly. This project should be continue until the fuzz targets build and run well, and the OSS-Fuzz `check_build` script passes without errors.\n5. **Conclude the integration**: Once the integration is complete, the agent should conclude with a message of the results achieved and the next steps the security engineer guiding the agent should take. The agent should *not* make any commits or push anything to GitHub, but should conclude on the work for the security engineer to review. The agent should never submit any changes to OSS-Fuzz's Github.\n\nWhen doing this type of work it's crucial the agent uses any skills it has related to code analysis and fuzzing harness writing.\n\n### Extending and improving fuzzing posture\n\nThe agent can also be used to extend and improve the fuzzing posture of existing OSS-Fuzz projects. This can include:\n- Adding new fuzz targets to cover more code paths and functionality.\n- Improving existing fuzz targets to make them more effective at finding bugs.\n- Updating the build environment to include new dependencies or tools that can enhance fuzzing.\n- Analyzing fuzzing results and identifying areas of the code that are not well covered by existing fuzz targets, and then writing new fuzz targets to cover those areas.\n\nA useful approach for extending a project is to study the latest code coverage report for the project, which is publicly available, to identify areas of the code that are not well covered by existing fuzz targets. The agent can then write new fuzz targets to cover those areas, and test them locally before concluding on the work for the security engineer to review.\n\n**Critical: avoid targeting already-covered code.** The most common mistake when extending an OSS-Fuzz project is writing harnesses that target functions already well-exercised by the existing production fuzzer corpus. Before selecting any target function:\n\n1. Fetch the latest public `summary.json` via the `latest_report_info/<project>.json` pointer (never guess the date). See the [code coverage reference](references/code_coverage.md) for the pointer, the JSON schema, and how to read it.\n2. Parse the per-file metrics. Line % is triage only — use the **functions** metric (which functions are never entered ⇒ a new harness may be needed) and the **regions/branches** metric (reached function, dark branches ⇒ a corpus/seed problem) to decide *what kind* of gap each file has. Relying on line % alone throws away the signals that tell harness-work from seed-work apart.\n3. Build an explicit blocklist of already-covered files (≥ 50% lines with most functions covered) — do NOT write harnesses whose primary target lives in one of these files.\n4. Only select targets from files with genuinely low coverage (< 30% lines hit), and classify the gap with the functions-vs-branches split before acting.\n\nReading the source code and identifying \"important-looking\" functions is not sufficient — important functions are frequently already covered. Coverage data is the authoritative source of truth for what needs work, and Fuzz Introspector (<https://introspector.oss-fuzz.com>) additionally surfaces reachable-but-unfuzzed functions — see the code coverage reference for the full workflow.\n\n**Structured seed generation.** Adding a new harness is not the only way to extend coverage — often the existing harnesses already reach dark code, but the corpus never produces inputs valid enough to enter it. When a target parses a structured format (binary containers, codec/network bitstreams, text grammars), a script that constructs structurally-valid inputs from scratch is frequently the highest-leverage, lowest-review-cost improvement: random bytes rarely pass a parser's early magic/length/checksum checks, so the deep logic stays dark until seeded. Drive this the same coverage-first way: pick reachable files that are dark in `summary.json`, generate seeds that target them, validate each one actually parses, append them to the existing corpora (never replace), and confirm the union does not digress. See the [structured seed generation reference](references/structured_seed_generation.md) for the full workflow, construction techniques, per-fuzzer tailoring, and pitfalls, and `projects/vlc/generate_seeds.py` for a worked example.\n\nUse the local code coverage feature of the `python3 infra/helper.py` tool to generate code coverage reports for fuzz targets locally, for example to validate the code coverage achieved by a new fuzz target. This can be done by running `python3 infra/helper.py introspector --coverage-only PROJECT_NAME` and then studying the generated report in e.g. build/out/PROJECT_NAME/report. Some examples of this include:\n\n```\n# Generate a coverage report for htslib OSS-Fuzz project from running each\n# fuzzer for 30 seconds, and store coverage directory in `htslib-cov-1`.\npython3 infra/helper.py introspector --coverage-only --seconds 30 --out htslib-cov-1 htslib\n\n# Generate a coverage report for leveldb OSS-Fuzz project from running each\n# fuzzer for 45 seconds, and store coverage directory in `leveldb-cov-1`.\npython3 infra/helper.py introspector --coverage-only --seconds 45 --out leveldb-cov-1 leveldb\n```\n\nThe user may provide directions on how to extend the fuzzing, and it's crucial to follow instructions on this matter. For example, the user may ask to focus on a specific area of the code, or to target specific types of vulnerabilities. The agent should always provide a clear explanation of the rationale for each extension or improvement made to the fuzzing posture of the project.\n\nWhen extending an OSS-Fuzz project it's crucial to have a good understanding of the target code. To this end, it's often useful to get a local version of the target source code into the OSS-Fuzz project structure to make working with the target project easy. This involves e.g. studying the `Dockerfile` of the target project, finding the e.g. `git clone` of the target project, and then cloning this repository locally and using e.g. `COPY` instead of `RUN git clone` in the Dockerfile to get the source code into the container.\n\nThe agent should always provide clear technical justification for each extension.\n\nWhen doing this type of work it's crucial the agent uses any skills it has related to code analysis and fuzzing harness writing. It's important each extension is done through a personal assessment of the current fuzzing posture of the project, and a clear explanation of the rationale for each extension or improvement. The agent should never make any commits or push anything to GitHub, but should conclude on the work for the security engineer to review. The agent should never submit any changes to OSS-Fuzz's Github.\n\nIt is crucial when extending existing OSS-Fuzz project you must validate the existing code coverage does not digress. You should empirically evaluate this and give a justification that no digression has happened, or if it has happened then you should give a justification for why the digression is acceptable in light of the achieved extension.\n\nUnless otherwise specified, the agent should focus on improving a single fuzzing harness for the target project, and not focus on making broad changes that will take a long time to review. Simple changes are often more effective than broad large changes.\n\n### Fixing broken existing OSS-Fuzz projects\n\nThe agent can also be used to fix broken existing OSS-Fuzz projects. This can include:\n- Identifying and fixing build issues that prevent fuzz targets from running correctly.\n- Updating dependencies or build scripts to ensure that the project can be fuzzed effectively.\n- Analyzing fuzzing results to identify and fix issues that are causing the fuzzing campaign to fail or produce unreliable results.\n\nA given OSS-Fuzz project must succeed with:\n\n```\npython3 infra/helper.py build_fuzzers PROJECT_NAME\npython3 infra/helper.py check_build PROJECT_NAME\n```\n\nThe agent should never make any commits or push anything to GitHub, but should conclude on the work for the security engineer to review. The agent should never submit any changes to OSS-Fuzz's Github.\n\n\n### Chronos integration\n\nA common task for an OSS-Fuzz engineer is to add Chronos support for a given OSS-Fuzz project.\n\nChronos is a feature of OSS-Fuzz that makes it possible to quickly rebuild OSS-Fuzz projects and run unit tests of a given OSS-Fuzz project. This is used to efficiently validate e.g. patches of a project without having to rebuild the entire target project image.\n\nTo add Chronos support a project needs to have two key scripts:\n\n- replay_build.sh: used to quickly rebuild the project without network access.\n- run_tests.sh: used to run unit tests of the project without network access.\n\nThere are several constraints on these scripts, e.g. no network access, and it's important to always check the infra/chronos/README.md file to understand the specifics.\n\nA given Chronos integration must succeed with:\n\n```sh\npython3 infra/experimental/chronos/manager.py check-replay PROJECT_NAME\npython3 infra/experimental/chronos/manager.py check-tests PROJECT_NAME\n```\n\nThe above two commands must succeed without error, and when integrating a new project these commands must be run before concluding on the work for the security engineer to review.\n\nIn addition to the above, there are some constraints on Chronos worth mentioning:\n- If the tests fail when `run_tests.sh` is run, then `check-tests` *must* fail as well. This is a crucial invariant that is used to validate if wrong patches lead to wrong outcomes, and we must be able to check wrong patches that break tests.\n- The `run_tests.sh` script should leave a given repository in the state it was before the script was run. For example, `git diff` should be the same before and after `run_tests.sh` is run inside the target repository.\n- `run_tests.sh` has no network connection, so if any tests requires network connection then these tests should be skipped in `run_tests.sh` and this should be clearly documented in the script.\n\n\n# Guidelines for working locally on OSS-Fuzz projects\n\n1. Always work from the base folder of the current OSS-Fuzz project unless otherwise specified.\n2. Make a local checkout of the target source code to make working with the target project easy. This involves e.g. studying the `Dockerfile` of the target project, finding the e.g. `git clone` of the target project, and then cloning this repository locally and using e.g. `COPY` instead of `RUN git clone` in the Dockerfile to get the source code into the container.\n3. Use the `python3 infra/helper.py` tool to build and test fuzz targets locally.\n4. Analyse if build scripts can be optimized to improve local building efficiency.\n\n\n# Public data available for OSS-Fuzz projects\n\nThe OSS-Fuzz infrastructure provides a lot of public data that can be used to guide the work of an OSS-Fuzz engineer. This includes:\n\n- Current build status of all OSS-Fuzz projects:\n  - html page: https://oss-fuzz-build-logs.storage.googleapis.com/index.html\n  - json file: https://oss-fuzz-build-logs.storage.googleapis.com/status.json\n  - use this reference to identify latest build status of a given project, and to identify if there are any build issues that need to be fixed.\n  - If you are tasked with fixing the build of a project, then use this data to identify the latest build error.\n  - If you are tasked with fixing the build of a project, then use this data to identify the conditions of the latest build error, e.g. which architecture, fuzzing engine and sanitizer is failing.\n  - Some build errors are due to the harnesses running into an issue immediately, meaning they build but `check_build` fails. These are bugs that likely indicate the fuzzing harnesses have a deficiency.\n- in the references section guidance is provided on code coverage reports, helper script used for interacting with OSS-Fuzz projects and documentation on the structure of OSS-Fuzz projects.\n- https://introspector.oss-fuzz.com : details insights on macro and micro level stats on OSS-Fuzz.","infra/experimental/agent-skills/fuzzing-memory-unsafe-expert/SKILL.md":"---\nname: fuzzing-memory-unsafe-expert\ndescription:\n  Use this skill to fuzz open source C/C++ software projects.\n---\n\n# Fuzzing memory-unsafe expert\n\nThis skill provides the agent with the necessary knowledge and tools to fuzz open source software projects, particularly those that are part of the OSS-Fuzz program. The agent can use this skill to build fuzzers, run fuzzing campaigns, analyze results, and improve the fuzzing posture of projects.\n\nThe fuzzing abilities focused on here is libFuzzer-style harnesses, which are commonly used in OSS-Fuzz.\n\n## Threat modelling and attack surface\n\nBefore writing a single line of harness code, decide **what you are trying to\nfind and where an attacker's input actually enters the code**. A harness is\nonly as good as the entry point it targets: a technically-correct harness\npointed at code no attacker can influence finds bugs no maintainer will fix.\nThis step is what separates a valuable harness from a noisy one.\n\n### What a threat model answers\n\nFor the target project, answer these four questions explicitly and write the\nanswers into the harness's rationale doc:\n\n1. **What input is untrusted?** The data an attacker can control — a file\n   downloaded and opened, bytes arriving on a socket, a message from another\n   process, a document pasted into an editor. Trusted input (a config file the\n   admin wrote, a compile-time constant, a path only the program itself\n   constructs) is *not* an attacker's lever and is usually out of scope.\n2. **Where does that input cross a trust boundary?** The exact function(s)\n   where untrusted bytes first reach parsing/processing logic. This is the\n   entry point your harness should call.\n3. **What does the attacker control at that boundary?** The whole buffer? Only\n   a length field, with the rest validated upstream? A filename but not its\n   contents? This determines what your harness should mutate and what it should\n   hold fixed.\n4. **What would count as a real bug here?** A memory-safety violation (ASan/\n   MSan/UBSan finding) on attacker-reachable input is almost always in scope. A\n   crash that requires trusted/malformed *developer* input, or an\n   `assert()`-guarded programmer-error precondition, usually is not — fuzzing it\n   produces findings maintainers reject.\n\n### Identifying the attack surface\n\nConcrete, common attack surfaces in C/C++ projects, and the entry points to\ntarget for each:\n\n- **File-format parsers / loaders** (image, audio, video, fonts, archives,\n  documents). Entry point: the function that takes a buffer or file and decodes\n  it — e.g. `png_read_info`, `TIFFClientOpen`, `av_read_frame`,\n  `archive_read_open_memory`. Attacker controls the whole file. High-value,\n  classic OSS-Fuzz target.\n- **Network / wire-protocol handlers** (packet parsers, TLS records, HTTP,\n  DNS, RPC deserialisation). Entry point: the function fed raw bytes off the\n  wire, e.g. `SSL_read`, `parse_packet`, `deserialize_message`. Attacker\n  controls the byte stream; often you must also drive a state machine (see the\n  reachability note below).\n- **Serialisation / IPC boundaries** (protobuf/JSON/CBOR/ASN.1 decoders,\n  shared-memory messages, clipboard, environment when spawned by another\n  privilege domain). Entry point: the *decode* direction — the untrusted side\n  is bytes-in, not object-out.\n- **Text / query languages** (SQL, regex, template engines, config-language\n  parsers, expression evaluators). Entry point: the compile/parse function that\n  accepts an arbitrary string.\n- **Decompression and codecs** (zlib, lz4, zstd, JPEG/HEIF bitstreams). Entry\n  point: the decompress/decode call on attacker-supplied compressed data —\n  these are prime targets because a small input expands into large, structured\n  work.\n\n### Deriving the harness from the threat model\n\nThe threat model dictates the harness shape:\n\n- **Target the untrusted-input direction only.** Fuzz the *decoder*, not the\n  encoder; the *reader*, not the writer — unless the writer also consumes\n  attacker-controlled data.\n- **Mutate exactly what the attacker controls; fix the rest.** If the attacker\n  controls a document but not the parser's configuration, mutate the document\n  bytes and hold the config constant (set it once in `LLVMFuzzerInitialize`).\n  Fuzzing the config too invents a threat that does not exist and yields\n  rejected findings.\n- **Enter at the real trust boundary, not below it.** Calling a deep internal\n  helper directly may crash on inputs the public API would have rejected\n  upstream — a false positive. Prefer the outermost function an attacker's data\n  actually reaches. If you must call an internal function for coverage, first\n  confirm the upstream validation it assumes, and reproduce that precondition\n  in the harness.\n- **Honour the API contract to avoid false positives.** If a function is\n  documented to require NUL-terminated input, a valid handle, or a\n  pre-allocated output buffer, supply those — a crash from violating the\n  contract is a harness bug, not a target bug (this is the \"True Positives\"\n  characteristic below).\n\n### Reachability: entry point is not enough\n\nAn entry point that is untrusted-reachable in production may still be\n*unreachable* from your harness if getting to the interesting code requires\nstate the harness never sets up — an open session, a completed handshake, a\nprior header packet, a registered codec. Two consequences:\n\n- If the deep code needs prior state, **build that state in the harness**\n  (e.g. feed a valid header, complete the handshake) before feeding the mutated\n  bytes — otherwise the fuzzer never gets past the front door and coverage\n  stays shallow.\n- Cross-check with the coverage data (see the OSS-Fuzz engineer skill): if a\n  file you believe is attacker-reachable sits dark in `summary.json`, decide\n  whether it is *seed-limited* (a better corpus would reach it — write seeds) or\n  *harness-limited* (no input reaches it as the harness stands — the harness\n  itself must set up more state).\n\n### A worked example\n\nConsider a library that loads a custom image format via\n`int img_load(const uint8_t *buf, size_t len, img_opts *opts)`, where `opts`\ncomes from the application, not the file:\n\n- **Untrusted input:** `buf`/`len` (the image file). **Trusted:** `opts`.\n- **Trust boundary / entry point:** `img_load` — the outermost public function\n  an attacker's bytes reach.\n- **Attacker controls:** the entire image buffer, not the options.\n- **Real bug:** any ASan/UBSan finding decoding a crafted image.\n\nThe harness therefore fixes `opts` to a representative default once, and feeds\nthe mutated bytes as `buf`/`len`:\n\n```cpp\n#include <fuzzer/FuzzedDataProvider.h>\n\nstatic img_opts g_opts;  // trusted config, set once — not fuzzed.\n\nextern \"C\" int LLVMFuzzerInitialize(int *argc, char ***argv) {\n    img_opts_default(&g_opts);   // represents the real application's setup\n    return 0;\n}\n\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {\n    // Attacker controls the whole file; feed it directly.\n    img_load(data, size, &g_opts);\n    return 0;\n}\n```\n\nFuzzing `opts` instead, or calling an internal `decode_scanline` directly with\nraw bytes, would either invent a non-existent threat or trip asserts the public\nAPI prevents — both produce findings maintainers will not act on.\n\n## Fundamental Concepts\n\n### Fuzzing harness core function\n\nA fuzzing harness is a function that takes a byte array as input and processes it in a way that can trigger bugs or vulnerabilities in the software being tested. The core function of a fuzzing harness typically looks like this:\n\n```cpp\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {\n    // Process the input data and trigger potential bugs\n    return 0; // Return 0 to indicate successful processing\n}\n```\n\nReturn `0` in all normal cases. Return `-1` to tell libFuzzer to reject an\ninput and not add it to the corpus (rarely needed). Never `exit()` on bad\ninput — it aborts the whole run and breaks coverage tooling.\n\n### Extracting typed input with FuzzedDataProvider\n\nMost non-trivial targets do not take a single flat byte buffer — they need an\ninteger here, a length there, a string, several sub-buffers. Passing the raw\n`data`/`size` directly to such an API means the fuzzer almost never produces a\nwell-formed call. `FuzzedDataProvider` splits the one input stream into typed\nvalues, so libFuzzer's mutations map onto the parameters the target actually\nexpects. It is the standard tool for this in OSS-Fuzz (used by well over a\nhundred projects) and is shipped in the base image — no dependency to add:\n\n```cpp\n#include <fuzzer/FuzzedDataProvider.h>\n\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {\n    FuzzedDataProvider fdp(data, size);\n\n    // Consume typed, bounded values up front...\n    int         width  = fdp.ConsumeIntegralInRange<int>(1, 4096);\n    bool        strict = fdp.ConsumeBool();\n    std::string name   = fdp.ConsumeRandomLengthString(64);\n    // ...then hand the rest of the bytes to the payload argument.\n    std::vector<uint8_t> payload = fdp.ConsumeRemainingBytes<uint8_t>();\n\n    my_decode(name.c_str(), width, strict, payload.data(), payload.size());\n    return 0;\n}\n```\n\nCommonly used methods (see `compiler-rt`'s `FuzzedDataProvider.h` for the full\nset):\n\n| Method | Description |\n|---|---|\n| `ConsumeIntegral<T>()` | one integer of type `T` |\n| `ConsumeIntegralInRange<T>(min, max)` | integer bounded to `[min, max]` — use this to pick sizes, indices, enum values |\n| `ConsumeBool()` | one boolean |\n| `ConsumeEnum<E>()` | a value of a scoped enum with `kMaxValue` |\n| `ConsumeFloatingPoint<T>()` / `...InRange(min, max)` | float/double |\n| `ConsumeRandomLengthString(max)` | a `std::string` whose length the fuzzer controls (stops at an escaped `\\`) |\n| `ConsumeBytes<T>(count)` / `ConsumeBytesAsString(count)` | exactly `count` bytes |\n| `ConsumeRemainingBytes<T>()` / `ConsumeRemainingBytesAsString()` | everything left |\n| `remaining_bytes()` | how many bytes are left to consume |\n\nGuidance:\n\n- **Consume in a fixed order and document it.** The mapping from bytes to\n  parameters must be stable, or a saved crash will not reproduce.\n- **Consume the variable-length / \"rest of the input\" argument last** with\n  `ConsumeRemaining...`. Consuming a fixed count first and the remainder last\n  keeps the layout robust to mutation.\n- **Bound sizes and indices with `ConsumeIntegralInRange`** rather than masking\n  a raw integer — it wastes fewer inputs and keeps allocations sane.\n- Use FDP when the target needs structure; for a target that genuinely takes\n  one opaque buffer (a single `parse(data, size)`), pass `data`/`size` straight\n  through — FDP would only add noise.\n\n### One-time setup with LLVMFuzzerInitialize\n\nIf the harness needs setup that must happen once before fuzzing (parsing\n`argv`, setting environment variables, initialising a library global), put it\nin the optional `LLVMFuzzerInitialize` hook, which libFuzzer calls once at\nstartup — never do per-input work there:\n\n```cpp\nextern \"C\" int LLVMFuzzerInitialize(int *argc, char ***argv) {\n    setenv(\"HOME\", \"/tmp\", 1);\n    my_library_global_init();\n    return 0;\n}\n```\n\nKeep expensive but per-process-constant state (loaded config, a compiled\nschema, an allocated context reused across inputs) in a file-scope\n`static`/global initialised once — either here or lazily on the first\n`LLVMFuzzerTestOneInput` call — so it is not rebuilt on every iteration.\n\n### Sanitizers are the bug oracle\n\nA C/C++ harness rarely detects a bug by itself — the sanitizer the project is\nbuilt with is what turns silent memory corruption into a crash the fuzzer can\ncatch. OSS-Fuzz builds each target under a sanitizer (default AddressSanitizer;\nalso UndefinedBehaviorSanitizer and MemorySanitizer):\n\n- **ASan** — heap/stack/global buffer overflows, use-after-free, double-free,\n  leaks. The default and highest-value oracle.\n- **UBSan** — signed overflow, invalid shifts, misaligned/`null` pointer use,\n  bad casts, invalid enum values.\n- **MSan** — reads of uninitialised memory. Requires *all* linked code\n  (including dependencies) to be instrumented, or it reports false positives —\n  only enable it when the whole dependency chain is built under MSan.\n\nDesign implication: the harness's job is to *reach* untrusted-input-driven\nmemory operations with enough variety; the sanitizer reports the violation.\n`build.sh` must compile both the target library and the harness with the\nOSS-Fuzz `$CFLAGS`/`$CXXFLAGS` (which carry the sanitizer + coverage flags) —\nlinking against a separately, non-instrumented build silently disables the\noracle and coverage guidance.\n\n### Building in OSS-Fuzz\n\n`build.sh` compiles the project (as a static library where possible) and then\ncompiles + links each harness against it with `$LIB_FUZZING_ENGINE`. Always use\nthe OSS-Fuzz-provided `$CC`/`$CXX` and `$CFLAGS`/`$CXXFLAGS` so instrumentation\nand the sanitizer are applied:\n\n```bash\n# build.sh — build the library with instrumentation, statically.\nmkdir build && cd build\ncmake -DBUILD_SHARED_LIBS=OFF ..     # a static .a is easiest to link the harness against\nmake -j$(nproc)\ncd ..\n\n# Compile and link each harness against the instrumented library.\nfor f in $SRC/project/fuzz/*_fuzzer.cc; do\n    fuzzer=$(basename \"$f\" _fuzzer.cc)\n    $CXX $CXXFLAGS -std=c++17 -I$SRC/project/include \\\n        \"$f\" -o \"$OUT/${fuzzer}\" \\\n        $LIB_FUZZING_ENGINE \"$SRC/project/build/libproject.a\"\ndone\n```\n\nKey points:\n\n- Link the harness with **`$LIB_FUZZING_ENGINE`**, not a hardcoded\n  `-fsanitize=fuzzer` — this lets OSS-Fuzz swap the engine (libFuzzer, AFL++,\n  Centipede, or the coverage/`check_build` no-op engine).\n- Prefer a **static** project build; it avoids `LD_LIBRARY_PATH` juggling at\n  run time and ensures the linked code is instrumented.\n- Copy seed corpora (`$OUT/<fuzzer>_seed_corpus.zip`) and dictionaries\n  (`$OUT/<fuzzer>.dict`) in the same script.\n\n### Examples of good harnesses already in OSS-Fuzz\n\nStudy existing harnesses before writing your own — they show the idioms above\napplied to real projects, and matching an established style makes your harness\neasier for maintainers to accept. Each example below is checked into this\nrepository; open the file and read it in full.\n\n- **`projects/sentencepiece/sample_encode_fuzzer.cc`** — the canonical\n  `FuzzedDataProvider` split. It carves the one input into an `int`\n  (`ConsumeIntegral`), a `float` (`ConsumeFloatingPoint`) and the remaining\n  bytes as the text argument (`ConsumeRemainingBytesAsString`), then calls\n  `SampleEncodeAsSerializedProto(text, nbest, alpha)`. Note the ordering: the\n  fixed-size scalars are consumed first and the variable-length string last.\n  This is the template whenever the target API takes several typed parameters\n  rather than one buffer.\n\n- **`projects/spdlog/fuzz/pattern_fuzzer.cc`** — lazy one-time initialisation\n  and a tightly-scoped threat model. A `static` logger is created on the first\n  call and reused across iterations (never rebuilt per input), it guards\n  `size == 0`, and it fuzzes exactly one attacker-relevant entry point:\n  `spdlog::set_pattern(str)`, the format-pattern parser. It does *not* fuzz the\n  logging config — a clean example of \"mutate only what the attacker controls.\"\n\n- **`projects/file/magic_fuzzer_fd.cc`** — `LLVMFuzzerInitialize` for expensive\n  setup, and feeding an API that needs a real file descriptor. The magic\n  database is loaded once in an `Environment` built from `argv[0]`'s directory\n  (setup that must not repeat per input), and each input is written to a\n  `FuzzerTemporaryFile` so it can be handed to `magic_descriptor(fd)`. Use this\n  pattern when the target only accepts a path/`fd` rather than an in-memory\n  buffer — but note that going through a temp file is slower, so prefer an\n  in-memory entry point when the library exposes one.\n\nWhen extending an existing OSS-Fuzz project, the best reference is that\nproject's *own* existing harnesses: match their file layout, naming\n(`*_fuzzer.cc`), build-script wiring and error-handling conventions.\n\n### Characteristics found in good fuzzing harnesses\n\nThe below are characteristics commonly found in good fuzzing harnesses, which contribute to their effectiveness in finding bugs. They are not all necessary for a good harness and at times it may even be desirable to actively not pursue some of them.\n\n1. **Simplicity**: The harness should be simple and focused on processing the input data without unnecessary complexity.\n2. **Coverage**: The harness should aim to cover as much of the codebase as possible, including edge cases and error handling paths.\n3. **Determinism**: The harness should produce consistent results for the same input, allowing for reliable reproduction of bugs.\n4. **Performance**: The harness should be efficient in processing inputs to maximize the number of test cases that can be executed in a given time frame.\n5. **Error Handling**: The harness should include robust error handling to capture and report any issues that arise during fuzzing.\n6. **True Positives**: The harness should be designed to have no false positives, ensuring that reported issues are genuine bugs. This means all issues found by the fuzzer is something the maintainers are interested in fixing.\n7. **Matches threat model**: The harness should be designed to target specific types of vulnerabilities that are relevant to the project being fuzzed.\n8. **Hits code on the attack surface**: The harness should be designed to target code that is exposed to untrusted input, such as network interfaces, file parsers, or APIs.\n9. **Enough entropy**: The harness should be designed to allow for a wide range of inputs, providing enough variability to trigger different code paths and potential bugs.\n10. **Follows the code structure**: The harness should be designed to follow the structure of the codebase, making it easier to identify and target specific areas of interest.\n11. **Follows code conventions**: The harness should follow the coding conventions of the project, making it easier for maintainers to understand and integrate the harness into the codebase.\n12. **Does not get stuck**: The harness should be designed to avoid getting stuck on certain inputs or code paths, allowing the fuzzer to continue exploring other areas of the codebase.\n13. **Includes dictionary**: The harness should include a dictionary of known inputs or patterns that are relevant to the project, helping the fuzzer to generate more effective test cases.\n\n### Operational guidelines\n\n- Always build and run fuzzing harnesses to validate they work. This can for example be done in a oss-fuzz environment:\n\n```\npython3 infra/helper.py build_fuzzers <project_name>\npython3 infra/helper.py run_fuzzer <project_name> <fuzzer_name> -- -max_total_time=30 # run the fuzzer for 30 seconds to validate it works\npython3 infra/helper.py check_build <project_name>\n```\n\n- If a fuzzer runs into a crash instantly, it's very likely wrong.\n- Always document the rationale for design decisions in the fuzzing harness, and the rationale for why the harness is expected to find bugs. This can be done in a markdown file in the same directory as the fuzzing harness, or in comments in the code of the fuzzing harness itself.\n- Look for function entrypoints that are exposed to untrusted input, and try to design fuzzing harnesses that target these entrypoints. This is often the most effective way to find security bugs.\n- When extending existing fuzzing harnesses, always validate that the existing code coverage does not digress. You should empirically evaluate this and give a justification that no digression has happened, or if it has happened then you should give a justification for why the digression is acceptable in light of the achieved extension.\n- When extending fuzzing harnesses you should give justification for the impact of bugs that they will find.\n\n### Seed corpus and structured generation\n\nA good harness needs a good initial corpus. Place seed files in\n`$OUT/<fuzzer_name>_seed_corpus.zip` and dictionaries in\n`$OUT/<fuzzer_name>.dict`.\n\nFor targets that parse a structured format (binary containers like ELF/PE, or\ncodec/network bitstreams, or text grammars), a few hand-picked sample files\nare rarely enough: random mutation almost never gets past the parser's magic /\nlength / checksum checks, so the deep parsing code stays dark. The most\neffective approach is a **script that constructs structurally-valid inputs\nfrom scratch**, run from `build.sh` and appended to the corpus. It is\nreproducible, needs no external samples, and lets you target specific\ndark-but-reachable code identified from coverage. See the OSS-Fuzz engineer\nskill's [structured seed generation\nreference](../oss-fuzz-engineer/references/structured_seed_generation.md) for\nthe full workflow and `projects/vlc/generate_seeds.py` for a worked example.","tools/vscode-extension/.vscode/extensions.json":"# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/extensions.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/extensions.json)","tools/vscode-extension/.vscode/launch.json":"# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/launch.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/launch.json)","tools/vscode-extension/.vscode/settings.json":"# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/settings.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/settings.json)","tools/vscode-extension/.vscode/tasks.json":"# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/tasks.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/tasks.json)","infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md":"# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md)","infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md":"# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md)","infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md":"# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md)","infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md":"# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md)"},"files":{"infra/experimental/agent-skills/fuzzing-jvm-expert/SKILL.md":"---\nname: fuzzing-jvm-expert\ndescription:\n  Use this skill to fuzz open source JVM projects (Java, Kotlin, Scala, etc.)\n  using Jazzer.\n---\n\n# Fuzzing JVM expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for JVM-based projects (Java, Kotlin, Scala, Groovy)\nintegrated into OSS-Fuzz. JVM fuzzing uses\n[Jazzer](https://github.com/CodeIntelligenceTesting/jazzer), which wraps\nlibFuzzer and instruments JVM bytecode for coverage guidance.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nJVM projects must use the JVM base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-jvm\n```\n\nSet `language: jvm` in `project.yaml`.\n\n### Harness structure — raw bytes\n\nThe simplest Jazzer harness receives raw bytes via `fuzzerTestOneInput`:\n\n```java\nimport com.code_intelligence.jazzer.api.FuzzedDataProvider;\n\npublic class MyTargetFuzzer {\n    public static void fuzzerTestOneInput(byte[] data) {\n        try {\n            MyLibrary.parse(data);\n        } catch (ExpectedExceptionType e) {\n            // Ignore expected exceptions; they are not bugs.\n        }\n    }\n}\n```\n\n### Harness structure — typed input via FuzzedDataProvider\n\n`FuzzedDataProvider` splits the raw byte stream into typed values, which is\nessential for targets that require structured input:\n\n```java\nimport com.code_intelligence.jazzer.api.FuzzedDataProvider;\n\npublic class MyTargetFuzzer {\n    public static void fuzzerTestOneInput(FuzzedDataProvider data) {\n        String header    = data.consumeString(64);\n        int    version   = data.consumeInt();\n        byte[] payload   = data.consumeRemainingAsBytes();\n\n        try {\n            MyLibrary.process(header, version, payload);\n        } catch (IllegalArgumentException | IOException e) {\n            // Expected — not a finding.\n        }\n    }\n}\n```\n\nUseful `FuzzedDataProvider` methods:\n\n| Method | Description |\n|---|---|\n| `consumeBytes(n)` | `byte[]` of length n |\n| `consumeRemainingAsBytes()` | all remaining bytes |\n| `consumeString(maxLen)` | arbitrary String |\n| `consumeAsciiString(maxLen)` | ASCII-only String |\n| `consumeInt()` / `consumeInt(min, max)` | int |\n| `consumeLong()` | long |\n| `consumeBoolean()` | boolean |\n| `consumeDouble()` | double |\n| `pickValue(collection)` | random element |\n\n### One-time setup with `fuzzerInitialize`\n\nIf initialisation is expensive (loading config, creating DB connections, etc.),\nput it in an optional static method that Jazzer calls once before fuzzing:\n\n```java\npublic class MyTargetFuzzer {\n    private static MyClient client;\n\n    public static void fuzzerInitialize() {\n        client = new MyClient(/* static config */);\n    }\n\n    public static void fuzzerTestOneInput(FuzzedDataProvider data) {\n        client.process(data.consumeRemainingAsBytes());\n    }\n}\n```\n\n### Building in OSS-Fuzz\n\nThe `build.sh` pattern for Maven projects:\n\n```bash\n# Build the project JARs.\n$MVN package -DskipTests -Dmaven.javadoc.skip=true\n\n# Collect JARs needed at runtime.\nALL_JARS=\"mylib-1.0.jar\"\nBUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- \"$OUT/%s:\"):$JAZZER_API_PATH\nRUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- \"\\$this_dir/%s:\"):\\$this_dir\n\nfor fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do\n    fuzzer_basename=$(basename -s .java \"$fuzzer\")\n    javac -cp $BUILD_CLASSPATH \"$fuzzer\"\n    cp $SRC/$fuzzer_basename.class $OUT/\n\n    # Wrapper script that launches jazzer_driver with the right arguments.\n    echo \"#!/bin/bash\nthis_dir=\\$(dirname \\\"\\$0\\\")\nif [[ \\\"\\$@\\\" =~ (^| )-runs=[0-9]+($| ) ]]; then\n  mem_settings='-Xmx1900m:-Xss900k'\nelse\n  mem_settings='-Xmx2048m:-Xss1024k'\nfi\nLD_LIBRARY_PATH=\\\"$JVM_LD_LIBRARY_PATH\\\":\\$this_dir \\\\\n\\$this_dir/jazzer_driver --agent_path=\\$this_dir/jazzer_agent_deploy.jar \\\\\n--instrumentation_includes=com.example.** \\\\\n--cp=$RUNTIME_CLASSPATH \\\\\n--target_class=$fuzzer_basename \\\\\n--jvm_args=\\\"\\$mem_settings\\\" \\\\\n\\$@\" > $OUT/$fuzzer_basename\n    chmod u+x $OUT/$fuzzer_basename\ndone\n```\n\nFor Gradle projects replace `$MVN package` with the appropriate Gradle command\nand adjust JAR paths accordingly.\n\n### Seed corpus and dictionaries\n\n- Zip seed files to `$OUT/<fuzzer_name>_seed_corpus.zip`.\n- Place dictionaries at `$OUT/<fuzzer_name>.dict`.\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks. See the [structured seed generation\n  reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good JVM fuzzing harnesses\n\n1. **Targets attack surface**: parsers, deserializers (JSON, XML, Protobuf,\n   custom binary formats), network protocol handlers, template engines, and\n   any API that accepts untrusted bytes or strings.\n2. **Catches expected exceptions**: wrap calls in `try/catch` for all\n   documented exception types. Only unexpected exceptions and crashes are\n   findings.\n3. **Uses `FuzzedDataProvider`** for structured input rather than passing raw\n   bytes to methods that expect well-formed data.\n4. **Initialises heavy state in `fuzzerInitialize`**: client connections,\n   parsers with complex configuration, and loaded schemas should be set up once.\n5. **Avoids non-determinism**: no `Math.random()`, no `System.currentTimeMillis()`\n   in the fuzzing path, no thread spawning.\n6. **Sets `--instrumentation_includes`** to the package prefix of the target\n   library in the wrapper script — without this Jazzer cannot guide fuzzing.\n7. **Configures JVM memory appropriately**: use the `mem_settings` pattern\n   shown above to avoid OOM kills during runs vs. crash reproduction.\n8. **Avoids false positives**: `OutOfMemoryError`, `StackOverflowError`, and\n   `NullPointerException` on invalid input are usually expected — decide which\n   are genuine bugs for this project.\n\n## What JVM fuzzing finds\n\n- **Unexpected exceptions**: `NullPointerException`, `ArrayIndexOutOfBoundsException`,\n  `ClassCastException`, `NumberFormatException` on paths that should not throw.\n- **Assertion errors and contract violations**: internal consistency checks\n  that fail on adversarial input.\n- **Hang / infinite loops**: detected by OSS-Fuzz's timeout.\n- **Security bugs**: deserialization gadgets, path traversal via crafted\n  filenames, SSRF via crafted URLs — depends on the library.\n- **Logic bugs**: incorrect output for valid-ish input.\n\nJazzer can also detect:\n- SQL injection (via JDBC hooks)\n- Path traversal (via file API hooks)\n- Command injection (via `Runtime.exec` hooks)\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash usually means a missing JAR on the classpath or an\n  uncaught expected exception — check `check_build` output carefully.\n- Build the project outside the fuzzing harness first (`mvn package` or\n  `gradle build`) to ensure the project itself compiles cleanly.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- Document why each entry point was chosen and what class of bugs it may find.\n","infra/experimental/agent-skills/fuzzing-go-expert/SKILL.md":"---\nname: fuzzing-go-expert\ndescription:\n  Use this skill to fuzz open source Go software projects.\n---\n\n# Fuzzing Go expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for Go projects integrated into OSS-Fuzz. Go fuzzing uses\nthe native Go fuzzing framework introduced in Go 1.18, which OSS-Fuzz drives\nvia libFuzzer under the hood using `compile_native_go_fuzzer`.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nGo projects must use the Go base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-go\n```\n\nSet `language: go` in `project.yaml`.\n\n### Harness structure\n\nGo fuzz targets are standard Go test functions with the prefix `Fuzz`, placed\nin `_test.go` files (or plain `.go` files that import the testing package):\n\n```go\npackage mypkg\n\nimport (\n    \"testing\"\n    _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\" // required for OSS-Fuzz native fuzzing\n)\n\nfunc FuzzMyTarget(f *testing.F) {\n    // Seed corpus: add representative valid inputs so the fuzzer starts\n    // from a meaningful state rather than empty bytes.\n    f.Add([]byte(\"example input\"))\n    f.Add([]byte(\"another seed\"))\n\n    f.Fuzz(func(t *testing.T, data []byte) {\n        // Call into the target. Ignore expected errors; let unexpected\n        // panics surface as findings.\n        _, _ = ParseSomething(data)\n    })\n}\n```\n\nThe inner `f.Fuzz` callback signature can use typed parameters instead of\n`[]byte` when the target expects structured input:\n\n```go\nf.Fuzz(func(t *testing.T, s string, n int, b bool) {\n    _ = ProcessRecord(s, n, b)\n})\n```\n\n### Building in OSS-Fuzz\n\nUse the `compile_native_go_fuzzer` helper in `build.sh`. It takes the package\nimport path, the function name, and the output binary name:\n\n```bash\n# build.sh\ncp $SRC/fuzz_test.go ./          # copy harness into the module if needed\nprintf \"package mypkg\\nimport _ \\\"github.com/AdamKorcz/go-118-fuzz-build/testing\\\"\\n\" \\\n    > register.go                # required registration shim\ngo mod tidy\ncompile_native_go_fuzzer github.com/owner/repo/pkg FuzzMyTarget fuzz_my_target\n```\n\nFor projects with multiple packages or multiple fuzz targets repeat the call:\n\n```bash\ncompile_native_go_fuzzer github.com/owner/repo/pkg1 FuzzFoo fuzz_foo\ncompile_native_go_fuzzer github.com/owner/repo/pkg2 FuzzBar fuzz_bar\n```\n\n### Seed corpus and dictionaries\n\n- Seed corpus entries go in `$OUT/<fuzzer_name>_seed_corpus/` as individual\n  files, or as a zip at `$OUT/<fuzzer_name>_seed_corpus.zip`.\n- Dictionaries go in `$OUT/<fuzzer_name>.dict` as plaintext token files.\n- Alternatively, add seeds directly via `f.Add(...)` in the harness — these\n  are compiled in and used as the initial corpus.\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks. See the [structured seed generation\n  reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good Go fuzzing harnesses\n\n1. **Targets attack surface**: focus on parsers, decoders, protocol handlers,\n   serialisation/deserialisation, and any API that accepts untrusted bytes or\n   strings.\n2. **Handles expected errors gracefully**: wrap calls in error checks and ignore\n   expected error returns. Only genuine panics and unexpected behaviour are\n   findings.\n3. **Uses typed fuzz parameters** when the target is not purely byte-oriented —\n   Go's fuzzer can mutate `string`, `int`, `bool`, `float64`, etc. directly.\n4. **Avoids non-determinism**: do not use random sources, time, goroutines, or\n   global state that persists between calls.\n5. **Keeps the callback fast**: expensive setup (e.g. parsing config, opening\n   files) belongs outside `f.Fuzz(...)`, not inside the inner function.\n6. **Provides meaningful seeds**: `f.Add(...)` entries should be valid\n   representative inputs so coverage grows from the start.\n7. **Does not get stuck**: avoid code paths that busy-loop or block on I/O\n   inside the fuzz function.\n8. **Includes the registration shim**: the `import _\n   \"github.com/AdamKorcz/go-118-fuzz-build/testing\"` blank import is required\n   for OSS-Fuzz to hook into native Go fuzzing — never omit it.\n\n## What Go fuzzing finds\n\nGo is memory-safe, so the focus shifts from memory-corruption bugs to:\n\n- **Panics**: index out of range, nil pointer dereference, type assertion\n  failures, stack overflows — any unrecovered `panic` is a crash.\n- **Logic bugs**: incorrect parsing, silent data corruption, wrong output for\n  valid input.\n- **Infinite loops / hangs**: code that never returns on certain inputs\n  (detected by OSS-Fuzz's timeout).\n- **Incorrect error handling**: code that should return an error but panics\n  instead, or vice versa.\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash almost always means the harness itself is wrong (e.g.\n  missing error handling, bad seed, wrong package path).\n- Run `go vet ./...` and `go build ./...` inside the module before wrapping in\n  an OSS-Fuzz build to catch compile errors early.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- Document why each entry point was chosen and what class of bugs it may find.\n","infra/experimental/agent-skills/fuzzing-rust-expert/SKILL.md":"---\nname: fuzzing-rust-expert\ndescription:\n  Use this skill to fuzz open source Rust software projects.\n---\n\n# Fuzzing Rust expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for Rust projects integrated into OSS-Fuzz. Rust fuzzing\nuses cargo-fuzz with the `libfuzzer_sys` crate, which drives libFuzzer.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nRust projects must use the Rust base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-rust\n```\n\nSet `language: rust` in `project.yaml`.\n\n### Harness structure\n\nRust fuzz targets live in `fuzz/fuzz_targets/<name>.rs` within the crate being\nfuzzed. The minimal harness using raw bytes:\n\n```rust\n#![no_main]\nuse libfuzzer_sys::fuzz_target;\n\nfuzz_target!(|data: &[u8]| {\n    // Call into the target. The fuzzer will mutate `data` on every iteration.\n    let _ = my_crate::parse(data);\n});\n```\n\nFor structured fuzzing using the `arbitrary` crate (preferred when the target\nexpects typed input):\n\n```rust\n#![no_main]\nuse libfuzzer_sys::fuzz_target;\nuse arbitrary::Arbitrary;\n\n#[derive(Debug, Arbitrary)]\nstruct MyInput {\n    header: u8,\n    payload: Vec<u8>,\n    flags: u32,\n}\n\nfuzz_target!(|input: MyInput| {\n    let _ = my_crate::process(input.header, &input.payload, input.flags);\n});\n```\n\nThe `Cargo.toml` for the fuzz directory must declare dependencies:\n\n```toml\n# fuzz/Cargo.toml\n[package]\nname = \"my-crate-fuzz\"\nversion = \"0.0.0\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nlibfuzzer-sys = \"0.4\"\narbitrary = { version = \"1\", features = [\"derive\"] }   # only if using structured fuzzing\n\n[dependencies.my-crate]\npath = \"..\"\n\n[[bin]]\nname = \"fuzz_target_name\"\npath = \"fuzz_targets/fuzz_target_name.rs\"\ntest = false\ndoc = false\n```\n\n### Building in OSS-Fuzz\n\n`build.sh` uses `cargo fuzz build` and then copies binaries to `$OUT`:\n\n```bash\n# build.sh\ncd $SRC/<crate-dir>\ncargo fuzz build -O   # -O enables release optimisations; important for performance\n\nFUZZ_TARGET_OUTPUT_DIR=$SRC/<crate-dir>/target/x86_64-unknown-linux-gnu/release\nfor f in fuzz/fuzz_targets/*.rs; do\n    name=$(basename \"${f%.*}\")\n    cp \"$FUZZ_TARGET_OUTPUT_DIR/$name\" \"$OUT/\"\ndone\n```\n\nIf the project requires a nightly toolchain, set it in the Dockerfile:\n\n```dockerfile\nENV RUSTUP_TOOLCHAIN=nightly\n```\n\nOr pin to a specific nightly for reproducibility:\n\n```dockerfile\nENV RUSTUP_TOOLCHAIN=nightly-2025-07-03\n```\n\n### Seed corpus and dictionaries\n\n- Place seed files in `fuzz/corpus/<target_name>/` within the repo; they are\n  automatically picked up by cargo-fuzz and can be zipped for OSS-Fuzz.\n- To ship a corpus with OSS-Fuzz copy a zip to `$OUT/<target_name>_seed_corpus.zip`.\n- Dictionaries go to `$OUT/<target_name>.dict`.\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks (note: cargo-fuzz's `arbitrary` is the better route when the\n  target takes typed data rather than a byte format). See the [structured seed\n  generation reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good Rust fuzzing harnesses\n\n1. **Targets attack surface**: parsers, deserializers, protocol implementations,\n   unsafe blocks, and any API that processes untrusted bytes.\n2. **Uses structured fuzzing** (`arbitrary`) when the target expects typed data\n   rather than raw bytes — this dramatically improves coverage.\n3. **Handles expected errors**: `Result` and `Option` should be let-bound and\n   ignored (`let _ = ...`). Only actual panics are findings.\n4. **Avoids panicking on every input**: do not use `.unwrap()` or `.expect()`\n   on fallible operations driven by fuzz input — these create false positives.\n5. **Avoids non-determinism**: no `rand`, no system time, no thread spawning\n   inside the fuzz callback.\n6. **Is fast**: avoid I/O, heavy allocations, or expensive setup inside the\n   callback; do those outside the `fuzz_target!` macro if needed with\n   `LazyLock` / `OnceLock`.\n7. **Considers `unsafe` code**: if the crate has `unsafe` blocks, write\n   harnesses that exercise those paths — this is where memory bugs can still\n   occur in Rust.\n8. **Builds in release mode** (`-O`): fuzzing in debug mode is much slower.\n\n## What Rust fuzzing finds\n\nRust's ownership model prevents most memory-corruption bugs, but fuzzing still\nfinds:\n\n- **Panics**: `unwrap`/`expect` on `None`/`Err`, index out of bounds,\n  arithmetic overflow in debug mode, explicit `panic!` calls.\n- **`unsafe` bugs**: use-after-free, out-of-bounds reads/writes, undefined\n  behaviour in `unsafe` blocks — these are real memory bugs.\n- **Logic errors**: incorrect parsing, data corruption, wrong output.\n- **Hangs**: infinite loops triggered by crafted input.\n- **Stack overflows**: deep recursion on adversarial input.\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash usually means a `panic!` on every input — check for\n  `.unwrap()` calls on fuzz-driven paths and replace with `if let` or `?`.\n- Run `cargo build` and `cargo test` inside the crate before adding the fuzz\n  harness to catch pre-existing compilation errors.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- If the crate uses `no_std`, use `libfuzzer-sys`'s `no_std` feature and ensure\n  the harness does not rely on `std`.\n- Document why each entry point was chosen and what class of bugs it may find.\n","tools/vscode-extension/.eslintrc.json":"{\n  \"extends\": \"./node_modules/gts/\"\n}\n","AGENTS.md":"* Use python3 infra/helper.py to build projects and run fuzzers.\n* If doing development on infra/ you should use a venv and if it doesn't already exist, install deps from infra/ci/requirements.txt build/functions/requirements.txt with pip.\n* If doing development on infra/ run python infra/presubmit.py to format, lint and run tests.\n","tools/vscode-extension/README.md":"# OSS-Fuzz VSCode extension\n\n[OSS-Fuzz](https://github.com/google/oss-fuzz) is a fuzzing toolkit and service for fuzzing open source projects. This VSCode extension provides features and capabilities for interacting with the OSS-Fuzz toolkit and also to compare local changes to the OSS-Fuzz cloud database by way of [Open source fuzz introspection](https://introspector.oss-fuzz.com).\n\n## Features\n\nThe VSCode extension is largely driven by commands at this point. The featues of these commands includes:\n\n- Easily setting up OSS-Fuzz\n- Templates for easily setting up a new OSS-Fuzz project\n- Building arbitrary projects from OSS-Fuzz\n- Modify a project from VSCode and test changes in OSS-Fuzz\n- Easily extract code coverage of fuzzers, including local-only fuzzers\n- Compare local code coverage to what is currently achieved by OSS-Fuzz\n- Auto-generation of fuzzer templates\n\nFor a full list of commands and their features, please check the commands page.","tools/vscode-extension/package.json":"{\n  \"name\": \"OSS-Fuzz\",\n  \"displayName\": \"OSS-Fuzz\",\n  \"description\": \"\",\n  \"version\": \"0.0.5\",\n  \"publisher\": \"OSS-FuzzMaintainers\",\n  \"icon\": \"images/thumbnail.png\",\n  \"engines\": {\n    \"vscode\": \"^1.76.0\"\n  },\n  \"repository\": \"https://github.com/google/oss-fuzz\",\n  \"categories\": [\n    \"Other\"\n  ],\n  \"extensionDependencies\": [\n    \"mindaro-dev.file-downloader\"\n  ],\n  \"activationEvents\": [],\n  \"main\": \"./build/src/extension.js\",\n  \"contributes\": {\n    \"configurations\": [\n      {\n        \"id\": \"OSS-Fuzz-Base\",\n        \"title\": \"Base path to OSS-Fuzz\",\n        \"properties\": {\n          \"oss-fuzz.OSS.Path\": {\n            \"type\": \"string\"\n          }\n        }\n      }\n    ],\n    \"viewsWelcome\": [\n      {\n        \"view\": \"workbench.explorer.emptyView\",\n        \"contents\": \"You can have paragraphs of text here. You can have [links](https://code.visualstudio.com) to external sources or [internal commands](command:welcome-view-content-sample.hello).\\nUse new lines to have new paragraphs.\\nPlace a link alone in a paragraph to make it a button\\n[Hello](command:welcome-view-content-sample.hello)\"\n      }\n    ],\n    \"commands\": [\n      {\n        \"command\": \"oss-fuzz.SetUp\",\n        \"title\": \"OSS-Fuzz: Set Up OSS-Fuzz\",\n        \"description\": \"Downloads the OSS-Fuzz repository and places it under /tmp/oss-fuzz. This will then be the OSS-Fuzz repository used by vscode.\"\n      },\n      {\n        \"command\": \"oss-fuzz.RunFuzzer\",\n        \"title\": \"OSS-Fuzz: Run Fuzzer\",\n        \"description\": \"Runs a single fuzzer from a given project. The fuzzer must already be build, meaning the project should be build first.\"\n      },\n      {\n        \"command\": \"oss-fuzz.ListFuzzers\",\n        \"title\": \"OSS-Fuzz: List Fuzzers\",\n        \"description\": \"Lists the fuzzers built for a given project. The project must be build first.\"\n      },\n      {\n        \"command\": \"oss-fuzz.GetCodeCoverage\",\n        \"title\": \"OSS-Fuzz: Display Code Coverage (Python only)\",\n        \"description\": \"Downloads the latest code coverage from OSS-Fuzz's cloud data (can find at https://introspector.oss-fuzz.com).\"\n      },\n      {\n        \"command\": \"oss-fuzz.ClearCodeCoverage\",\n        \"title\": \"OSS-Fuzz: Clear Code Coverage\",\n        \"description\": \"Clears code coverage visualization in the editor.\"\n      },\n      {\n        \"command\": \"oss-fuzz.CreateOSSFuzzSetup\",\n        \"title\": \"OSS-Fuzz: Initialize OSS-Fuzz Set Up\",\n        \"description\": \"Creates the relevant files using templates to set up an OSS-Fuzz project. Uses minor heuristics e.g. detection of language.\"\n      },\n      {\n        \"command\": \"oss-fuzz.WSBuildFuzzers\",\n        \"title\": \"OSS-Fuzz: Build Fuzzers In Workspace\",\n        \"description\": \"Builds the fuzzers from the project in the current VSCode workspace.\"\n      },\n      {\n        \"command\": \"oss-fuzz.SetupCIFuzz\",\n        \"title\": \"OSS-Fuzz: Set up CIFuzz\",\n        \"description\": \"Creates the files necessary for a CIFuzz set up.\"\n      },\n      {\n        \"command\": \"oss-fuzz.testFuzzer\",\n        \"title\": \"OSS-Fuzz: Test Specific Fuzzer\",\n        \"description\": \"Tests if a given fuzzer works by running it for 10 seconds.\"\n      },\n      {\n        \"command\": \"oss-fuzz.testCodeCoverage\",\n        \"title\": \"OSS-Fuzz: End-To-End Code Coverage Generation\",\n        \"description\": \"Builds the fuzzers in a ASAN mode for a project, collects corpus using the ASAN fuzzers and then generates an HTLM code coverage report using the generated corpus.\"\n      },\n      {\n        \"command\": \"oss-fuzz.Redo\",\n        \"title\": \"OSS-Fuzz: Redo Previous Command\",\n        \"description\": \"Performs the exact same command as the most recent one. Will provide the same input to the command as the previous one. This is efficient when e.g. continuously generating code coverage reports while working on improving a fuzzing set up.\"\n      },\n      {\n        \"command\": \"oss-fuzz.Template\",\n        \"title\": \"OSS-Fuzz: Fuzzer Creation Using Templates\",\n        \"description\": \"Creates a template fuzzer file using a catalogue of templates available.\"\n      },\n      {\n        \"command\": \"oss-fuzz.GenerateClusterfuzzLite\",\n        \"title\": \"OSS-Fuzz: [CFLite] Generate ClusterfuzzLite setup\",\n        \"description\": \"Creates the files needed for ClusterfuzzLite integration.\"\n      },\n      {\n        \"command\": \"oss-fuzz.WSBuildFuzzersCFLite\",\n        \"title\": \"OSS-Fuzz: [CFLite] Build Fuzzers In Workspace\",\n        \"description\": \"Builds the ClusterfuzzLite fuzzers from the project in the current VSCode workspace.\"\n      },\n      {\n        \"command\": \"oss-fuzz.testFuzzerCFLite\",\n        \"title\": \"OSS-Fuzz: [CFLite] Test running a specific fuzzer.\",\n        \"description\": \"Builds the CFLite setup and runs a fuzzer for a short period of time.\"\n      },\n      {\n        \"command\": \"oss-fuzz.setupFuzzIntrospector\",\n        \"title\": \"OSS-Fuzz: Set up Fuzz Introspector\",\n        \"description\": \"Install fuzz introspector on the system\"\n      },\n      {\n        \"command\": \"oss-fuzz.runFuzzIntrospector\",\n        \"title\": \"OSS-Fuzz: Run Full Fuzz Introspector\",\n        \"description\": \"Runs a full Fuzz Introspector\"\n      },\n      {\n        \"command\": \"oss-fuzz.GetOptimalTargets\",\n        \"title\": \"OSS-Fuzz: Get optimal targets\",\n        \"description\": \"Gets the optimal targets of this project\"\n      }\n    ],\n    \"walkthroughs\":[\n      {\n        \"id\": \"BuildAndRunExisting Project\",\n        \"title\": \"Set up OSS-Fuzz\",\n        \"description\": \"This walkthrough takes you through how to set up OSS-Fuzz in the VSCode extension and proceeding to build the fuzzers of an existing project as well as running a fuzzer from the project.\",\n        \"steps\": [\n          {\n            \"id\": \"s1\",\n            \"title\": \"Set up OSS-Fuzz\",\n            \"description\": \"This step sets up OSS-Fuzz in the folder /tmp/oss-fuzz\",\n            \"completionEvents\": [\"onCommand:oss-fuzz.SetUp\"],\n            \"media\": {\"altText\": \".\", \"image\": \"images/workflow-1-s-1\"}\n          }\n        ]\n      }\n    ]\n  },\n  \"scripts\": {\n    \"vscode:prepublish\": \"npm run compile\",\n    \"compile\": \"tsc\",\n    \"watch\": \"tsc -watch -p ./\",\n    \"pretest\": \"npm run compile\",\n    \"lint\": \"gts lint\",\n    \"clean\": \"gts clean\",\n    \"fix\": \"gts fix\",\n    \"prepare\": \"npm run compile\",\n    \"posttest\": \"npm run lint\"\n  },\n  \"devDependencies\": {\n    \"@types/glob\": \"^8.1.0\",\n    \"@types/mocha\": \"^10.0.1\",\n    \"@types/node\": \"^14.11.2\",\n    \"@types/vscode\": \"^1.76.0\",\n    \"@typescript-eslint/eslint-plugin\": \"^5.53.0\",\n    \"@typescript-eslint/parser\": \"^5.53.0\",\n    \"@vscode/test-electron\": \"^2.2.3\",\n    \"eslint\": \"^8.34.0\",\n    \"glob\": \"^8.1.0\",\n    \"mocha\": \"^10.8.2\",\n    \"typescript\": \"~4.7.0\",\n    \"gts\": \"^3.1.1\"\n  },\n  \"dependencies\": {\n    \"@microsoft/vscode-file-downloader-api\": \"^1.0.1\"\n  }\n}\n","tools/vscode-extension/tsconfig.json":"{\n  \"extends\": \"./node_modules/gts/tsconfig-google.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \".\",\n    \"outDir\": \"build\"\n  },\n  \"include\": [\n    \"src/**/*.ts\",\n    \"test/**/*.ts\"\n  ]\n}\n","tools/vscode-extension/package-lock.json":"{\n  \"name\": \"OSS-Fuzz\",\n  \"version\": \"0.0.5\",\n  \"lockfileVersion\": 2,\n  \"requires\": true,\n  \"packages\": {\n    \"\": {\n      \"name\": \"OSS-Fuzz\",\n      \"version\": \"0.0.5\",\n      \"dependencies\": {\n        \"@microsoft/vscode-file-downloader-api\": \"^1.0.1\"\n      },\n      \"devDependencies\": {\n        \"@types/glob\": \"^8.1.0\",\n        \"@types/mocha\": \"^10.0.1\",\n        \"@types/node\": \"^14.11.2\",\n        \"@types/vscode\": \"^1.76.0\",\n        \"@typescript-eslint/eslint-plugin\": \"^5.53.0\",\n        \"@typescript-eslint/parser\": \"^5.53.0\",\n        \"@vscode/test-electron\": \"^2.2.3\",\n        \"eslint\": \"^8.34.0\",\n        \"glob\": \"^8.1.0\",\n        \"gts\": \"^3.1.1\",\n        \"mocha\": \"^10.8.2\",\n        \"typescript\": \"~4.7.0\"\n      },\n      \"engines\": {\n        \"vscode\": \"^1.76.0\"\n      }\n    },\n    \"node_modules/@babel/code-frame\": {\n      \"version\": \"7.22.5\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz\",\n      \"integrity\": \"sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@babel/highlight\": \"^7.22.5\"\n      },\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@babel/helper-validator-identifier\": {\n      \"version\": \"7.22.5\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz\",\n      \"integrity\": \"sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@babel/highlight\": {\n      \"version\": \"7.22.5\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz\",\n      \"integrity\": \"sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@babel/helper-validator-identifier\": \"^7.22.5\",\n        \"chalk\": \"^2.0.0\",\n        \"js-tokens\": \"^4.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/ansi-styles\": {\n      \"version\": \"3.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz\",\n      \"integrity\": \"sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-convert\": \"^1.9.0\"\n      },\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/chalk\": {\n      \"version\": \"2.4.2\",\n      \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz\",\n      \"integrity\": \"sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ansi-styles\": \"^3.2.1\",\n        \"escape-string-regexp\": \"^1.0.5\",\n        \"supports-color\": \"^5.3.0\"\n      },\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/color-convert\": {\n      \"version\": \"1.9.3\",\n      \"resolved\": \"https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz\",\n      \"integrity\": \"sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-name\": \"1.1.3\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/color-name\": {\n      \"version\": \"1.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz\",\n      \"integrity\": \"sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==\",\n      \"dev\": true\n    },\n    \"node_modules/@babel/highlight/node_modules/escape-string-regexp\": {\n      \"version\": \"1.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz\",\n      \"integrity\": \"sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.8.0\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/has-flag\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz\",\n      \"integrity\": \"sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/supports-color\": {\n      \"version\": \"5.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz\",\n      \"integrity\": \"sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"has-flag\": \"^3.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@eslint/eslintrc\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz\",\n      \"integrity\": \"sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ajv\": \"^6.12.4\",\n        \"debug\": \"^4.3.2\",\n        \"espree\": \"^9.4.0\",\n        \"globals\": \"^13.19.0\",\n        \"ignore\": \"^5.2.0\",\n        \"import-fresh\": \"^3.2.1\",\n        \"js-yaml\": \"^4.1.0\",\n        \"minimatch\": \"^3.1.2\",\n        \"strip-json-comments\": \"^3.1.1\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://opencollective.com/eslint\"\n      }\n    },\n    \"node_modules/@eslint/js\": {\n      \"version\": \"8.35.0\",\n      \"resolved\": \"https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz\",\n      \"integrity\": \"sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      }\n    },\n    \"node_modules/@humanwhocodes/config-array\": {\n      \"version\": \"0.11.8\",\n      \"resolved\": \"https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz\",\n      \"integrity\": \"sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@humanwhocodes/object-schema\": \"^1.2.1\",\n        \"debug\": \"^4.1.1\",\n        \"minimatch\": \"^3.0.5\"\n      },\n      \"engines\": {\n        \"node\": \">=10.10.0\"\n      }\n    },\n    \"node_modules/@humanwhocodes/module-importer\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz\",\n      \"integrity\": \"sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=12.22\"\n      },\n      \"funding\": {\n        \"type\": \"github\",\n        \"url\": \"https://github.com/sponsors/nzakas\"\n      }\n    },\n    \"node_modules/@humanwhocodes/object-schema\": {\n      \"version\": \"1.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz\",\n      \"integrity\": \"sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==\",\n      \"dev\": true\n    },\n    \"node_modules/@microsoft/vscode-file-downloader-api\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/@microsoft/vscode-file-downloader-api/-/vscode-file-downloader-api-1.0.1.tgz\",\n      \"integrity\": \"sha512-cO9n/IpTMbXizz5YcEkiuRyX5r66SBY/3LnrlroyXbQXrgDdaKecfV3n4viTcvp9O//QF2AxcBfDZex2d4VSTg==\"\n    },\n    \"node_modules/@nodelib/fs.scandir\": {\n      \"version\": \"2.1.5\",\n      \"resolved\": \"https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz\",\n      \"integrity\": \"sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@nodelib/fs.stat\": \"2.0.5\",\n        \"run-parallel\": \"^1.1.9\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/@nodelib/fs.stat\": {\n      \"version\": \"2.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz\",\n      \"integrity\": \"sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/@nodelib/fs.walk\": {\n      \"version\": \"1.2.8\",\n      \"resolved\": \"https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz\",\n      \"integrity\": \"sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@nodelib/fs.scandir\": \"2.1.5\",\n        \"fastq\": \"^1.6.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/@tootallnate/once\": {\n      \"version\": \"1.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz\",\n      \"integrity\": \"sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">= 6\"\n      }\n    },\n    \"node_modules/@types/glob\": {\n      \"version\": \"8.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz\",\n      \"integrity\": \"sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@types/minimatch\": \"^5.1.2\",\n        \"@types/node\": \"*\"\n      }\n    },\n    \"node_modules/@types/json-schema\": {\n      \"version\": \"7.0.11\",\n      \"resolved\": \"https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz\",\n      \"integrity\": \"sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/minimatch\": {\n      \"version\": \"5.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz\",\n      \"integrity\": \"sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/minimist\": {\n      \"version\": \"1.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz\",\n      \"integrity\": \"sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/mocha\": {\n      \"version\": \"10.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz\",\n      \"integrity\": \"sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/node\": {\n      \"version\": \"14.18.54\",\n      \"resolved\": \"https://registry.npmjs.org/@types/node/-/node-14.18.54.tgz\",\n      \"integrity\": \"sha512-uq7O52wvo2Lggsx1x21tKZgqkJpvwCseBBPtX/nKQfpVlEsLOb11zZ1CRsWUKvJF0+lzuA9jwvA7Pr2Wt7i3xw==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/normalize-package-data\": {\n      \"version\": \"2.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz\",\n      \"integrity\": \"sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/semver\": {\n      \"version\": \"7.3.13\",\n      \"resolved\": \"https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz\",\n      \"integrity\": \"sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/vscode\": {\n      \"version\": \"1.76.0\",\n      \"resolved\": \"https://registry.npmjs.org/@types/vscode/-/vscode-1.76.0.tgz\",\n      \"integrity\": \"sha512-CQcY3+Fe5hNewHnOEAVYj4dd1do/QHliXaknAEYSXx2KEHUzFibDZSKptCon+HPgK55xx20pR+PBJjf0MomnBA==\",\n      \"dev\": true\n    },\n    \"node_modules/@typescript-eslint/eslint-plugin\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.1.tgz\",\n      \"integrity\": \"sha512-a2RQAkosH3d3ZIV08s3DcL/mcGc2M/UC528VkPULFxR9VnVPT8pBu0IyBAJJmVsCmhVfwQX1v6q+QGnmSe1bew==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/scope-manager\": \"5.54.1\",\n        \"@typescript-eslint/type-utils\": \"5.54.1\",\n        \"@typescript-eslint/utils\": \"5.54.1\",\n        \"debug\": \"^4.3.4\",\n        \"grapheme-splitter\": \"^1.0.4\",\n        \"ignore\": \"^5.2.0\",\n        \"natural-compare-lite\": \"^1.4.0\",\n        \"regexpp\": \"^3.2.0\",\n        \"semver\": \"^7.3.7\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"@typescript-eslint/parser\": \"^5.0.0\",\n        \"eslint\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz\",\n      \"integrity\": \"sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@types/json-schema\": \"^7.0.7\",\n        \"@typescript-eslint/scope-manager\": \"4.33.0\",\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"@typescript-eslint/typescript-estree\": \"4.33.0\",\n        \"eslint-scope\": \"^5.1.1\",\n        \"eslint-utils\": \"^3.0.0\"\n      },\n      \"engines\": {\n        \"node\": \"^10.12.0 || >=12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"*\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz\",\n      \"integrity\": \"sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"@typescript-eslint/visitor-keys\": \"4.33.0\"\n      },\n      \"engines\": {\n        \"node\": \"^8.10.0 || ^10.13.0 || >=11.10.1\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz\",\n      \"integrity\": \"sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \"^8.10.0 || ^10.13.0 || >=11.10.1\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz\",\n      \"integrity\": \"sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"@typescript-eslint/visitor-keys\": \"4.33.0\",\n        \"debug\": \"^4.3.1\",\n        \"globby\": \"^11.0.3\",\n        \"is-glob\": \"^4.0.1\",\n        \"semver\": \"^7.3.5\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^10.12.0 || >=12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz\",\n      \"integrity\": \"sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"eslint-visitor-keys\": \"^2.0.0\"\n      },\n      \"engines\": {\n        \"node\": \"^8.10.0 || ^10.13.0 || >=11.10.1\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-visitor-keys\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz\",\n      \"integrity\": \"sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@typescript-eslint/parser\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.1.tgz\",\n      \"integrity\": \"sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/scope-manager\": \"5.54.1\",\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/typescript-estree\": \"5.54.1\",\n        \"debug\": \"^4.3.4\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/scope-manager\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz\",\n      \"integrity\": \"sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/visitor-keys\": \"5.54.1\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/type-utils\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.1.tgz\",\n      \"integrity\": \"sha512-WREHsTz0GqVYLIbzIZYbmUUr95DKEKIXZNH57W3s+4bVnuF1TKe2jH8ZNH8rO1CeMY3U4j4UQeqPNkHMiGem3g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/typescript-estree\": \"5.54.1\",\n        \"@typescript-eslint/utils\": \"5.54.1\",\n        \"debug\": \"^4.3.4\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"*\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/types\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz\",\n      \"integrity\": \"sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/typescript-estree\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz\",\n      \"integrity\": \"sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/visitor-keys\": \"5.54.1\",\n        \"debug\": \"^4.3.4\",\n        \"globby\": \"^11.1.0\",\n        \"is-glob\": \"^4.0.3\",\n        \"semver\": \"^7.3.7\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/utils\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.1.tgz\",\n      \"integrity\": \"sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@types/json-schema\": \"^7.0.9\",\n        \"@types/semver\": \"^7.3.12\",\n        \"@typescript-eslint/scope-manager\": \"5.54.1\",\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/typescript-estree\": \"5.54.1\",\n        \"eslint-scope\": \"^5.1.1\",\n        \"eslint-utils\": \"^3.0.0\",\n        \"semver\": \"^7.3.7\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      }\n    },\n    \"node_modules/@typescript-eslint/visitor-keys\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz\",\n      \"integrity\": \"sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"eslint-visitor-keys\": \"^3.3.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@vscode/test-electron\": {\n      \"version\": \"2.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.0.tgz\",\n      \"integrity\": \"sha512-fwzA9RtazH1GT/sckYlbxu6t5e4VaMXwCVtyLv4UAG0hP6NTfnMaaG25XCfWqlVwFhBMcQXHBCy5dmz2eLUnkw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"http-proxy-agent\": \"^4.0.1\",\n        \"https-proxy-agent\": \"^5.0.0\",\n        \"jszip\": \"^3.10.1\",\n        \"semver\": \"^7.3.8\"\n      },\n      \"engines\": {\n        \"node\": \">=16\"\n      }\n    },\n    \"node_modules/acorn\": {\n      \"version\": \"8.8.2\",\n      \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz\",\n      \"integrity\": \"sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==\",\n      \"dev\": true,\n      \"bin\": {\n        \"acorn\": \"bin/acorn\"\n      },\n      \"engines\": {\n        \"node\": \">=0.4.0\"\n      }\n    },\n    \"node_modules/acorn-jsx\": {\n      \"version\": \"5.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz\",\n      \"integrity\": \"sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==\",\n      \"dev\": true,\n      \"peerDependencies\": {\n        \"acorn\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      }\n    },\n    \"node_modules/agent-base\": {\n      \"version\": \"6.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz\",\n      \"integrity\": \"sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"debug\": \"4\"\n      },\n      \"engines\": {\n        \"node\": \">= 6.0.0\"\n      }\n    },\n    \"node_modules/ajv\": {\n      \"version\": \"6.12.6\",\n      \"resolved\": \"https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz\",\n      \"integrity\": \"sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"fast-deep-equal\": \"^3.1.1\",\n        \"fast-json-stable-stringify\": \"^2.0.0\",\n        \"json-schema-traverse\": \"^0.4.1\",\n        \"uri-js\": \"^4.2.2\"\n      },\n      \"funding\": {\n        \"type\": \"github\",\n        \"url\": \"https://github.com/sponsors/epoberezkin\"\n      }\n    },\n    \"node_modules/ansi-colors\": {\n      \"version\": \"4.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz\",\n      \"integrity\": \"sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/ansi-escapes\": {\n      \"version\": \"4.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz\",\n      \"integrity\": \"sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"type-fest\": \"^0.21.3\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/ansi-escapes/node_modules/type-fest\": {\n      \"version\": \"0.21.3\",\n      \"resolved\": \"https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz\",\n      \"integrity\": \"sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/ansi-regex\": {\n      \"version\": \"5.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n      \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/ansi-styles\": {\n      \"version\": \"4.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz\",\n      \"integrity\": \"sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-convert\": \"^2.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n      }\n    },\n    \"node_modules/anymatch\": {\n      \"version\": \"3.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz\",\n      \"integrity\": \"sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"normalize-path\": \"^3.0.0\",\n        \"picomatch\": \"^2.0.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/argparse\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz\",\n      \"integrity\": \"sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==\",\n      \"dev\": true\n    },\n    \"node_modules/array-union\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz\",\n      \"integrity\": \"sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/arrify\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz\",\n      \"integrity\": \"sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/astral-regex\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz\",\n      \"integrity\": \"sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/balanced-match\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz\",\n      \"integrity\": \"sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==\",\n      \"dev\": true\n    },\n    \"node_modules/binary-extensions\": {\n      \"version\": \"2.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz\",\n      \"integrity\": \"sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/brace-expansion\": {\n      \"version\": \"1.1.11\",\n      \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz\",\n      \"integrity\": \"sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"balanced-match\": \"^1.0.0\",\n        \"concat-map\": \"0.0.1\"\n      }\n    },\n    \"node_modules/braces\": {\n      \"version\": \"3.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/braces/-/braces-3.0.3.tgz\",\n      \"integrity\": \"sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"fill-range\": \"^7.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/browser-stdout\": {\n      \"version\": \"1.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz\",\n      \"integrity\": \"sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==\",\n      \"dev\": true\n    },\n    \"node_modules/callsites\": {\n      \"version\": \"3.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz\",\n      \"integrity\": \"sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/camelcase\": {\n      \"version\": \"6.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz\",\n      \"integrity\": \"sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/camelcase-keys\": {\n      \"version\": \"6.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz\",\n      \"integrity\": \"sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"camelcase\": \"^5.3.1\",\n        \"map-obj\": \"^4.0.0\",\n        \"quick-lru\": \"^4.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/camelcase-keys/node_modules/camelcase\": {\n      \"version\": \"5.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz\",\n      \"integrity\": \"sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/chalk\": {\n      \"version\": \"4.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz\",\n      \"integrity\": \"sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ansi-styles\": \"^4.1.0\",\n        \"supports-color\": \"^7.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/chalk/chalk?sponsor=1\"\n      }\n    },\n    \"node_modules/chardet\": {\n      \"version\": \"0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz\",\n      \"integrity\": \"sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==\",\n      \"dev\": true\n    },\n    \"node_modules/chokidar\": {\n      \"version\": \"3.5.3\",\n      \"resolved\": \"https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz\",\n      \"integrity\": \"sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==\",\n      \"dev\": true,\n      \"funding\": [\n        {\n          \"type\": \"individual\",\n          \"url\": \"https://paulmillr.com/funding/\"\n        }\n      ],\n      \"dependencies\": {\n        \"anymatch\": \"~3.1.2\",\n        \"braces\": \"~3.0.2\",\n        \"glob-parent\": \"~5.1.2\",\n        \"is-binary-path\": \"~2.1.0\",\n        \"is-glob\": \"~4.0.1\",\n        \"normalize-path\": \"~3.0.0\",\n        \"readdirp\": \"~3.6.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 8.10.0\"\n      },\n      \"optionalDependencies\": {\n        \"fsevents\": \"~2.3.2\"\n      }\n    },\n    \"node_modules/chokidar/node_modules/glob-parent\": {\n      \"version\": \"5.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz\",\n      \"integrity\": \"sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"is-glob\": \"^4.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 6\"\n      }\n    },\n    \"node_modules/cli-cursor\": {\n      \"version\": \"3.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz\",\n      \"integrity\": \"sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"restore-cursor\": \"^3.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/cli-width\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz\",\n      \"integrity\": \"sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">= 10\"\n      }\n    },\n    \"node_modules/cliui\": {\n      \"version\": \"7.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz\",\n      \"integrity\": \"sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"string-width\": \"^4.2.0\",\n        \"strip-ansi\": \"^6.0.0\",\n        \"wrap-ansi\": \"^7.0.0\"\n      }\n    },\n    \"node_modules/color-convert\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz\",\n      \"integrity\": \"sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-name\": \"~1.1.4\"\n      },\n      \"engines\": {\n        \"node\": \">=7.0.0\"\n      }\n    },\n    \"node_modules/color-name\": {\n      \"version\": \"1.1.4\",\n      \"resolved\": \"https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz\",\n      \"integrity\": \"sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==\",\n      \"dev\": true\n    },\n    \"node_modules/concat-map\": {\n      \"version\": \"0.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz\",\n      \"integrity\": \"sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==\",\n      \"dev\": true\n    },\n    \"node_modules/core-util-is\": {\n      \"version\": \"1.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz\",\n      \"integrity\": \"sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==\",\n      \"dev\": true\n    },\n    \"node_modules/cross-spawn\": {\n      \"version\": \"7.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz\",\n      \"integrity\": \"sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"path-key\": \"^3.1.0\",\n        \"shebang-command\": \"^2.0.0\",\n        \"which\": \"^2.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/debug\": {\n      \"version\": \"4.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/debug/-/debug-4.4.0.tgz\",\n      \"integrity\": \"sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"ms\": \"^2.1.3\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"supports-color\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/decamelize\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz\",\n      \"integrity\": \"sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/decamelize-keys\": {\n      \"version\": \"1.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz\",\n      \"integrity\": \"sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"decamelize\": \"^1.1.0\",\n        \"map-obj\": \"^1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/decamelize-keys/node_modules/decamelize\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz\",\n      \"integrity\": \"sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/decamelize-keys/node_modules/map-obj\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz\",\n      \"integrity\": \"sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/deep-is\": {\n      \"version\": \"0.1.4\",\n      \"resolved\": \"https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz\",\n      \"integrity\": \"sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==\",\n      \"dev\": true\n    },\n    \"node_modules/diff\": {\n      \"version\": \"5.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/diff/-/diff-5.2.0.tgz\",\n      \"integrity\": \"sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==\",\n      \"dev\": true,\n      \"license\": \"BSD-3-Clause\",\n      \"engines\": {\n        \"node\": \">=0.3.1\"\n      }\n    },\n    \"node_modules/dir-glob\": {\n      \"version\": \"3.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz\",\n      \"integrity\": \"sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"path-type\": \"^4.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/doctrine\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz\",\n      \"integrity\": \"sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"esutils\": \"^2.0.2\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0.0\"\n      }\n    },\n    \"node_modules/emoji-regex\": {\n      \"version\": \"8.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n      \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n      \"dev\": true\n    },\n    \"node_modules/enquirer\": {\n      \"version\": \"2.3.6\",\n      \"resolved\": \"https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz\",\n      \"integrity\": \"sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ansi-colors\": \"^4.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8.6\"\n      }\n    },\n    \"node_modules/error-ex\": {\n      \"version\": \"1.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz\",\n      \"integrity\": \"sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"is-arrayish\": \"^0.2.1\"\n      }\n    },\n    \"node_modules/escalade\": {\n      \"version\": \"3.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz\",\n      \"integrity\": \"sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/escape-string-regexp\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz\",\n      \"integrity\": \"sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/eslint\": {\n      \"version\": \"8.35.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz\",\n      \"integrity\": \"sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@eslint/eslintrc\": \"^2.0.0\",\n        \"@eslint/js\": \"8.35.0\",\n        \"@humanwhocodes/config-array\": \"^0.11.8\",\n        \"@humanwhocodes/module-importer\": \"^1.0.1\",\n        \"@nodelib/fs.walk\": \"^1.2.8\",\n        \"ajv\": \"^6.10.0\",\n        \"chalk\": \"^4.0.0\",\n        \"cross-spawn\": \"^7.0.2\",\n        \"debug\": \"^4.3.2\",\n        \"doctrine\": \"^3.0.0\",\n        \"escape-string-regexp\": \"^4.0.0\",\n        \"eslint-scope\": \"^7.1.1\",\n        \"eslint-utils\": \"^3.0.0\",\n        \"eslint-visitor-keys\": \"^3.3.0\",\n        \"espree\": \"^9.4.0\",\n        \"esquery\": \"^1.4.2\",\n        \"esutils\": \"^2.0.2\",\n        \"fast-deep-equal\": \"^3.1.3\",\n        \"file-entry-cache\": \"^6.0.1\",\n        \"find-up\": \"^5.0.0\",\n        \"glob-parent\": \"^6.0.2\",\n        \"globals\": \"^13.19.0\",\n        \"grapheme-splitter\": \"^1.0.4\",\n        \"ignore\": \"^5.2.0\",\n        \"import-fresh\": \"^3.0.0\",\n        \"imurmurhash\": \"^0.1.4\",\n        \"is-glob\": \"^4.0.0\",\n        \"is-path-inside\": \"^3.0.3\",\n        \"js-sdsl\": \"^4.1.4\",\n        \"js-yaml\": \"^4.1.0\",\n        \"json-stable-stringify-without-jsonify\": \"^1.0.1\",\n        \"levn\": \"^0.4.1\",\n        \"lodash.merge\": \"^4.6.2\",\n        \"minimatch\": \"^3.1.2\",\n        \"natural-compare\": \"^1.4.0\",\n        \"optionator\": \"^0.9.1\",\n        \"regexpp\": \"^3.2.0\",\n        \"strip-ansi\": \"^6.0.1\",\n        \"strip-json-comments\": \"^3.1.0\",\n        \"text-table\": \"^0.2.0\"\n      },\n      \"bin\": {\n        \"eslint\": \"bin/eslint.js\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://opencollective.com/eslint\"\n      }\n    },\n    \"node_modules/eslint-config-prettier\": {\n      \"version\": \"7.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz\",\n      \"integrity\": \"sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==\",\n      \"dev\": true,\n      \"bin\": {\n        \"eslint-config-prettier\": \"bin/cli.js\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=7.0.0\"\n      }\n    },\n    \"node_modules/eslint-plugin-es\": {\n      \"version\": \"3.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz\",\n      \"integrity\": \"sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-utils\": \"^2.0.0\",\n        \"regexpp\": \"^3.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8.10.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/mysticatea\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=4.19.1\"\n      }\n    },\n    \"node_modules/eslint-plugin-es/node_modules/eslint-utils\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz\",\n      \"integrity\": \"sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-visitor-keys\": \"^1.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/mysticatea\"\n      }\n    },\n    \"node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz\",\n      \"integrity\": \"sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/eslint-plugin-node\": {\n      \"version\": \"11.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz\",\n      \"integrity\": \"sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-plugin-es\": \"^3.0.0\",\n        \"eslint-utils\": \"^2.0.0\",\n        \"ignore\": \"^5.1.1\",\n        \"minimatch\": \"^3.0.4\",\n        \"resolve\": \"^1.10.1\",\n        \"semver\": \"^6.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8.10.0\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=5.16.0\"\n      }\n    },\n    \"node_modules/eslint-plugin-node/node_modules/eslint-utils\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz\",\n      \"integrity\": \"sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-visitor-keys\": \"^1.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/mysticatea\"\n      }\n    },\n    \"node_modules/eslint-plugin-node/node_modules/eslint-visitor-keys\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz\",\n      \"integrity\": \"sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/eslint-plugin-node/node_modules/semver\": {\n      \"version\": \"6.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/semver/-/semver-6.3.1.tgz\",\n      \"integrity\": \"sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==\",\n      \"dev\": true,\n      \"bin\": {\n        \"semver\": \"bin/semver.js\"\n      }\n    },\n    \"node_modules/eslint-plugin-prettier\": {\n      \"version\": \"3.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz\",\n      \"integrity\": \"sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"prettier-linter-helpers\": \"^1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0.0\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=5.0.0\",\n        \"prettier\": \">=1.13.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"eslint-config-prettier\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/eslint-scope\": {\n      \"version\": \"5.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz\",\n      \"integrity\": \"sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"esrecurse\": \"^4.3.0\",\n        \"estraverse\": \"^4.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8.0.0\"\n      }\n    },\n    \"node_modules/eslint-utils\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz\",\n      \"integrity\": \"sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-visitor-keys\": \"^2.0.0\"\n      },\n      \"engine","infra/experimental/agent-skills/fuzzing-python-expert/SKILL.md":"---\nname: fuzzing-python-expert\ndescription:\n  Use this skill to fuzz open source Python software projects using Atheris.\n---\n\n# Fuzzing Python expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for Python projects integrated into OSS-Fuzz. Python\nfuzzing uses [Atheris](https://github.com/google/atheris), which wraps libFuzzer\nand instruments Python bytecode for coverage-guided fuzzing.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nPython projects must use the Python base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-python\n```\n\nSet `language: python` in `project.yaml`.\n\n### Harness structure\n\nA Python fuzz target is a `.py` file (named `fuzz_<target>.py` by convention)\nthat follows this pattern:\n\n```python\n#!/usr/bin/python3\nimport sys\nimport atheris\n\n# Import the module under test after atheris.instrument_imports() or within\n# the atheris.instrument_all() context so bytecode is instrumented.\n\ndef TestOneInput(data):\n    fdp = atheris.FuzzedDataProvider(data)\n    # Extract typed values from the raw fuzzer bytes.\n    value = fdp.ConsumeString(128)\n    try:\n        my_module.parse(value)\n    except (ValueError, TypeError, KeyError):\n        # Expected exceptions from invalid input are not bugs.\n        pass\n\ndef main():\n    atheris.instrument_all()   # instrument all loaded Python modules\n    atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True)\n    atheris.Fuzz()\n\nif __name__ == \"__main__\":\n    main()\n```\n\n### Instrumenting imports selectively\n\nWhen `instrument_all()` is too broad (e.g. causes conflicts with C extensions),\ninstrument specific modules using the `instrument_imports()` context manager:\n\n```python\nimport atheris\nwith atheris.instrument_imports():\n    import my_module\n    import my_module.subpackage\n```\n\n### FuzzedDataProvider reference\n\n`atheris.FuzzedDataProvider` splits the raw byte stream into typed values:\n\n| Method | Description |\n|---|---|\n| `ConsumeBytes(count)` | `bytes` of length count |\n| `ConsumeByteList(count)` | `list[int]` of length count |\n| `ConsumeString(count)` | decoded `str` (may contain surrogates) |\n| `ConsumeUnicode(count)` | `str` without surrogates |\n| `ConsumeUnicodeNoSurrogates(count)` | strict `str` |\n| `ConsumeInt(nbytes)` | signed int from nbytes |\n| `ConsumeIntInRange(min, max)` | int in range |\n| `ConsumeFloat()` | float |\n| `ConsumeBool()` | bool |\n| `ConsumeIntList(count, nbytes)` | list of ints |\n| `PickValueInList(lst)` | random element |\n| `ConsumeRemainingBytes()` | all remaining bytes |\n\n### Building in OSS-Fuzz\n\n`build.sh` installs the target package and uses the `compile_python_fuzzer`\nhelper to turn each `fuzz_*.py` file into a standalone fuzzer binary in `$OUT`:\n\n```bash\n# build.sh\n\n# Install the package under test.\npip3 install .\n\n# Compile all fuzz targets found in $SRC.\nfor fuzzer in $(find $SRC -name 'fuzz_*.py'); do\n    compile_python_fuzzer \"$fuzzer\"\ndone\n```\n\n`compile_python_fuzzer` handles linking against Atheris and libFuzzer and\nproduces an executable in `$OUT` named after the `.py` file.\n\n### Seed corpus and dictionaries\n\n- Place seed files in `$OUT/<fuzzer_name>_seed_corpus/` or zip them as\n  `$OUT/<fuzzer_name>_seed_corpus.zip`.\n- Dictionaries go to `$OUT/<fuzzer_name>.dict` — especially valuable for\n  text-format parsers (JSON, XML, YAML, CSV, etc.).\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks. See the [structured seed generation\n  reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good Python fuzzing harnesses\n\n1. **Instruments the right modules**: use `instrument_all()` for simplicity or\n   `instrument_imports()` for targeted instrumentation. Without instrumentation\n   coverage guidance is blind.\n2. **Targets attack surface**: parsers, template engines, serialisation\n   (pickle, JSON, YAML, XML), network protocol handling, and any API that\n   accepts untrusted strings or bytes.\n3. **Catches expected exceptions**: wrap target calls in `try/except` for the\n   documented exception types the target raises on bad input. Only unexpected\n   exceptions and hard crashes are findings.\n4. **Uses `FuzzedDataProvider` for structured input** rather than feeding raw\n   bytes directly to APIs that expect text — most Python APIs work on strings,\n   not bytes.\n5. **Avoids importing under test inside `TestOneInput`**: imports should happen\n   at module level (inside the `instrument_imports()` block if used) so they\n   are instrumented and not re-executed per iteration.\n6. **Is fast**: avoid file I/O, network calls, or subprocess invocations inside\n   `TestOneInput`.\n7. **Avoids non-determinism**: no `random`, no `datetime.now()`, no\n   `os.urandom()` inside the fuzz function.\n8. **Enables Python coverage**: pass `enable_python_coverage=True` to\n   `atheris.Setup` for bytecode-level coverage tracking.\n\n## What Python fuzzing finds\n\nPython is memory-safe, so the focus is on:\n\n- **Unhandled exceptions**: `ValueError`, `RecursionError`, `MemoryError`,\n  `UnicodeDecodeError`, and any exception the library should have caught and\n  converted to a clean error.\n- **`AssertionError`**: internal invariant violations triggered by crafted\n  input.\n- **Hangs / infinite loops**: detected by OSS-Fuzz's timeout.\n- **Crashes in C extensions**: Python libraries that wrap C code (e.g. lxml,\n  Pillow, cryptography) can still have memory-corruption bugs in their C layer,\n  which Atheris will surface because libFuzzer runs the whole process.\n- **Logic errors**: incorrect output, silent data corruption, wrong parsing\n  results on edge-case inputs.\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash usually means an exception is being raised on every input.\n  Run the harness locally (`python3 fuzz_target.py`) on a sample input to\n  debug before building through OSS-Fuzz.\n- Test the harness locally before the OSS-Fuzz build:\n  ```python\n  python3 fuzz_target.py <seed_file>\n  ```\n  Atheris supports running in single-input mode outside libFuzzer.\n- Install the package locally (`pip3 install .`) and iterate quickly before\n  going through the Docker build.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- Document why each entry point was chosen and what class of bugs it may find.\n","infra/experimental/agent-skills/oss-fuzz-engineer/SKILL.md":"---\nname: oss-fuzz-engineer\ndescription:\n  Use this skill to interact with the OSS-Fuzz infrastructure.\n---\n\n# OSS-Fuzz engineer\n\nThis skill guides the agent how to use the OSS-Fuzz infrastructure to find and report bugs in open source software. The agent can use this skill to integrate new projects, extend and improve the fuzzing posture of projects, run fuzzing campaigns, and fix broken existing OSS-Fuzz projects.\n\nWhen working on OSS-Fuzz tasks then you should also use any fuzzing related skills you have, such as code analysis and fuzzing harness writing skills, to achieve the best results.\n\n## Workflows\n\nThere are multiple common workflows that an OSS-Fuzz engineer might follow and we describe some imporant ones here.\n\n### Integrating a new project\n\nGiven a reference to an open source project, such as a link to a GitHub repository, the agent can follow these steps to integrate the project into OSS-Fuzz:\n1. **Assess the project**: The agent should first assess whether the project is suitable for fuzzing. This includes checking if the project is open source, has a significant user base, and contains code that can be fuzzed (e.g., C/C++ code).\n2. **Set up the environment**: The agent should set up the necessary environment for fuzzing the project. This includes:\n- A Dockerfile that defines the build environment for the project, using the OSS-Fuzz base images.\n- A build script that compiles the project with the necessary instrumentation for fuzzing.\n- A project.yaml that provides the necessary OSS-Fuzz meta data.\n3. **Write fuzz targets**: The agent should write fuzz targets for the project. Fuzz targets are small programs that call into the project's code and are used by the fuzzing engine to generate inputs and find bugs.\n4. **Test the integration**: The agent should test the integration by running the fuzz targets locally and ensuring that they work correctly. This project should be continue until the fuzz targets build and run well, and the OSS-Fuzz `check_build` script passes without errors.\n5. **Conclude the integration**: Once the integration is complete, the agent should conclude with a message of the results achieved and the next steps the security engineer guiding the agent should take. The agent should *not* make any commits or push anything to GitHub, but should conclude on the work for the security engineer to review. The agent should never submit any changes to OSS-Fuzz's Github.\n\nWhen doing this type of work it's crucial the agent uses any skills it has related to code analysis and fuzzing harness writing.\n\n### Extending and improving fuzzing posture\n\nThe agent can also be used to extend and improve the fuzzing posture of existing OSS-Fuzz projects. This can include:\n- Adding new fuzz targets to cover more code paths and functionality.\n- Improving existing fuzz targets to make them more effective at finding bugs.\n- Updating the build environment to include new dependencies or tools that can enhance fuzzing.\n- Analyzing fuzzing results and identifying areas of the code that are not well covered by existing fuzz targets, and then writing new fuzz targets to cover those areas.\n\nA useful approach for extending a project is to study the latest code coverage report for the project, which is publicly available, to identify areas of the code that are not well covered by existing fuzz targets. The agent can then write new fuzz targets to cover those areas, and test them locally before concluding on the work for the security engineer to review.\n\n**Critical: avoid targeting already-covered code.** The most common mistake when extending an OSS-Fuzz project is writing harnesses that target functions already well-exercised by the existing production fuzzer corpus. Before selecting any target function:\n\n1. Fetch the latest public `summary.json` via the `latest_report_info/<project>.json` pointer (never guess the date). See the [code coverage reference](references/code_coverage.md) for the pointer, the JSON schema, and how to read it.\n2. Parse the per-file metrics. Line % is triage only — use the **functions** metric (which functions are never entered ⇒ a new harness may be needed) and the **regions/branches** metric (reached function, dark branches ⇒ a corpus/seed problem) to decide *what kind* of gap each file has. Relying on line % alone throws away the signals that tell harness-work from seed-work apart.\n3. Build an explicit blocklist of already-covered files (≥ 50% lines with most functions covered) — do NOT write harnesses whose primary target lives in one of these files.\n4. Only select targets from files with genuinely low coverage (< 30% lines hit), and classify the gap with the functions-vs-branches split before acting.\n\nReading the source code and identifying \"important-looking\" functions is not sufficient — important functions are frequently already covered. Coverage data is the authoritative source of truth for what needs work, and Fuzz Introspector (<https://introspector.oss-fuzz.com>) additionally surfaces reachable-but-unfuzzed functions — see the code coverage reference for the full workflow.\n\n**Structured seed generation.** Adding a new harness is not the only way to extend coverage — often the existing harnesses already reach dark code, but the corpus never produces inputs valid enough to enter it. When a target parses a structured format (binary containers, codec/network bitstreams, text grammars), a script that constructs structurally-valid inputs from scratch is frequently the highest-leverage, lowest-review-cost improvement: random bytes rarely pass a parser's early magic/length/checksum checks, so the deep logic stays dark until seeded. Drive this the same coverage-first way: pick reachable files that are dark in `summary.json`, generate seeds that target them, validate each one actually parses, append them to the existing corpora (never replace), and confirm the union does not digress. See the [structured seed generation reference](references/structured_seed_generation.md) for the full workflow, construction techniques, per-fuzzer tailoring, and pitfalls, and `projects/vlc/generate_seeds.py` for a worked example.\n\nUse the local code coverage feature of the `python3 infra/helper.py` tool to generate code coverage reports for fuzz targets locally, for example to validate the code coverage achieved by a new fuzz target. This can be done by running `python3 infra/helper.py introspector --coverage-only PROJECT_NAME` and then studying the generated report in e.g. build/out/PROJECT_NAME/report. Some examples of this include:\n\n```\n# Generate a coverage report for htslib OSS-Fuzz project from running each\n# fuzzer for 30 seconds, and store coverage directory in `htslib-cov-1`.\npython3 infra/helper.py introspector --coverage-only --seconds 30 --out htslib-cov-1 htslib\n\n# Generate a coverage report for leveldb OSS-Fuzz project from running each\n# fuzzer for 45 seconds, and store coverage directory in `leveldb-cov-1`.\npython3 infra/helper.py introspector --coverage-only --seconds 45 --out leveldb-cov-1 leveldb\n```\n\nThe user may provide directions on how to extend the fuzzing, and it's crucial to follow instructions on this matter. For example, the user may ask to focus on a specific area of the code, or to target specific types of vulnerabilities. The agent should always provide a clear explanation of the rationale for each extension or improvement made to the fuzzing posture of the project.\n\nWhen extending an OSS-Fuzz project it's crucial to have a good understanding of the target code. To this end, it's often useful to get a local version of the target source code into the OSS-Fuzz project structure to make working with the target project easy. This involves e.g. studying the `Dockerfile` of the target project, finding the e.g. `git clone` of the target project, and then cloning this repository locally and using e.g. `COPY` instead of `RUN git clone` in the Dockerfile to get the source code into the container.\n\nThe agent should always provide clear technical justification for each extension.\n\nWhen doing this type of work it's crucial the agent uses any skills it has related to code analysis and fuzzing harness writing. It's important each extension is done through a personal assessment of the current fuzzing posture of the project, and a clear explanation of the rationale for each extension or improvement. The agent should never make any commits or push anything to GitHub, but should conclude on the work for the security engineer to review. The agent should never submit any changes to OSS-Fuzz's Github.\n\nIt is crucial when extending existing OSS-Fuzz project you must validate the existing code coverage does not digress. You should empirically evaluate this and give a justification that no digression has happened, or if it has happened then you should give a justification for why the digression is acceptable in light of the achieved extension.\n\nUnless otherwise specified, the agent should focus on improving a single fuzzing harness for the target project, and not focus on making broad changes that will take a long time to review. Simple changes are often more effective than broad large changes.\n\n### Fixing broken existing OSS-Fuzz projects\n\nThe agent can also be used to fix broken existing OSS-Fuzz projects. This can include:\n- Identifying and fixing build issues that prevent fuzz targets from running correctly.\n- Updating dependencies or build scripts to ensure that the project can be fuzzed effectively.\n- Analyzing fuzzing results to identify and fix issues that are causing the fuzzing campaign to fail or produce unreliable results.\n\nA given OSS-Fuzz project must succeed with:\n\n```\npython3 infra/helper.py build_fuzzers PROJECT_NAME\npython3 infra/helper.py check_build PROJECT_NAME\n```\n\nThe agent should never make any commits or push anything to GitHub, but should conclude on the work for the security engineer to review. The agent should never submit any changes to OSS-Fuzz's Github.\n\n\n### Chronos integration\n\nA common task for an OSS-Fuzz engineer is to add Chronos support for a given OSS-Fuzz project.\n\nChronos is a feature of OSS-Fuzz that makes it possible to quickly rebuild OSS-Fuzz projects and run unit tests of a given OSS-Fuzz project. This is used to efficiently validate e.g. patches of a project without having to rebuild the entire target project image.\n\nTo add Chronos support a project needs to have two key scripts:\n\n- replay_build.sh: used to quickly rebuild the project without network access.\n- run_tests.sh: used to run unit tests of the project without network access.\n\nThere are several constraints on these scripts, e.g. no network access, and it's important to always check the infra/chronos/README.md file to understand the specifics.\n\nA given Chronos integration must succeed with:\n\n```sh\npython3 infra/experimental/chronos/manager.py check-replay PROJECT_NAME\npython3 infra/experimental/chronos/manager.py check-tests PROJECT_NAME\n```\n\nThe above two commands must succeed without error, and when integrating a new project these commands must be run before concluding on the work for the security engineer to review.\n\nIn addition to the above, there are some constraints on Chronos worth mentioning:\n- If the tests fail when `run_tests.sh` is run, then `check-tests` *must* fail as well. This is a crucial invariant that is used to validate if wrong patches lead to wrong outcomes, and we must be able to check wrong patches that break tests.\n- The `run_tests.sh` script should leave a given repository in the state it was before the script was run. For example, `git diff` should be the same before and after `run_tests.sh` is run inside the target repository.\n- `run_tests.sh` has no network connection, so if any tests requires network connection then these tests should be skipped in `run_tests.sh` and this should be clearly documented in the script.\n\n\n# Guidelines for working locally on OSS-Fuzz projects\n\n1. Always work from the base folder of the current OSS-Fuzz project unless otherwise specified.\n2. Make a local checkout of the target source code to make working with the target project easy. This involves e.g. studying the `Dockerfile` of the target project, finding the e.g. `git clone` of the target project, and then cloning this repository locally and using e.g. `COPY` instead of `RUN git clone` in the Dockerfile to get the source code into the container.\n3. Use the `python3 infra/helper.py` tool to build and test fuzz targets locally.\n4. Analyse if build scripts can be optimized to improve local building efficiency.\n\n\n# Public data available for OSS-Fuzz projects\n\nThe OSS-Fuzz infrastructure provides a lot of public data that can be used to guide the work of an OSS-Fuzz engineer. This includes:\n\n- Current build status of all OSS-Fuzz projects:\n  - html page: https://oss-fuzz-build-logs.storage.googleapis.com/index.html\n  - json file: https://oss-fuzz-build-logs.storage.googleapis.com/status.json\n  - use this reference to identify latest build status of a given project, and to identify if there are any build issues that need to be fixed.\n  - If you are tasked with fixing the build of a project, then use this data to identify the latest build error.\n  - If you are tasked with fixing the build of a project, then use this data to identify the conditions of the latest build error, e.g. which architecture, fuzzing engine and sanitizer is failing.\n  - Some build errors are due to the harnesses running into an issue immediately, meaning they build but `check_build` fails. These are bugs that likely indicate the fuzzing harnesses have a deficiency.\n- in the references section guidance is provided on code coverage reports, helper script used for interacting with OSS-Fuzz projects and documentation on the structure of OSS-Fuzz projects.\n- https://introspector.oss-fuzz.com : details insights on macro and micro level stats on OSS-Fuzz.","infra/experimental/agent-skills/fuzzing-memory-unsafe-expert/SKILL.md":"---\nname: fuzzing-memory-unsafe-expert\ndescription:\n  Use this skill to fuzz open source C/C++ software projects.\n---\n\n# Fuzzing memory-unsafe expert\n\nThis skill provides the agent with the necessary knowledge and tools to fuzz open source software projects, particularly those that are part of the OSS-Fuzz program. The agent can use this skill to build fuzzers, run fuzzing campaigns, analyze results, and improve the fuzzing posture of projects.\n\nThe fuzzing abilities focused on here is libFuzzer-style harnesses, which are commonly used in OSS-Fuzz.\n\n## Threat modelling and attack surface\n\nBefore writing a single line of harness code, decide **what you are trying to\nfind and where an attacker's input actually enters the code**. A harness is\nonly as good as the entry point it targets: a technically-correct harness\npointed at code no attacker can influence finds bugs no maintainer will fix.\nThis step is what separates a valuable harness from a noisy one.\n\n### What a threat model answers\n\nFor the target project, answer these four questions explicitly and write the\nanswers into the harness's rationale doc:\n\n1. **What input is untrusted?** The data an attacker can control — a file\n   downloaded and opened, bytes arriving on a socket, a message from another\n   process, a document pasted into an editor. Trusted input (a config file the\n   admin wrote, a compile-time constant, a path only the program itself\n   constructs) is *not* an attacker's lever and is usually out of scope.\n2. **Where does that input cross a trust boundary?** The exact function(s)\n   where untrusted bytes first reach parsing/processing logic. This is the\n   entry point your harness should call.\n3. **What does the attacker control at that boundary?** The whole buffer? Only\n   a length field, with the rest validated upstream? A filename but not its\n   contents? This determines what your harness should mutate and what it should\n   hold fixed.\n4. **What would count as a real bug here?** A memory-safety violation (ASan/\n   MSan/UBSan finding) on attacker-reachable input is almost always in scope. A\n   crash that requires trusted/malformed *developer* input, or an\n   `assert()`-guarded programmer-error precondition, usually is not — fuzzing it\n   produces findings maintainers reject.\n\n### Identifying the attack surface\n\nConcrete, common attack surfaces in C/C++ projects, and the entry points to\ntarget for each:\n\n- **File-format parsers / loaders** (image, audio, video, fonts, archives,\n  documents). Entry point: the function that takes a buffer or file and decodes\n  it — e.g. `png_read_info`, `TIFFClientOpen`, `av_read_frame`,\n  `archive_read_open_memory`. Attacker controls the whole file. High-value,\n  classic OSS-Fuzz target.\n- **Network / wire-protocol handlers** (packet parsers, TLS records, HTTP,\n  DNS, RPC deserialisation). Entry point: the function fed raw bytes off the\n  wire, e.g. `SSL_read`, `parse_packet`, `deserialize_message`. Attacker\n  controls the byte stream; often you must also drive a state machine (see the\n  reachability note below).\n- **Serialisation / IPC boundaries** (protobuf/JSON/CBOR/ASN.1 decoders,\n  shared-memory messages, clipboard, environment when spawned by another\n  privilege domain). Entry point: the *decode* direction — the untrusted side\n  is bytes-in, not object-out.\n- **Text / query languages** (SQL, regex, template engines, config-language\n  parsers, expression evaluators). Entry point: the compile/parse function that\n  accepts an arbitrary string.\n- **Decompression and codecs** (zlib, lz4, zstd, JPEG/HEIF bitstreams). Entry\n  point: the decompress/decode call on attacker-supplied compressed data —\n  these are prime targets because a small input expands into large, structured\n  work.\n\n### Deriving the harness from the threat model\n\nThe threat model dictates the harness shape:\n\n- **Target the untrusted-input direction only.** Fuzz the *decoder*, not the\n  encoder; the *reader*, not the writer — unless the writer also consumes\n  attacker-controlled data.\n- **Mutate exactly what the attacker controls; fix the rest.** If the attacker\n  controls a document but not the parser's configuration, mutate the document\n  bytes and hold the config constant (set it once in `LLVMFuzzerInitialize`).\n  Fuzzing the config too invents a threat that does not exist and yields\n  rejected findings.\n- **Enter at the real trust boundary, not below it.** Calling a deep internal\n  helper directly may crash on inputs the public API would have rejected\n  upstream — a false positive. Prefer the outermost function an attacker's data\n  actually reaches. If you must call an internal function for coverage, first\n  confirm the upstream validation it assumes, and reproduce that precondition\n  in the harness.\n- **Honour the API contract to avoid false positives.** If a function is\n  documented to require NUL-terminated input, a valid handle, or a\n  pre-allocated output buffer, supply those — a crash from violating the\n  contract is a harness bug, not a target bug (this is the \"True Positives\"\n  characteristic below).\n\n### Reachability: entry point is not enough\n\nAn entry point that is untrusted-reachable in production may still be\n*unreachable* from your harness if getting to the interesting code requires\nstate the harness never sets up — an open session, a completed handshake, a\nprior header packet, a registered codec. Two consequences:\n\n- If the deep code needs prior state, **build that state in the harness**\n  (e.g. feed a valid header, complete the handshake) before feeding the mutated\n  bytes — otherwise the fuzzer never gets past the front door and coverage\n  stays shallow.\n- Cross-check with the coverage data (see the OSS-Fuzz engineer skill): if a\n  file you believe is attacker-reachable sits dark in `summary.json`, decide\n  whether it is *seed-limited* (a better corpus would reach it — write seeds) or\n  *harness-limited* (no input reaches it as the harness stands — the harness\n  itself must set up more state).\n\n### A worked example\n\nConsider a library that loads a custom image format via\n`int img_load(const uint8_t *buf, size_t len, img_opts *opts)`, where `opts`\ncomes from the application, not the file:\n\n- **Untrusted input:** `buf`/`len` (the image file). **Trusted:** `opts`.\n- **Trust boundary / entry point:** `img_load` — the outermost public function\n  an attacker's bytes reach.\n- **Attacker controls:** the entire image buffer, not the options.\n- **Real bug:** any ASan/UBSan finding decoding a crafted image.\n\nThe harness therefore fixes `opts` to a representative default once, and feeds\nthe mutated bytes as `buf`/`len`:\n\n```cpp\n#include <fuzzer/FuzzedDataProvider.h>\n\nstatic img_opts g_opts;  // trusted config, set once — not fuzzed.\n\nextern \"C\" int LLVMFuzzerInitialize(int *argc, char ***argv) {\n    img_opts_default(&g_opts);   // represents the real application's setup\n    return 0;\n}\n\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {\n    // Attacker controls the whole file; feed it directly.\n    img_load(data, size, &g_opts);\n    return 0;\n}\n```\n\nFuzzing `opts` instead, or calling an internal `decode_scanline` directly with\nraw bytes, would either invent a non-existent threat or trip asserts the public\nAPI prevents — both produce findings maintainers will not act on.\n\n## Fundamental Concepts\n\n### Fuzzing harness core function\n\nA fuzzing harness is a function that takes a byte array as input and processes it in a way that can trigger bugs or vulnerabilities in the software being tested. The core function of a fuzzing harness typically looks like this:\n\n```cpp\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {\n    // Process the input data and trigger potential bugs\n    return 0; // Return 0 to indicate successful processing\n}\n```\n\nReturn `0` in all normal cases. Return `-1` to tell libFuzzer to reject an\ninput and not add it to the corpus (rarely needed). Never `exit()` on bad\ninput — it aborts the whole run and breaks coverage tooling.\n\n### Extracting typed input with FuzzedDataProvider\n\nMost non-trivial targets do not take a single flat byte buffer — they need an\ninteger here, a length there, a string, several sub-buffers. Passing the raw\n`data`/`size` directly to such an API means the fuzzer almost never produces a\nwell-formed call. `FuzzedDataProvider` splits the one input stream into typed\nvalues, so libFuzzer's mutations map onto the parameters the target actually\nexpects. It is the standard tool for this in OSS-Fuzz (used by well over a\nhundred projects) and is shipped in the base image — no dependency to add:\n\n```cpp\n#include <fuzzer/FuzzedDataProvider.h>\n\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {\n    FuzzedDataProvider fdp(data, size);\n\n    // Consume typed, bounded values up front...\n    int         width  = fdp.ConsumeIntegralInRange<int>(1, 4096);\n    bool        strict = fdp.ConsumeBool();\n    std::string name   = fdp.ConsumeRandomLengthString(64);\n    // ...then hand the rest of the bytes to the payload argument.\n    std::vector<uint8_t> payload = fdp.ConsumeRemainingBytes<uint8_t>();\n\n    my_decode(name.c_str(), width, strict, payload.data(), payload.size());\n    return 0;\n}\n```\n\nCommonly used methods (see `compiler-rt`'s `FuzzedDataProvider.h` for the full\nset):\n\n| Method | Description |\n|---|---|\n| `ConsumeIntegral<T>()` | one integer of type `T` |\n| `ConsumeIntegralInRange<T>(min, max)` | integer bounded to `[min, max]` — use this to pick sizes, indices, enum values |\n| `ConsumeBool()` | one boolean |\n| `ConsumeEnum<E>()` | a value of a scoped enum with `kMaxValue` |\n| `ConsumeFloatingPoint<T>()` / `...InRange(min, max)` | float/double |\n| `ConsumeRandomLengthString(max)` | a `std::string` whose length the fuzzer controls (stops at an escaped `\\`) |\n| `ConsumeBytes<T>(count)` / `ConsumeBytesAsString(count)` | exactly `count` bytes |\n| `ConsumeRemainingBytes<T>()` / `ConsumeRemainingBytesAsString()` | everything left |\n| `remaining_bytes()` | how many bytes are left to consume |\n\nGuidance:\n\n- **Consume in a fixed order and document it.** The mapping from bytes to\n  parameters must be stable, or a saved crash will not reproduce.\n- **Consume the variable-length / \"rest of the input\" argument last** with\n  `ConsumeRemaining...`. Consuming a fixed count first and the remainder last\n  keeps the layout robust to mutation.\n- **Bound sizes and indices with `ConsumeIntegralInRange`** rather than masking\n  a raw integer — it wastes fewer inputs and keeps allocations sane.\n- Use FDP when the target needs structure; for a target that genuinely takes\n  one opaque buffer (a single `parse(data, size)`), pass `data`/`size` straight\n  through — FDP would only add noise.\n\n### One-time setup with LLVMFuzzerInitialize\n\nIf the harness needs setup that must happen once before fuzzing (parsing\n`argv`, setting environment variables, initialising a library global), put it\nin the optional `LLVMFuzzerInitialize` hook, which libFuzzer calls once at\nstartup — never do per-input work there:\n\n```cpp\nextern \"C\" int LLVMFuzzerInitialize(int *argc, char ***argv) {\n    setenv(\"HOME\", \"/tmp\", 1);\n    my_library_global_init();\n    return 0;\n}\n```\n\nKeep expensive but per-process-constant state (loaded config, a compiled\nschema, an allocated context reused across inputs) in a file-scope\n`static`/global initialised once — either here or lazily on the first\n`LLVMFuzzerTestOneInput` call — so it is not rebuilt on every iteration.\n\n### Sanitizers are the bug oracle\n\nA C/C++ harness rarely detects a bug by itself — the sanitizer the project is\nbuilt with is what turns silent memory corruption into a crash the fuzzer can\ncatch. OSS-Fuzz builds each target under a sanitizer (default AddressSanitizer;\nalso UndefinedBehaviorSanitizer and MemorySanitizer):\n\n- **ASan** — heap/stack/global buffer overflows, use-after-free, double-free,\n  leaks. The default and highest-value oracle.\n- **UBSan** — signed overflow, invalid shifts, misaligned/`null` pointer use,\n  bad casts, invalid enum values.\n- **MSan** — reads of uninitialised memory. Requires *all* linked code\n  (including dependencies) to be instrumented, or it reports false positives —\n  only enable it when the whole dependency chain is built under MSan.\n\nDesign implication: the harness's job is to *reach* untrusted-input-driven\nmemory operations with enough variety; the sanitizer reports the violation.\n`build.sh` must compile both the target library and the harness with the\nOSS-Fuzz `$CFLAGS`/`$CXXFLAGS` (which carry the sanitizer + coverage flags) —\nlinking against a separately, non-instrumented build silently disables the\noracle and coverage guidance.\n\n### Building in OSS-Fuzz\n\n`build.sh` compiles the project (as a static library where possible) and then\ncompiles + links each harness against it with `$LIB_FUZZING_ENGINE`. Always use\nthe OSS-Fuzz-provided `$CC`/`$CXX` and `$CFLAGS`/`$CXXFLAGS` so instrumentation\nand the sanitizer are applied:\n\n```bash\n# build.sh — build the library with instrumentation, statically.\nmkdir build && cd build\ncmake -DBUILD_SHARED_LIBS=OFF ..     # a static .a is easiest to link the harness against\nmake -j$(nproc)\ncd ..\n\n# Compile and link each harness against the instrumented library.\nfor f in $SRC/project/fuzz/*_fuzzer.cc; do\n    fuzzer=$(basename \"$f\" _fuzzer.cc)\n    $CXX $CXXFLAGS -std=c++17 -I$SRC/project/include \\\n        \"$f\" -o \"$OUT/${fuzzer}\" \\\n        $LIB_FUZZING_ENGINE \"$SRC/project/build/libproject.a\"\ndone\n```\n\nKey points:\n\n- Link the harness with **`$LIB_FUZZING_ENGINE`**, not a hardcoded\n  `-fsanitize=fuzzer` — this lets OSS-Fuzz swap the engine (libFuzzer, AFL++,\n  Centipede, or the coverage/`check_build` no-op engine).\n- Prefer a **static** project build; it avoids `LD_LIBRARY_PATH` juggling at\n  run time and ensures the linked code is instrumented.\n- Copy seed corpora (`$OUT/<fuzzer>_seed_corpus.zip`) and dictionaries\n  (`$OUT/<fuzzer>.dict`) in the same script.\n\n### Examples of good harnesses already in OSS-Fuzz\n\nStudy existing harnesses before writing your own — they show the idioms above\napplied to real projects, and matching an established style makes your harness\neasier for maintainers to accept. Each example below is checked into this\nrepository; open the file and read it in full.\n\n- **`projects/sentencepiece/sample_encode_fuzzer.cc`** — the canonical\n  `FuzzedDataProvider` split. It carves the one input into an `int`\n  (`ConsumeIntegral`), a `float` (`ConsumeFloatingPoint`) and the remaining\n  bytes as the text argument (`ConsumeRemainingBytesAsString`), then calls\n  `SampleEncodeAsSerializedProto(text, nbest, alpha)`. Note the ordering: the\n  fixed-size scalars are consumed first and the variable-length string last.\n  This is the template whenever the target API takes several typed parameters\n  rather than one buffer.\n\n- **`projects/spdlog/fuzz/pattern_fuzzer.cc`** — lazy one-time initialisation\n  and a tightly-scoped threat model. A `static` logger is created on the first\n  call and reused across iterations (never rebuilt per input), it guards\n  `size == 0`, and it fuzzes exactly one attacker-relevant entry point:\n  `spdlog::set_pattern(str)`, the format-pattern parser. It does *not* fuzz the\n  logging config — a clean example of \"mutate only what the attacker controls.\"\n\n- **`projects/file/magic_fuzzer_fd.cc`** — `LLVMFuzzerInitialize` for expensive\n  setup, and feeding an API that needs a real file descriptor. The magic\n  database is loaded once in an `Environment` built from `argv[0]`'s directory\n  (setup that must not repeat per input), and each input is written to a\n  `FuzzerTemporaryFile` so it can be handed to `magic_descriptor(fd)`. Use this\n  pattern when the target only accepts a path/`fd` rather than an in-memory\n  buffer — but note that going through a temp file is slower, so prefer an\n  in-memory entry point when the library exposes one.\n\nWhen extending an existing OSS-Fuzz project, the best reference is that\nproject's *own* existing harnesses: match their file layout, naming\n(`*_fuzzer.cc`), build-script wiring and error-handling conventions.\n\n### Characteristics found in good fuzzing harnesses\n\nThe below are characteristics commonly found in good fuzzing harnesses, which contribute to their effectiveness in finding bugs. They are not all necessary for a good harness and at times it may even be desirable to actively not pursue some of them.\n\n1. **Simplicity**: The harness should be simple and focused on processing the input data without unnecessary complexity.\n2. **Coverage**: The harness should aim to cover as much of the codebase as possible, including edge cases and error handling paths.\n3. **Determinism**: The harness should produce consistent results for the same input, allowing for reliable reproduction of bugs.\n4. **Performance**: The harness should be efficient in processing inputs to maximize the number of test cases that can be executed in a given time frame.\n5. **Error Handling**: The harness should include robust error handling to capture and report any issues that arise during fuzzing.\n6. **True Positives**: The harness should be designed to have no false positives, ensuring that reported issues are genuine bugs. This means all issues found by the fuzzer is something the maintainers are interested in fixing.\n7. **Matches threat model**: The harness should be designed to target specific types of vulnerabilities that are relevant to the project being fuzzed.\n8. **Hits code on the attack surface**: The harness should be designed to target code that is exposed to untrusted input, such as network interfaces, file parsers, or APIs.\n9. **Enough entropy**: The harness should be designed to allow for a wide range of inputs, providing enough variability to trigger different code paths and potential bugs.\n10. **Follows the code structure**: The harness should be designed to follow the structure of the codebase, making it easier to identify and target specific areas of interest.\n11. **Follows code conventions**: The harness should follow the coding conventions of the project, making it easier for maintainers to understand and integrate the harness into the codebase.\n12. **Does not get stuck**: The harness should be designed to avoid getting stuck on certain inputs or code paths, allowing the fuzzer to continue exploring other areas of the codebase.\n13. **Includes dictionary**: The harness should include a dictionary of known inputs or patterns that are relevant to the project, helping the fuzzer to generate more effective test cases.\n\n### Operational guidelines\n\n- Always build and run fuzzing harnesses to validate they work. This can for example be done in a oss-fuzz environment:\n\n```\npython3 infra/helper.py build_fuzzers <project_name>\npython3 infra/helper.py run_fuzzer <project_name> <fuzzer_name> -- -max_total_time=30 # run the fuzzer for 30 seconds to validate it works\npython3 infra/helper.py check_build <project_name>\n```\n\n- If a fuzzer runs into a crash instantly, it's very likely wrong.\n- Always document the rationale for design decisions in the fuzzing harness, and the rationale for why the harness is expected to find bugs. This can be done in a markdown file in the same directory as the fuzzing harness, or in comments in the code of the fuzzing harness itself.\n- Look for function entrypoints that are exposed to untrusted input, and try to design fuzzing harnesses that target these entrypoints. This is often the most effective way to find security bugs.\n- When extending existing fuzzing harnesses, always validate that the existing code coverage does not digress. You should empirically evaluate this and give a justification that no digression has happened, or if it has happened then you should give a justification for why the digression is acceptable in light of the achieved extension.\n- When extending fuzzing harnesses you should give justification for the impact of bugs that they will find.\n\n### Seed corpus and structured generation\n\nA good harness needs a good initial corpus. Place seed files in\n`$OUT/<fuzzer_name>_seed_corpus.zip` and dictionaries in\n`$OUT/<fuzzer_name>.dict`.\n\nFor targets that parse a structured format (binary containers like ELF/PE, or\ncodec/network bitstreams, or text grammars), a few hand-picked sample files\nare rarely enough: random mutation almost never gets past the parser's magic /\nlength / checksum checks, so the deep parsing code stays dark. The most\neffective approach is a **script that constructs structurally-valid inputs\nfrom scratch**, run from `build.sh` and appended to the corpus. It is\nreproducible, needs no external samples, and lets you target specific\ndark-but-reachable code identified from coverage. See the OSS-Fuzz engineer\nskill's [structured seed generation\nreference](../oss-fuzz-engineer/references/structured_seed_generation.md) for\nthe full workflow and `projects/vlc/generate_seeds.py` for a worked example.","tools/vscode-extension/.vscode/extensions.json":"# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/extensions.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/extensions.json)","tools/vscode-extension/.vscode/launch.json":"# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/launch.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/launch.json)","tools/vscode-extension/.vscode/settings.json":"# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/settings.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/settings.json)","tools/vscode-extension/.vscode/tasks.json":"# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/tasks.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/tasks.json)","infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md":"# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md)","infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md":"# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md)","infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md":"# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md)","infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md":"# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"* Use python3 infra/helper.py to build projects and run fuzzers.\n* If doing development on infra/ you should use a venv and if it doesn't already exist, install deps from infra/ci/requirements.txt build/functions/requirements.txt with pip.\n* If doing development on infra/ run python infra/presubmit.py to format, lint and run tests.\n","isInternal":false,"tokens":76,"sizeBytes":334},{"name":"SKILL.md","path":"infra/experimental/agent-skills/fuzzing-go-expert/SKILL.md","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/fuzzing-go-expert/SKILL.md","title":"fuzzing-go-expert","category":"anthropic-skill","format":"markdown","content":"---\nname: fuzzing-go-expert\ndescription:\n  Use this skill to fuzz open source Go software projects.\n---\n\n# Fuzzing Go expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for Go projects integrated into OSS-Fuzz. Go fuzzing uses\nthe native Go fuzzing framework introduced in Go 1.18, which OSS-Fuzz drives\nvia libFuzzer under the hood using `compile_native_go_fuzzer`.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nGo projects must use the Go base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-go\n```\n\nSet `language: go` in `project.yaml`.\n\n### Harness structure\n\nGo fuzz targets are standard Go test functions with the prefix `Fuzz`, placed\nin `_test.go` files (or plain `.go` files that import the testing package):\n\n```go\npackage mypkg\n\nimport (\n    \"testing\"\n    _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\" // required for OSS-Fuzz native fuzzing\n)\n\nfunc FuzzMyTarget(f *testing.F) {\n    // Seed corpus: add representative valid inputs so the fuzzer starts\n    // from a meaningful state rather than empty bytes.\n    f.Add([]byte(\"example input\"))\n    f.Add([]byte(\"another seed\"))\n\n    f.Fuzz(func(t *testing.T, data []byte) {\n        // Call into the target. Ignore expected errors; let unexpected\n        // panics surface as findings.\n        _, _ = ParseSomething(data)\n    })\n}\n```\n\nThe inner `f.Fuzz` callback signature can use typed parameters instead of\n`[]byte` when the target expects structured input:\n\n```go\nf.Fuzz(func(t *testing.T, s string, n int, b bool) {\n    _ = ProcessRecord(s, n, b)\n})\n```\n\n### Building in OSS-Fuzz\n\nUse the `compile_native_go_fuzzer` helper in `build.sh`. It takes the package\nimport path, the function name, and the output binary name:\n\n```bash\n# build.sh\ncp $SRC/fuzz_test.go ./          # copy harness into the module if needed\nprintf \"package mypkg\\nimport _ \\\"github.com/AdamKorcz/go-118-fuzz-build/testing\\\"\\n\" \\\n    > register.go                # required registration shim\ngo mod tidy\ncompile_native_go_fuzzer github.com/owner/repo/pkg FuzzMyTarget fuzz_my_target\n```\n\nFor projects with multiple packages or multiple fuzz targets repeat the call:\n\n```bash\ncompile_native_go_fuzzer github.com/owner/repo/pkg1 FuzzFoo fuzz_foo\ncompile_native_go_fuzzer github.com/owner/repo/pkg2 FuzzBar fuzz_bar\n```\n\n### Seed corpus and dictionaries\n\n- Seed corpus entries go in `$OUT/<fuzzer_name>_seed_corpus/` as individual\n  files, or as a zip at `$OUT/<fuzzer_name>_seed_corpus.zip`.\n- Dictionaries go in `$OUT/<fuzzer_name>.dict` as plaintext token files.\n- Alternatively, add seeds directly via `f.Add(...)` in the harness — these\n  are compiled in and used as the initial corpus.\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks. See the [structured seed generation\n  reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good Go fuzzing harnesses\n\n1. **Targets attack surface**: focus on parsers, decoders, protocol handlers,\n   serialisation/deserialisation, and any API that accepts untrusted bytes or\n   strings.\n2. **Handles expected errors gracefully**: wrap calls in error checks and ignore\n   expected error returns. Only genuine panics and unexpected behaviour are\n   findings.\n3. **Uses typed fuzz parameters** when the target is not purely byte-oriented —\n   Go's fuzzer can mutate `string`, `int`, `bool`, `float64`, etc. directly.\n4. **Avoids non-determinism**: do not use random sources, time, goroutines, or\n   global state that persists between calls.\n5. **Keeps the callback fast**: expensive setup (e.g. parsing config, opening\n   files) belongs outside `f.Fuzz(...)`, not inside the inner function.\n6. **Provides meaningful seeds**: `f.Add(...)` entries should be valid\n   representative inputs so coverage grows from the start.\n7. **Does not get stuck**: avoid code paths that busy-loop or block on I/O\n   inside the fuzz function.\n8. **Includes the registration shim**: the `import _\n   \"github.com/AdamKorcz/go-118-fuzz-build/testing\"` blank import is required\n   for OSS-Fuzz to hook into native Go fuzzing — never omit it.\n\n## What Go fuzzing finds\n\nGo is memory-safe, so the focus shifts from memory-corruption bugs to:\n\n- **Panics**: index out of range, nil pointer dereference, type assertion\n  failures, stack overflows — any unrecovered `panic` is a crash.\n- **Logic bugs**: incorrect parsing, silent data corruption, wrong output for\n  valid input.\n- **Infinite loops / hangs**: code that never returns on certain inputs\n  (detected by OSS-Fuzz's timeout).\n- **Incorrect error handling**: code that should return an error but panics\n  instead, or vice versa.\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash almost always means the harness itself is wrong (e.g.\n  missing error handling, bad seed, wrong package path).\n- Run `go vet ./...` and `go build ./...` inside the module before wrapping in\n  an OSS-Fuzz build to catch compile errors early.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- Document why each entry point was chosen and what class of bugs it may find.\n","frontmatter":{"name":"fuzzing-go-expert","description":"Use this skill to fuzz open source Go software projects."},"isInternal":false,"tokens":1335,"sizeBytes":5520},{"name":"SKILL.md","path":"infra/experimental/agent-skills/fuzzing-jvm-expert/SKILL.md","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/fuzzing-jvm-expert/SKILL.md","title":"fuzzing-jvm-expert","category":"anthropic-skill","format":"markdown","content":"---\nname: fuzzing-jvm-expert\ndescription:\n  Use this skill to fuzz open source JVM projects (Java, Kotlin, Scala, etc.)\n  using Jazzer.\n---\n\n# Fuzzing JVM expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for JVM-based projects (Java, Kotlin, Scala, Groovy)\nintegrated into OSS-Fuzz. JVM fuzzing uses\n[Jazzer](https://github.com/CodeIntelligenceTesting/jazzer), which wraps\nlibFuzzer and instruments JVM bytecode for coverage guidance.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nJVM projects must use the JVM base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-jvm\n```\n\nSet `language: jvm` in `project.yaml`.\n\n### Harness structure — raw bytes\n\nThe simplest Jazzer harness receives raw bytes via `fuzzerTestOneInput`:\n\n```java\nimport com.code_intelligence.jazzer.api.FuzzedDataProvider;\n\npublic class MyTargetFuzzer {\n    public static void fuzzerTestOneInput(byte[] data) {\n        try {\n            MyLibrary.parse(data);\n        } catch (ExpectedExceptionType e) {\n            // Ignore expected exceptions; they are not bugs.\n        }\n    }\n}\n```\n\n### Harness structure — typed input via FuzzedDataProvider\n\n`FuzzedDataProvider` splits the raw byte stream into typed values, which is\nessential for targets that require structured input:\n\n```java\nimport com.code_intelligence.jazzer.api.FuzzedDataProvider;\n\npublic class MyTargetFuzzer {\n    public static void fuzzerTestOneInput(FuzzedDataProvider data) {\n        String header    = data.consumeString(64);\n        int    version   = data.consumeInt();\n        byte[] payload   = data.consumeRemainingAsBytes();\n\n        try {\n            MyLibrary.process(header, version, payload);\n        } catch (IllegalArgumentException | IOException e) {\n            // Expected — not a finding.\n        }\n    }\n}\n```\n\nUseful `FuzzedDataProvider` methods:\n\n| Method | Description |\n|---|---|\n| `consumeBytes(n)` | `byte[]` of length n |\n| `consumeRemainingAsBytes()` | all remaining bytes |\n| `consumeString(maxLen)` | arbitrary String |\n| `consumeAsciiString(maxLen)` | ASCII-only String |\n| `consumeInt()` / `consumeInt(min, max)` | int |\n| `consumeLong()` | long |\n| `consumeBoolean()` | boolean |\n| `consumeDouble()` | double |\n| `pickValue(collection)` | random element |\n\n### One-time setup with `fuzzerInitialize`\n\nIf initialisation is expensive (loading config, creating DB connections, etc.),\nput it in an optional static method that Jazzer calls once before fuzzing:\n\n```java\npublic class MyTargetFuzzer {\n    private static MyClient client;\n\n    public static void fuzzerInitialize() {\n        client = new MyClient(/* static config */);\n    }\n\n    public static void fuzzerTestOneInput(FuzzedDataProvider data) {\n        client.process(data.consumeRemainingAsBytes());\n    }\n}\n```\n\n### Building in OSS-Fuzz\n\nThe `build.sh` pattern for Maven projects:\n\n```bash\n# Build the project JARs.\n$MVN package -DskipTests -Dmaven.javadoc.skip=true\n\n# Collect JARs needed at runtime.\nALL_JARS=\"mylib-1.0.jar\"\nBUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- \"$OUT/%s:\"):$JAZZER_API_PATH\nRUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- \"\\$this_dir/%s:\"):\\$this_dir\n\nfor fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do\n    fuzzer_basename=$(basename -s .java \"$fuzzer\")\n    javac -cp $BUILD_CLASSPATH \"$fuzzer\"\n    cp $SRC/$fuzzer_basename.class $OUT/\n\n    # Wrapper script that launches jazzer_driver with the right arguments.\n    echo \"#!/bin/bash\nthis_dir=\\$(dirname \\\"\\$0\\\")\nif [[ \\\"\\$@\\\" =~ (^| )-runs=[0-9]+($| ) ]]; then\n  mem_settings='-Xmx1900m:-Xss900k'\nelse\n  mem_settings='-Xmx2048m:-Xss1024k'\nfi\nLD_LIBRARY_PATH=\\\"$JVM_LD_LIBRARY_PATH\\\":\\$this_dir \\\\\n\\$this_dir/jazzer_driver --agent_path=\\$this_dir/jazzer_agent_deploy.jar \\\\\n--instrumentation_includes=com.example.** \\\\\n--cp=$RUNTIME_CLASSPATH \\\\\n--target_class=$fuzzer_basename \\\\\n--jvm_args=\\\"\\$mem_settings\\\" \\\\\n\\$@\" > $OUT/$fuzzer_basename\n    chmod u+x $OUT/$fuzzer_basename\ndone\n```\n\nFor Gradle projects replace `$MVN package` with the appropriate Gradle command\nand adjust JAR paths accordingly.\n\n### Seed corpus and dictionaries\n\n- Zip seed files to `$OUT/<fuzzer_name>_seed_corpus.zip`.\n- Place dictionaries at `$OUT/<fuzzer_name>.dict`.\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks. See the [structured seed generation\n  reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good JVM fuzzing harnesses\n\n1. **Targets attack surface**: parsers, deserializers (JSON, XML, Protobuf,\n   custom binary formats), network protocol handlers, template engines, and\n   any API that accepts untrusted bytes or strings.\n2. **Catches expected exceptions**: wrap calls in `try/catch` for all\n   documented exception types. Only unexpected exceptions and crashes are\n   findings.\n3. **Uses `FuzzedDataProvider`** for structured input rather than passing raw\n   bytes to methods that expect well-formed data.\n4. **Initialises heavy state in `fuzzerInitialize`**: client connections,\n   parsers with complex configuration, and loaded schemas should be set up once.\n5. **Avoids non-determinism**: no `Math.random()`, no `System.currentTimeMillis()`\n   in the fuzzing path, no thread spawning.\n6. **Sets `--instrumentation_includes`** to the package prefix of the target\n   library in the wrapper script — without this Jazzer cannot guide fuzzing.\n7. **Configures JVM memory appropriately**: use the `mem_settings` pattern\n   shown above to avoid OOM kills during runs vs. crash reproduction.\n8. **Avoids false positives**: `OutOfMemoryError`, `StackOverflowError`, and\n   `NullPointerException` on invalid input are usually expected — decide which\n   are genuine bugs for this project.\n\n## What JVM fuzzing finds\n\n- **Unexpected exceptions**: `NullPointerException`, `ArrayIndexOutOfBoundsException`,\n  `ClassCastException`, `NumberFormatException` on paths that should not throw.\n- **Assertion errors and contract violations**: internal consistency checks\n  that fail on adversarial input.\n- **Hang / infinite loops**: detected by OSS-Fuzz's timeout.\n- **Security bugs**: deserialization gadgets, path traversal via crafted\n  filenames, SSRF via crafted URLs — depends on the library.\n- **Logic bugs**: incorrect output for valid-ish input.\n\nJazzer can also detect:\n- SQL injection (via JDBC hooks)\n- Path traversal (via file API hooks)\n- Command injection (via `Runtime.exec` hooks)\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash usually means a missing JAR on the classpath or an\n  uncaught expected exception — check `check_build` output carefully.\n- Build the project outside the fuzzing harness first (`mvn package` or\n  `gradle build`) to ensure the project itself compiles cleanly.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- Document why each entry point was chosen and what class of bugs it may find.\n","frontmatter":{"name":"fuzzing-jvm-expert","description":"Use this skill to fuzz open source JVM projects (Java, Kotlin, Scala, etc.) using Jazzer."},"isInternal":false,"tokens":1757,"sizeBytes":7317},{"name":"SKILL.md","path":"infra/experimental/agent-skills/fuzzing-memory-unsafe-expert/SKILL.md","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/fuzzing-memory-unsafe-expert/SKILL.md","title":"fuzzing-memory-unsafe-expert","category":"anthropic-skill","format":"markdown","content":"---\nname: fuzzing-memory-unsafe-expert\ndescription:\n  Use this skill to fuzz open source C/C++ software projects.\n---\n\n# Fuzzing memory-unsafe expert\n\nThis skill provides the agent with the necessary knowledge and tools to fuzz open source software projects, particularly those that are part of the OSS-Fuzz program. The agent can use this skill to build fuzzers, run fuzzing campaigns, analyze results, and improve the fuzzing posture of projects.\n\nThe fuzzing abilities focused on here is libFuzzer-style harnesses, which are commonly used in OSS-Fuzz.\n\n## Threat modelling and attack surface\n\nBefore writing a single line of harness code, decide **what you are trying to\nfind and where an attacker's input actually enters the code**. A harness is\nonly as good as the entry point it targets: a technically-correct harness\npointed at code no attacker can influence finds bugs no maintainer will fix.\nThis step is what separates a valuable harness from a noisy one.\n\n### What a threat model answers\n\nFor the target project, answer these four questions explicitly and write the\nanswers into the harness's rationale doc:\n\n1. **What input is untrusted?** The data an attacker can control — a file\n   downloaded and opened, bytes arriving on a socket, a message from another\n   process, a document pasted into an editor. Trusted input (a config file the\n   admin wrote, a compile-time constant, a path only the program itself\n   constructs) is *not* an attacker's lever and is usually out of scope.\n2. **Where does that input cross a trust boundary?** The exact function(s)\n   where untrusted bytes first reach parsing/processing logic. This is the\n   entry point your harness should call.\n3. **What does the attacker control at that boundary?** The whole buffer? Only\n   a length field, with the rest validated upstream? A filename but not its\n   contents? This determines what your harness should mutate and what it should\n   hold fixed.\n4. **What would count as a real bug here?** A memory-safety violation (ASan/\n   MSan/UBSan finding) on attacker-reachable input is almost always in scope. A\n   crash that requires trusted/malformed *developer* input, or an\n   `assert()`-guarded programmer-error precondition, usually is not — fuzzing it\n   produces findings maintainers reject.\n\n### Identifying the attack surface\n\nConcrete, common attack surfaces in C/C++ projects, and the entry points to\ntarget for each:\n\n- **File-format parsers / loaders** (image, audio, video, fonts, archives,\n  documents). Entry point: the function that takes a buffer or file and decodes\n  it — e.g. `png_read_info`, `TIFFClientOpen`, `av_read_frame`,\n  `archive_read_open_memory`. Attacker controls the whole file. High-value,\n  classic OSS-Fuzz target.\n- **Network / wire-protocol handlers** (packet parsers, TLS records, HTTP,\n  DNS, RPC deserialisation). Entry point: the function fed raw bytes off the\n  wire, e.g. `SSL_read`, `parse_packet`, `deserialize_message`. Attacker\n  controls the byte stream; often you must also drive a state machine (see the\n  reachability note below).\n- **Serialisation / IPC boundaries** (protobuf/JSON/CBOR/ASN.1 decoders,\n  shared-memory messages, clipboard, environment when spawned by another\n  privilege domain). Entry point: the *decode* direction — the untrusted side\n  is bytes-in, not object-out.\n- **Text / query languages** (SQL, regex, template engines, config-language\n  parsers, expression evaluators). Entry point: the compile/parse function that\n  accepts an arbitrary string.\n- **Decompression and codecs** (zlib, lz4, zstd, JPEG/HEIF bitstreams). Entry\n  point: the decompress/decode call on attacker-supplied compressed data —\n  these are prime targets because a small input expands into large, structured\n  work.\n\n### Deriving the harness from the threat model\n\nThe threat model dictates the harness shape:\n\n- **Target the untrusted-input direction only.** Fuzz the *decoder*, not the\n  encoder; the *reader*, not the writer — unless the writer also consumes\n  attacker-controlled data.\n- **Mutate exactly what the attacker controls; fix the rest.** If the attacker\n  controls a document but not the parser's configuration, mutate the document\n  bytes and hold the config constant (set it once in `LLVMFuzzerInitialize`).\n  Fuzzing the config too invents a threat that does not exist and yields\n  rejected findings.\n- **Enter at the real trust boundary, not below it.** Calling a deep internal\n  helper directly may crash on inputs the public API would have rejected\n  upstream — a false positive. Prefer the outermost function an attacker's data\n  actually reaches. If you must call an internal function for coverage, first\n  confirm the upstream validation it assumes, and reproduce that precondition\n  in the harness.\n- **Honour the API contract to avoid false positives.** If a function is\n  documented to require NUL-terminated input, a valid handle, or a\n  pre-allocated output buffer, supply those — a crash from violating the\n  contract is a harness bug, not a target bug (this is the \"True Positives\"\n  characteristic below).\n\n### Reachability: entry point is not enough\n\nAn entry point that is untrusted-reachable in production may still be\n*unreachable* from your harness if getting to the interesting code requires\nstate the harness never sets up — an open session, a completed handshake, a\nprior header packet, a registered codec. Two consequences:\n\n- If the deep code needs prior state, **build that state in the harness**\n  (e.g. feed a valid header, complete the handshake) before feeding the mutated\n  bytes — otherwise the fuzzer never gets past the front door and coverage\n  stays shallow.\n- Cross-check with the coverage data (see the OSS-Fuzz engineer skill): if a\n  file you believe is attacker-reachable sits dark in `summary.json`, decide\n  whether it is *seed-limited* (a better corpus would reach it — write seeds) or\n  *harness-limited* (no input reaches it as the harness stands — the harness\n  itself must set up more state).\n\n### A worked example\n\nConsider a library that loads a custom image format via\n`int img_load(const uint8_t *buf, size_t len, img_opts *opts)`, where `opts`\ncomes from the application, not the file:\n\n- **Untrusted input:** `buf`/`len` (the image file). **Trusted:** `opts`.\n- **Trust boundary / entry point:** `img_load` — the outermost public function\n  an attacker's bytes reach.\n- **Attacker controls:** the entire image buffer, not the options.\n- **Real bug:** any ASan/UBSan finding decoding a crafted image.\n\nThe harness therefore fixes `opts` to a representative default once, and feeds\nthe mutated bytes as `buf`/`len`:\n\n```cpp\n#include <fuzzer/FuzzedDataProvider.h>\n\nstatic img_opts g_opts;  // trusted config, set once — not fuzzed.\n\nextern \"C\" int LLVMFuzzerInitialize(int *argc, char ***argv) {\n    img_opts_default(&g_opts);   // represents the real application's setup\n    return 0;\n}\n\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {\n    // Attacker controls the whole file; feed it directly.\n    img_load(data, size, &g_opts);\n    return 0;\n}\n```\n\nFuzzing `opts` instead, or calling an internal `decode_scanline` directly with\nraw bytes, would either invent a non-existent threat or trip asserts the public\nAPI prevents — both produce findings maintainers will not act on.\n\n## Fundamental Concepts\n\n### Fuzzing harness core function\n\nA fuzzing harness is a function that takes a byte array as input and processes it in a way that can trigger bugs or vulnerabilities in the software being tested. The core function of a fuzzing harness typically looks like this:\n\n```cpp\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {\n    // Process the input data and trigger potential bugs\n    return 0; // Return 0 to indicate successful processing\n}\n```\n\nReturn `0` in all normal cases. Return `-1` to tell libFuzzer to reject an\ninput and not add it to the corpus (rarely needed). Never `exit()` on bad\ninput — it aborts the whole run and breaks coverage tooling.\n\n### Extracting typed input with FuzzedDataProvider\n\nMost non-trivial targets do not take a single flat byte buffer — they need an\ninteger here, a length there, a string, several sub-buffers. Passing the raw\n`data`/`size` directly to such an API means the fuzzer almost never produces a\nwell-formed call. `FuzzedDataProvider` splits the one input stream into typed\nvalues, so libFuzzer's mutations map onto the parameters the target actually\nexpects. It is the standard tool for this in OSS-Fuzz (used by well over a\nhundred projects) and is shipped in the base image — no dependency to add:\n\n```cpp\n#include <fuzzer/FuzzedDataProvider.h>\n\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {\n    FuzzedDataProvider fdp(data, size);\n\n    // Consume typed, bounded values up front...\n    int         width  = fdp.ConsumeIntegralInRange<int>(1, 4096);\n    bool        strict = fdp.ConsumeBool();\n    std::string name   = fdp.ConsumeRandomLengthString(64);\n    // ...then hand the rest of the bytes to the payload argument.\n    std::vector<uint8_t> payload = fdp.ConsumeRemainingBytes<uint8_t>();\n\n    my_decode(name.c_str(), width, strict, payload.data(), payload.size());\n    return 0;\n}\n```\n\nCommonly used methods (see `compiler-rt`'s `FuzzedDataProvider.h` for the full\nset):\n\n| Method | Description |\n|---|---|\n| `ConsumeIntegral<T>()` | one integer of type `T` |\n| `ConsumeIntegralInRange<T>(min, max)` | integer bounded to `[min, max]` — use this to pick sizes, indices, enum values |\n| `ConsumeBool()` | one boolean |\n| `ConsumeEnum<E>()` | a value of a scoped enum with `kMaxValue` |\n| `ConsumeFloatingPoint<T>()` / `...InRange(min, max)` | float/double |\n| `ConsumeRandomLengthString(max)` | a `std::string` whose length the fuzzer controls (stops at an escaped `\\`) |\n| `ConsumeBytes<T>(count)` / `ConsumeBytesAsString(count)` | exactly `count` bytes |\n| `ConsumeRemainingBytes<T>()` / `ConsumeRemainingBytesAsString()` | everything left |\n| `remaining_bytes()` | how many bytes are left to consume |\n\nGuidance:\n\n- **Consume in a fixed order and document it.** The mapping from bytes to\n  parameters must be stable, or a saved crash will not reproduce.\n- **Consume the variable-length / \"rest of the input\" argument last** with\n  `ConsumeRemaining...`. Consuming a fixed count first and the remainder last\n  keeps the layout robust to mutation.\n- **Bound sizes and indices with `ConsumeIntegralInRange`** rather than masking\n  a raw integer — it wastes fewer inputs and keeps allocations sane.\n- Use FDP when the target needs structure; for a target that genuinely takes\n  one opaque buffer (a single `parse(data, size)`), pass `data`/`size` straight\n  through — FDP would only add noise.\n\n### One-time setup with LLVMFuzzerInitialize\n\nIf the harness needs setup that must happen once before fuzzing (parsing\n`argv`, setting environment variables, initialising a library global), put it\nin the optional `LLVMFuzzerInitialize` hook, which libFuzzer calls once at\nstartup — never do per-input work there:\n\n```cpp\nextern \"C\" int LLVMFuzzerInitialize(int *argc, char ***argv) {\n    setenv(\"HOME\", \"/tmp\", 1);\n    my_library_global_init();\n    return 0;\n}\n```\n\nKeep expensive but per-process-constant state (loaded config, a compiled\nschema, an allocated context reused across inputs) in a file-scope\n`static`/global initialised once — either here or lazily on the first\n`LLVMFuzzerTestOneInput` call — so it is not rebuilt on every iteration.\n\n### Sanitizers are the bug oracle\n\nA C/C++ harness rarely detects a bug by itself — the sanitizer the project is\nbuilt with is what turns silent memory corruption into a crash the fuzzer can\ncatch. OSS-Fuzz builds each target under a sanitizer (default AddressSanitizer;\nalso UndefinedBehaviorSanitizer and MemorySanitizer):\n\n- **ASan** — heap/stack/global buffer overflows, use-after-free, double-free,\n  leaks. The default and highest-value oracle.\n- **UBSan** — signed overflow, invalid shifts, misaligned/`null` pointer use,\n  bad casts, invalid enum values.\n- **MSan** — reads of uninitialised memory. Requires *all* linked code\n  (including dependencies) to be instrumented, or it reports false positives —\n  only enable it when the whole dependency chain is built under MSan.\n\nDesign implication: the harness's job is to *reach* untrusted-input-driven\nmemory operations with enough variety; the sanitizer reports the violation.\n`build.sh` must compile both the target library and the harness with the\nOSS-Fuzz `$CFLAGS`/`$CXXFLAGS` (which carry the sanitizer + coverage flags) —\nlinking against a separately, non-instrumented build silently disables the\noracle and coverage guidance.\n\n### Building in OSS-Fuzz\n\n`build.sh` compiles the project (as a static library where possible) and then\ncompiles + links each harness against it with `$LIB_FUZZING_ENGINE`. Always use\nthe OSS-Fuzz-provided `$CC`/`$CXX` and `$CFLAGS`/`$CXXFLAGS` so instrumentation\nand the sanitizer are applied:\n\n```bash\n# build.sh — build the library with instrumentation, statically.\nmkdir build && cd build\ncmake -DBUILD_SHARED_LIBS=OFF ..     # a static .a is easiest to link the harness against\nmake -j$(nproc)\ncd ..\n\n# Compile and link each harness against the instrumented library.\nfor f in $SRC/project/fuzz/*_fuzzer.cc; do\n    fuzzer=$(basename \"$f\" _fuzzer.cc)\n    $CXX $CXXFLAGS -std=c++17 -I$SRC/project/include \\\n        \"$f\" -o \"$OUT/${fuzzer}\" \\\n        $LIB_FUZZING_ENGINE \"$SRC/project/build/libproject.a\"\ndone\n```\n\nKey points:\n\n- Link the harness with **`$LIB_FUZZING_ENGINE`**, not a hardcoded\n  `-fsanitize=fuzzer` — this lets OSS-Fuzz swap the engine (libFuzzer, AFL++,\n  Centipede, or the coverage/`check_build` no-op engine).\n- Prefer a **static** project build; it avoids `LD_LIBRARY_PATH` juggling at\n  run time and ensures the linked code is instrumented.\n- Copy seed corpora (`$OUT/<fuzzer>_seed_corpus.zip`) and dictionaries\n  (`$OUT/<fuzzer>.dict`) in the same script.\n\n### Examples of good harnesses already in OSS-Fuzz\n\nStudy existing harnesses before writing your own — they show the idioms above\napplied to real projects, and matching an established style makes your harness\neasier for maintainers to accept. Each example below is checked into this\nrepository; open the file and read it in full.\n\n- **`projects/sentencepiece/sample_encode_fuzzer.cc`** — the canonical\n  `FuzzedDataProvider` split. It carves the one input into an `int`\n  (`ConsumeIntegral`), a `float` (`ConsumeFloatingPoint`) and the remaining\n  bytes as the text argument (`ConsumeRemainingBytesAsString`), then calls\n  `SampleEncodeAsSerializedProto(text, nbest, alpha)`. Note the ordering: the\n  fixed-size scalars are consumed first and the variable-length string last.\n  This is the template whenever the target API takes several typed parameters\n  rather than one buffer.\n\n- **`projects/spdlog/fuzz/pattern_fuzzer.cc`** — lazy one-time initialisation\n  and a tightly-scoped threat model. A `static` logger is created on the first\n  call and reused across iterations (never rebuilt per input), it guards\n  `size == 0`, and it fuzzes exactly one attacker-relevant entry point:\n  `spdlog::set_pattern(str)`, the format-pattern parser. It does *not* fuzz the\n  logging config — a clean example of \"mutate only what the attacker controls.\"\n\n- **`projects/file/magic_fuzzer_fd.cc`** — `LLVMFuzzerInitialize` for expensive\n  setup, and feeding an API that needs a real file descriptor. The magic\n  database is loaded once in an `Environment` built from `argv[0]`'s directory\n  (setup that must not repeat per input), and each input is written to a\n  `FuzzerTemporaryFile` so it can be handed to `magic_descriptor(fd)`. Use this\n  pattern when the target only accepts a path/`fd` rather than an in-memory\n  buffer — but note that going through a temp file is slower, so prefer an\n  in-memory entry point when the library exposes one.\n\nWhen extending an existing OSS-Fuzz project, the best reference is that\nproject's *own* existing harnesses: match their file layout, naming\n(`*_fuzzer.cc`), build-script wiring and error-handling conventions.\n\n### Characteristics found in good fuzzing harnesses\n\nThe below are characteristics commonly found in good fuzzing harnesses, which contribute to their effectiveness in finding bugs. They are not all necessary for a good harness and at times it may even be desirable to actively not pursue some of them.\n\n1. **Simplicity**: The harness should be simple and focused on processing the input data without unnecessary complexity.\n2. **Coverage**: The harness should aim to cover as much of the codebase as possible, including edge cases and error handling paths.\n3. **Determinism**: The harness should produce consistent results for the same input, allowing for reliable reproduction of bugs.\n4. **Performance**: The harness should be efficient in processing inputs to maximize the number of test cases that can be executed in a given time frame.\n5. **Error Handling**: The harness should include robust error handling to capture and report any issues that arise during fuzzing.\n6. **True Positives**: The harness should be designed to have no false positives, ensuring that reported issues are genuine bugs. This means all issues found by the fuzzer is something the maintainers are interested in fixing.\n7. **Matches threat model**: The harness should be designed to target specific types of vulnerabilities that are relevant to the project being fuzzed.\n8. **Hits code on the attack surface**: The harness should be designed to target code that is exposed to untrusted input, such as network interfaces, file parsers, or APIs.\n9. **Enough entropy**: The harness should be designed to allow for a wide range of inputs, providing enough variability to trigger different code paths and potential bugs.\n10. **Follows the code structure**: The harness should be designed to follow the structure of the codebase, making it easier to identify and target specific areas of interest.\n11. **Follows code conventions**: The harness should follow the coding conventions of the project, making it easier for maintainers to understand and integrate the harness into the codebase.\n12. **Does not get stuck**: The harness should be designed to avoid getting stuck on certain inputs or code paths, allowing the fuzzer to continue exploring other areas of the codebase.\n13. **Includes dictionary**: The harness should include a dictionary of known inputs or patterns that are relevant to the project, helping the fuzzer to generate more effective test cases.\n\n### Operational guidelines\n\n- Always build and run fuzzing harnesses to validate they work. This can for example be done in a oss-fuzz environment:\n\n```\npython3 infra/helper.py build_fuzzers <project_name>\npython3 infra/helper.py run_fuzzer <project_name> <fuzzer_name> -- -max_total_time=30 # run the fuzzer for 30 seconds to validate it works\npython3 infra/helper.py check_build <project_name>\n```\n\n- If a fuzzer runs into a crash instantly, it's very likely wrong.\n- Always document the rationale for design decisions in the fuzzing harness, and the rationale for why the harness is expected to find bugs. This can be done in a markdown file in the same directory as the fuzzing harness, or in comments in the code of the fuzzing harness itself.\n- Look for function entrypoints that are exposed to untrusted input, and try to design fuzzing harnesses that target these entrypoints. This is often the most effective way to find security bugs.\n- When extending existing fuzzing harnesses, always validate that the existing code coverage does not digress. You should empirically evaluate this and give a justification that no digression has happened, or if it has happened then you should give a justification for why the digression is acceptable in light of the achieved extension.\n- When extending fuzzing harnesses you should give justification for the impact of bugs that they will find.\n\n### Seed corpus and structured generation\n\nA good harness needs a good initial corpus. Place seed files in\n`$OUT/<fuzzer_name>_seed_corpus.zip` and dictionaries in\n`$OUT/<fuzzer_name>.dict`.\n\nFor targets that parse a structured format (binary containers like ELF/PE, or\ncodec/network bitstreams, or text grammars), a few hand-picked sample files\nare rarely enough: random mutation almost never gets past the parser's magic /\nlength / checksum checks, so the deep parsing code stays dark. The most\neffective approach is a **script that constructs structurally-valid inputs\nfrom scratch**, run from `build.sh` and appended to the corpus. It is\nreproducible, needs no external samples, and lets you target specific\ndark-but-reachable code identified from coverage. See the OSS-Fuzz engineer\nskill's [structured seed generation\nreference](../oss-fuzz-engineer/references/structured_seed_generation.md) for\nthe full workflow and `projects/vlc/generate_seeds.py` for a worked example.","frontmatter":{"name":"fuzzing-memory-unsafe-expert","description":"Use this skill to fuzz open source C/C++ software projects."},"isInternal":false,"tokens":4895,"sizeBytes":20983},{"name":"SKILL.md","path":"infra/experimental/agent-skills/fuzzing-python-expert/SKILL.md","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/fuzzing-python-expert/SKILL.md","title":"fuzzing-python-expert","category":"anthropic-skill","format":"markdown","content":"---\nname: fuzzing-python-expert\ndescription:\n  Use this skill to fuzz open source Python software projects using Atheris.\n---\n\n# Fuzzing Python expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for Python projects integrated into OSS-Fuzz. Python\nfuzzing uses [Atheris](https://github.com/google/atheris), which wraps libFuzzer\nand instruments Python bytecode for coverage-guided fuzzing.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nPython projects must use the Python base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-python\n```\n\nSet `language: python` in `project.yaml`.\n\n### Harness structure\n\nA Python fuzz target is a `.py` file (named `fuzz_<target>.py` by convention)\nthat follows this pattern:\n\n```python\n#!/usr/bin/python3\nimport sys\nimport atheris\n\n# Import the module under test after atheris.instrument_imports() or within\n# the atheris.instrument_all() context so bytecode is instrumented.\n\ndef TestOneInput(data):\n    fdp = atheris.FuzzedDataProvider(data)\n    # Extract typed values from the raw fuzzer bytes.\n    value = fdp.ConsumeString(128)\n    try:\n        my_module.parse(value)\n    except (ValueError, TypeError, KeyError):\n        # Expected exceptions from invalid input are not bugs.\n        pass\n\ndef main():\n    atheris.instrument_all()   # instrument all loaded Python modules\n    atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True)\n    atheris.Fuzz()\n\nif __name__ == \"__main__\":\n    main()\n```\n\n### Instrumenting imports selectively\n\nWhen `instrument_all()` is too broad (e.g. causes conflicts with C extensions),\ninstrument specific modules using the `instrument_imports()` context manager:\n\n```python\nimport atheris\nwith atheris.instrument_imports():\n    import my_module\n    import my_module.subpackage\n```\n\n### FuzzedDataProvider reference\n\n`atheris.FuzzedDataProvider` splits the raw byte stream into typed values:\n\n| Method | Description |\n|---|---|\n| `ConsumeBytes(count)` | `bytes` of length count |\n| `ConsumeByteList(count)` | `list[int]` of length count |\n| `ConsumeString(count)` | decoded `str` (may contain surrogates) |\n| `ConsumeUnicode(count)` | `str` without surrogates |\n| `ConsumeUnicodeNoSurrogates(count)` | strict `str` |\n| `ConsumeInt(nbytes)` | signed int from nbytes |\n| `ConsumeIntInRange(min, max)` | int in range |\n| `ConsumeFloat()` | float |\n| `ConsumeBool()` | bool |\n| `ConsumeIntList(count, nbytes)` | list of ints |\n| `PickValueInList(lst)` | random element |\n| `ConsumeRemainingBytes()` | all remaining bytes |\n\n### Building in OSS-Fuzz\n\n`build.sh` installs the target package and uses the `compile_python_fuzzer`\nhelper to turn each `fuzz_*.py` file into a standalone fuzzer binary in `$OUT`:\n\n```bash\n# build.sh\n\n# Install the package under test.\npip3 install .\n\n# Compile all fuzz targets found in $SRC.\nfor fuzzer in $(find $SRC -name 'fuzz_*.py'); do\n    compile_python_fuzzer \"$fuzzer\"\ndone\n```\n\n`compile_python_fuzzer` handles linking against Atheris and libFuzzer and\nproduces an executable in `$OUT` named after the `.py` file.\n\n### Seed corpus and dictionaries\n\n- Place seed files in `$OUT/<fuzzer_name>_seed_corpus/` or zip them as\n  `$OUT/<fuzzer_name>_seed_corpus.zip`.\n- Dictionaries go to `$OUT/<fuzzer_name>.dict` — especially valuable for\n  text-format parsers (JSON, XML, YAML, CSV, etc.).\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks. See the [structured seed generation\n  reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good Python fuzzing harnesses\n\n1. **Instruments the right modules**: use `instrument_all()` for simplicity or\n   `instrument_imports()` for targeted instrumentation. Without instrumentation\n   coverage guidance is blind.\n2. **Targets attack surface**: parsers, template engines, serialisation\n   (pickle, JSON, YAML, XML), network protocol handling, and any API that\n   accepts untrusted strings or bytes.\n3. **Catches expected exceptions**: wrap target calls in `try/except` for the\n   documented exception types the target raises on bad input. Only unexpected\n   exceptions and hard crashes are findings.\n4. **Uses `FuzzedDataProvider` for structured input** rather than feeding raw\n   bytes directly to APIs that expect text — most Python APIs work on strings,\n   not bytes.\n5. **Avoids importing under test inside `TestOneInput`**: imports should happen\n   at module level (inside the `instrument_imports()` block if used) so they\n   are instrumented and not re-executed per iteration.\n6. **Is fast**: avoid file I/O, network calls, or subprocess invocations inside\n   `TestOneInput`.\n7. **Avoids non-determinism**: no `random`, no `datetime.now()`, no\n   `os.urandom()` inside the fuzz function.\n8. **Enables Python coverage**: pass `enable_python_coverage=True` to\n   `atheris.Setup` for bytecode-level coverage tracking.\n\n## What Python fuzzing finds\n\nPython is memory-safe, so the focus is on:\n\n- **Unhandled exceptions**: `ValueError`, `RecursionError`, `MemoryError`,\n  `UnicodeDecodeError`, and any exception the library should have caught and\n  converted to a clean error.\n- **`AssertionError`**: internal invariant violations triggered by crafted\n  input.\n- **Hangs / infinite loops**: detected by OSS-Fuzz's timeout.\n- **Crashes in C extensions**: Python libraries that wrap C code (e.g. lxml,\n  Pillow, cryptography) can still have memory-corruption bugs in their C layer,\n  which Atheris will surface because libFuzzer runs the whole process.\n- **Logic errors**: incorrect output, silent data corruption, wrong parsing\n  results on edge-case inputs.\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash usually means an exception is being raised on every input.\n  Run the harness locally (`python3 fuzz_target.py`) on a sample input to\n  debug before building through OSS-Fuzz.\n- Test the harness locally before the OSS-Fuzz build:\n  ```python\n  python3 fuzz_target.py <seed_file>\n  ```\n  Atheris supports running in single-input mode outside libFuzzer.\n- Install the package locally (`pip3 install .`) and iterate quickly before\n  going through the Docker build.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- Document why each entry point was chosen and what class of bugs it may find.\n","frontmatter":{"name":"fuzzing-python-expert","description":"Use this skill to fuzz open source Python software projects using Atheris."},"isInternal":false,"tokens":1605,"sizeBytes":6700},{"name":"SKILL.md","path":"infra/experimental/agent-skills/fuzzing-rust-expert/SKILL.md","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/fuzzing-rust-expert/SKILL.md","title":"fuzzing-rust-expert","category":"anthropic-skill","format":"markdown","content":"---\nname: fuzzing-rust-expert\ndescription:\n  Use this skill to fuzz open source Rust software projects.\n---\n\n# Fuzzing Rust expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for Rust projects integrated into OSS-Fuzz. Rust fuzzing\nuses cargo-fuzz with the `libfuzzer_sys` crate, which drives libFuzzer.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nRust projects must use the Rust base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-rust\n```\n\nSet `language: rust` in `project.yaml`.\n\n### Harness structure\n\nRust fuzz targets live in `fuzz/fuzz_targets/<name>.rs` within the crate being\nfuzzed. The minimal harness using raw bytes:\n\n```rust\n#![no_main]\nuse libfuzzer_sys::fuzz_target;\n\nfuzz_target!(|data: &[u8]| {\n    // Call into the target. The fuzzer will mutate `data` on every iteration.\n    let _ = my_crate::parse(data);\n});\n```\n\nFor structured fuzzing using the `arbitrary` crate (preferred when the target\nexpects typed input):\n\n```rust\n#![no_main]\nuse libfuzzer_sys::fuzz_target;\nuse arbitrary::Arbitrary;\n\n#[derive(Debug, Arbitrary)]\nstruct MyInput {\n    header: u8,\n    payload: Vec<u8>,\n    flags: u32,\n}\n\nfuzz_target!(|input: MyInput| {\n    let _ = my_crate::process(input.header, &input.payload, input.flags);\n});\n```\n\nThe `Cargo.toml` for the fuzz directory must declare dependencies:\n\n```toml\n# fuzz/Cargo.toml\n[package]\nname = \"my-crate-fuzz\"\nversion = \"0.0.0\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nlibfuzzer-sys = \"0.4\"\narbitrary = { version = \"1\", features = [\"derive\"] }   # only if using structured fuzzing\n\n[dependencies.my-crate]\npath = \"..\"\n\n[[bin]]\nname = \"fuzz_target_name\"\npath = \"fuzz_targets/fuzz_target_name.rs\"\ntest = false\ndoc = false\n```\n\n### Building in OSS-Fuzz\n\n`build.sh` uses `cargo fuzz build` and then copies binaries to `$OUT`:\n\n```bash\n# build.sh\ncd $SRC/<crate-dir>\ncargo fuzz build -O   # -O enables release optimisations; important for performance\n\nFUZZ_TARGET_OUTPUT_DIR=$SRC/<crate-dir>/target/x86_64-unknown-linux-gnu/release\nfor f in fuzz/fuzz_targets/*.rs; do\n    name=$(basename \"${f%.*}\")\n    cp \"$FUZZ_TARGET_OUTPUT_DIR/$name\" \"$OUT/\"\ndone\n```\n\nIf the project requires a nightly toolchain, set it in the Dockerfile:\n\n```dockerfile\nENV RUSTUP_TOOLCHAIN=nightly\n```\n\nOr pin to a specific nightly for reproducibility:\n\n```dockerfile\nENV RUSTUP_TOOLCHAIN=nightly-2025-07-03\n```\n\n### Seed corpus and dictionaries\n\n- Place seed files in `fuzz/corpus/<target_name>/` within the repo; they are\n  automatically picked up by cargo-fuzz and can be zipped for OSS-Fuzz.\n- To ship a corpus with OSS-Fuzz copy a zip to `$OUT/<target_name>_seed_corpus.zip`.\n- Dictionaries go to `$OUT/<target_name>.dict`.\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks (note: cargo-fuzz's `arbitrary` is the better route when the\n  target takes typed data rather than a byte format). See the [structured seed\n  generation reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good Rust fuzzing harnesses\n\n1. **Targets attack surface**: parsers, deserializers, protocol implementations,\n   unsafe blocks, and any API that processes untrusted bytes.\n2. **Uses structured fuzzing** (`arbitrary`) when the target expects typed data\n   rather than raw bytes — this dramatically improves coverage.\n3. **Handles expected errors**: `Result` and `Option` should be let-bound and\n   ignored (`let _ = ...`). Only actual panics are findings.\n4. **Avoids panicking on every input**: do not use `.unwrap()` or `.expect()`\n   on fallible operations driven by fuzz input — these create false positives.\n5. **Avoids non-determinism**: no `rand`, no system time, no thread spawning\n   inside the fuzz callback.\n6. **Is fast**: avoid I/O, heavy allocations, or expensive setup inside the\n   callback; do those outside the `fuzz_target!` macro if needed with\n   `LazyLock` / `OnceLock`.\n7. **Considers `unsafe` code**: if the crate has `unsafe` blocks, write\n   harnesses that exercise those paths — this is where memory bugs can still\n   occur in Rust.\n8. **Builds in release mode** (`-O`): fuzzing in debug mode is much slower.\n\n## What Rust fuzzing finds\n\nRust's ownership model prevents most memory-corruption bugs, but fuzzing still\nfinds:\n\n- **Panics**: `unwrap`/`expect` on `None`/`Err`, index out of bounds,\n  arithmetic overflow in debug mode, explicit `panic!` calls.\n- **`unsafe` bugs**: use-after-free, out-of-bounds reads/writes, undefined\n  behaviour in `unsafe` blocks — these are real memory bugs.\n- **Logic errors**: incorrect parsing, data corruption, wrong output.\n- **Hangs**: infinite loops triggered by crafted input.\n- **Stack overflows**: deep recursion on adversarial input.\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash usually means a `panic!` on every input — check for\n  `.unwrap()` calls on fuzz-driven paths and replace with `if let` or `?`.\n- Run `cargo build` and `cargo test` inside the crate before adding the fuzz\n  harness to catch pre-existing compilation errors.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- If the crate uses `no_std`, use `libfuzzer-sys`'s `no_std` feature and ensure\n  the harness does not rely on `std`.\n- Document why each entry point was chosen and what class of bugs it may find.\n","frontmatter":{"name":"fuzzing-rust-expert","description":"Use this skill to fuzz open source Rust software projects."},"isInternal":false,"tokens":1472,"sizeBytes":5736},{"name":"code_coverage.md","path":"infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md)","tokens":300,"sizeBytes":269},{"name":"helper.md","path":"infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md)","tokens":300,"sizeBytes":255},{"name":"oss_fuzz_project_structure.md","path":"infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md)","tokens":300,"sizeBytes":295},{"name":"structured_seed_generation.md","path":"infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md)","tokens":300,"sizeBytes":295},{"name":"SKILL.md","path":"infra/experimental/agent-skills/oss-fuzz-engineer/SKILL.md","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/SKILL.md","title":"oss-fuzz-engineer","category":"anthropic-skill","format":"markdown","content":"---\nname: oss-fuzz-engineer\ndescription:\n  Use this skill to interact with the OSS-Fuzz infrastructure.\n---\n\n# OSS-Fuzz engineer\n\nThis skill guides the agent how to use the OSS-Fuzz infrastructure to find and report bugs in open source software. The agent can use this skill to integrate new projects, extend and improve the fuzzing posture of projects, run fuzzing campaigns, and fix broken existing OSS-Fuzz projects.\n\nWhen working on OSS-Fuzz tasks then you should also use any fuzzing related skills you have, such as code analysis and fuzzing harness writing skills, to achieve the best results.\n\n## Workflows\n\nThere are multiple common workflows that an OSS-Fuzz engineer might follow and we describe some imporant ones here.\n\n### Integrating a new project\n\nGiven a reference to an open source project, such as a link to a GitHub repository, the agent can follow these steps to integrate the project into OSS-Fuzz:\n1. **Assess the project**: The agent should first assess whether the project is suitable for fuzzing. This includes checking if the project is open source, has a significant user base, and contains code that can be fuzzed (e.g., C/C++ code).\n2. **Set up the environment**: The agent should set up the necessary environment for fuzzing the project. This includes:\n- A Dockerfile that defines the build environment for the project, using the OSS-Fuzz base images.\n- A build script that compiles the project with the necessary instrumentation for fuzzing.\n- A project.yaml that provides the necessary OSS-Fuzz meta data.\n3. **Write fuzz targets**: The agent should write fuzz targets for the project. Fuzz targets are small programs that call into the project's code and are used by the fuzzing engine to generate inputs and find bugs.\n4. **Test the integration**: The agent should test the integration by running the fuzz targets locally and ensuring that they work correctly. This project should be continue until the fuzz targets build and run well, and the OSS-Fuzz `check_build` script passes without errors.\n5. **Conclude the integration**: Once the integration is complete, the agent should conclude with a message of the results achieved and the next steps the security engineer guiding the agent should take. The agent should *not* make any commits or push anything to GitHub, but should conclude on the work for the security engineer to review. The agent should never submit any changes to OSS-Fuzz's Github.\n\nWhen doing this type of work it's crucial the agent uses any skills it has related to code analysis and fuzzing harness writing.\n\n### Extending and improving fuzzing posture\n\nThe agent can also be used to extend and improve the fuzzing posture of existing OSS-Fuzz projects. This can include:\n- Adding new fuzz targets to cover more code paths and functionality.\n- Improving existing fuzz targets to make them more effective at finding bugs.\n- Updating the build environment to include new dependencies or tools that can enhance fuzzing.\n- Analyzing fuzzing results and identifying areas of the code that are not well covered by existing fuzz targets, and then writing new fuzz targets to cover those areas.\n\nA useful approach for extending a project is to study the latest code coverage report for the project, which is publicly available, to identify areas of the code that are not well covered by existing fuzz targets. The agent can then write new fuzz targets to cover those areas, and test them locally before concluding on the work for the security engineer to review.\n\n**Critical: avoid targeting already-covered code.** The most common mistake when extending an OSS-Fuzz project is writing harnesses that target functions already well-exercised by the existing production fuzzer corpus. Before selecting any target function:\n\n1. Fetch the latest public `summary.json` via the `latest_report_info/<project>.json` pointer (never guess the date). See the [code coverage reference](references/code_coverage.md) for the pointer, the JSON schema, and how to read it.\n2. Parse the per-file metrics. Line % is triage only — use the **functions** metric (which functions are never entered ⇒ a new harness may be needed) and the **regions/branches** metric (reached function, dark branches ⇒ a corpus/seed problem) to decide *what kind* of gap each file has. Relying on line % alone throws away the signals that tell harness-work from seed-work apart.\n3. Build an explicit blocklist of already-covered files (≥ 50% lines with most functions covered) — do NOT write harnesses whose primary target lives in one of these files.\n4. Only select targets from files with genuinely low coverage (< 30% lines hit), and classify the gap with the functions-vs-branches split before acting.\n\nReading the source code and identifying \"important-looking\" functions is not sufficient — important functions are frequently already covered. Coverage data is the authoritative source of truth for what needs work, and Fuzz Introspector (<https://introspector.oss-fuzz.com>) additionally surfaces reachable-but-unfuzzed functions — see the code coverage reference for the full workflow.\n\n**Structured seed generation.** Adding a new harness is not the only way to extend coverage — often the existing harnesses already reach dark code, but the corpus never produces inputs valid enough to enter it. When a target parses a structured format (binary containers, codec/network bitstreams, text grammars), a script that constructs structurally-valid inputs from scratch is frequently the highest-leverage, lowest-review-cost improvement: random bytes rarely pass a parser's early magic/length/checksum checks, so the deep logic stays dark until seeded. Drive this the same coverage-first way: pick reachable files that are dark in `summary.json`, generate seeds that target them, validate each one actually parses, append them to the existing corpora (never replace), and confirm the union does not digress. See the [structured seed generation reference](references/structured_seed_generation.md) for the full workflow, construction techniques, per-fuzzer tailoring, and pitfalls, and `projects/vlc/generate_seeds.py` for a worked example.\n\nUse the local code coverage feature of the `python3 infra/helper.py` tool to generate code coverage reports for fuzz targets locally, for example to validate the code coverage achieved by a new fuzz target. This can be done by running `python3 infra/helper.py introspector --coverage-only PROJECT_NAME` and then studying the generated report in e.g. build/out/PROJECT_NAME/report. Some examples of this include:\n\n```\n# Generate a coverage report for htslib OSS-Fuzz project from running each\n# fuzzer for 30 seconds, and store coverage directory in `htslib-cov-1`.\npython3 infra/helper.py introspector --coverage-only --seconds 30 --out htslib-cov-1 htslib\n\n# Generate a coverage report for leveldb OSS-Fuzz project from running each\n# fuzzer for 45 seconds, and store coverage directory in `leveldb-cov-1`.\npython3 infra/helper.py introspector --coverage-only --seconds 45 --out leveldb-cov-1 leveldb\n```\n\nThe user may provide directions on how to extend the fuzzing, and it's crucial to follow instructions on this matter. For example, the user may ask to focus on a specific area of the code, or to target specific types of vulnerabilities. The agent should always provide a clear explanation of the rationale for each extension or improvement made to the fuzzing posture of the project.\n\nWhen extending an OSS-Fuzz project it's crucial to have a good understanding of the target code. To this end, it's often useful to get a local version of the target source code into the OSS-Fuzz project structure to make working with the target project easy. This involves e.g. studying the `Dockerfile` of the target project, finding the e.g. `git clone` of the target project, and then cloning this repository locally and using e.g. `COPY` instead of `RUN git clone` in the Dockerfile to get the source code into the container.\n\nThe agent should always provide clear technical justification for each extension.\n\nWhen doing this type of work it's crucial the agent uses any skills it has related to code analysis and fuzzing harness writing. It's important each extension is done through a personal assessment of the current fuzzing posture of the project, and a clear explanation of the rationale for each extension or improvement. The agent should never make any commits or push anything to GitHub, but should conclude on the work for the security engineer to review. The agent should never submit any changes to OSS-Fuzz's Github.\n\nIt is crucial when extending existing OSS-Fuzz project you must validate the existing code coverage does not digress. You should empirically evaluate this and give a justification that no digression has happened, or if it has happened then you should give a justification for why the digression is acceptable in light of the achieved extension.\n\nUnless otherwise specified, the agent should focus on improving a single fuzzing harness for the target project, and not focus on making broad changes that will take a long time to review. Simple changes are often more effective than broad large changes.\n\n### Fixing broken existing OSS-Fuzz projects\n\nThe agent can also be used to fix broken existing OSS-Fuzz projects. This can include:\n- Identifying and fixing build issues that prevent fuzz targets from running correctly.\n- Updating dependencies or build scripts to ensure that the project can be fuzzed effectively.\n- Analyzing fuzzing results to identify and fix issues that are causing the fuzzing campaign to fail or produce unreliable results.\n\nA given OSS-Fuzz project must succeed with:\n\n```\npython3 infra/helper.py build_fuzzers PROJECT_NAME\npython3 infra/helper.py check_build PROJECT_NAME\n```\n\nThe agent should never make any commits or push anything to GitHub, but should conclude on the work for the security engineer to review. The agent should never submit any changes to OSS-Fuzz's Github.\n\n\n### Chronos integration\n\nA common task for an OSS-Fuzz engineer is to add Chronos support for a given OSS-Fuzz project.\n\nChronos is a feature of OSS-Fuzz that makes it possible to quickly rebuild OSS-Fuzz projects and run unit tests of a given OSS-Fuzz project. This is used to efficiently validate e.g. patches of a project without having to rebuild the entire target project image.\n\nTo add Chronos support a project needs to have two key scripts:\n\n- replay_build.sh: used to quickly rebuild the project without network access.\n- run_tests.sh: used to run unit tests of the project without network access.\n\nThere are several constraints on these scripts, e.g. no network access, and it's important to always check the infra/chronos/README.md file to understand the specifics.\n\nA given Chronos integration must succeed with:\n\n```sh\npython3 infra/experimental/chronos/manager.py check-replay PROJECT_NAME\npython3 infra/experimental/chronos/manager.py check-tests PROJECT_NAME\n```\n\nThe above two commands must succeed without error, and when integrating a new project these commands must be run before concluding on the work for the security engineer to review.\n\nIn addition to the above, there are some constraints on Chronos worth mentioning:\n- If the tests fail when `run_tests.sh` is run, then `check-tests` *must* fail as well. This is a crucial invariant that is used to validate if wrong patches lead to wrong outcomes, and we must be able to check wrong patches that break tests.\n- The `run_tests.sh` script should leave a given repository in the state it was before the script was run. For example, `git diff` should be the same before and after `run_tests.sh` is run inside the target repository.\n- `run_tests.sh` has no network connection, so if any tests requires network connection then these tests should be skipped in `run_tests.sh` and this should be clearly documented in the script.\n\n\n# Guidelines for working locally on OSS-Fuzz projects\n\n1. Always work from the base folder of the current OSS-Fuzz project unless otherwise specified.\n2. Make a local checkout of the target source code to make working with the target project easy. This involves e.g. studying the `Dockerfile` of the target project, finding the e.g. `git clone` of the target project, and then cloning this repository locally and using e.g. `COPY` instead of `RUN git clone` in the Dockerfile to get the source code into the container.\n3. Use the `python3 infra/helper.py` tool to build and test fuzz targets locally.\n4. Analyse if build scripts can be optimized to improve local building efficiency.\n\n\n# Public data available for OSS-Fuzz projects\n\nThe OSS-Fuzz infrastructure provides a lot of public data that can be used to guide the work of an OSS-Fuzz engineer. This includes:\n\n- Current build status of all OSS-Fuzz projects:\n  - html page: https://oss-fuzz-build-logs.storage.googleapis.com/index.html\n  - json file: https://oss-fuzz-build-logs.storage.googleapis.com/status.json\n  - use this reference to identify latest build status of a given project, and to identify if there are any build issues that need to be fixed.\n  - If you are tasked with fixing the build of a project, then use this data to identify the latest build error.\n  - If you are tasked with fixing the build of a project, then use this data to identify the conditions of the latest build error, e.g. which architecture, fuzzing engine and sanitizer is failing.\n  - Some build errors are due to the harnesses running into an issue immediately, meaning they build but `check_build` fails. These are bugs that likely indicate the fuzzing harnesses have a deficiency.\n- in the references section guidance is provided on code coverage reports, helper script used for interacting with OSS-Fuzz projects and documentation on the structure of OSS-Fuzz projects.\n- https://introspector.oss-fuzz.com : details insights on macro and micro level stats on OSS-Fuzz.","frontmatter":{"name":"oss-fuzz-engineer","description":"Use this skill to interact with the OSS-Fuzz infrastructure."},"isInternal":false,"tokens":2891,"sizeBytes":13922},{"name":".eslintrc.json","path":"tools/vscode-extension/.eslintrc.json","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.eslintrc.json","title":"Vscode-extension Skill","category":"anthropic-skill","format":"json","content":"{\n  \"extends\": \"./node_modules/gts/\"\n}\n","frontmatter":{"extends":"./node_modules/gts/"},"isInternal":false,"tokens":12,"sizeBytes":39},{"name":"extensions.json","path":"tools/vscode-extension/.vscode/extensions.json","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/extensions.json","title":".vscode Skill","category":"anthropic-skill","format":"json","content":"# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/extensions.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/extensions.json)","tokens":300,"sizeBytes":204},{"name":"launch.json","path":"tools/vscode-extension/.vscode/launch.json","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/launch.json","title":".vscode Skill","category":"anthropic-skill","format":"json","content":"# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/launch.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/launch.json)","tokens":300,"sizeBytes":196},{"name":"settings.json","path":"tools/vscode-extension/.vscode/settings.json","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/settings.json","title":".vscode Skill","category":"anthropic-skill","format":"json","content":"# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/settings.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/settings.json)","tokens":300,"sizeBytes":200},{"name":"tasks.json","path":"tools/vscode-extension/.vscode/tasks.json","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/tasks.json","title":".vscode Skill","category":"anthropic-skill","format":"json","content":"# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/tasks.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/tasks.json)","tokens":300,"sizeBytes":194},{"name":"package-lock.json","path":"tools/vscode-extension/package-lock.json","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/package-lock.json","title":"Vscode-extension Skill","category":"anthropic-skill","format":"json","content":"{\n  \"name\": \"OSS-Fuzz\",\n  \"version\": \"0.0.5\",\n  \"lockfileVersion\": 2,\n  \"requires\": true,\n  \"packages\": {\n    \"\": {\n      \"name\": \"OSS-Fuzz\",\n      \"version\": \"0.0.5\",\n      \"dependencies\": {\n        \"@microsoft/vscode-file-downloader-api\": \"^1.0.1\"\n      },\n      \"devDependencies\": {\n        \"@types/glob\": \"^8.1.0\",\n        \"@types/mocha\": \"^10.0.1\",\n        \"@types/node\": \"^14.11.2\",\n        \"@types/vscode\": \"^1.76.0\",\n        \"@typescript-eslint/eslint-plugin\": \"^5.53.0\",\n        \"@typescript-eslint/parser\": \"^5.53.0\",\n        \"@vscode/test-electron\": \"^2.2.3\",\n        \"eslint\": \"^8.34.0\",\n        \"glob\": \"^8.1.0\",\n        \"gts\": \"^3.1.1\",\n        \"mocha\": \"^10.8.2\",\n        \"typescript\": \"~4.7.0\"\n      },\n      \"engines\": {\n        \"vscode\": \"^1.76.0\"\n      }\n    },\n    \"node_modules/@babel/code-frame\": {\n      \"version\": \"7.22.5\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz\",\n      \"integrity\": \"sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@babel/highlight\": \"^7.22.5\"\n      },\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@babel/helper-validator-identifier\": {\n      \"version\": \"7.22.5\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz\",\n      \"integrity\": \"sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@babel/highlight\": {\n      \"version\": \"7.22.5\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz\",\n      \"integrity\": \"sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@babel/helper-validator-identifier\": \"^7.22.5\",\n        \"chalk\": \"^2.0.0\",\n        \"js-tokens\": \"^4.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/ansi-styles\": {\n      \"version\": \"3.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz\",\n      \"integrity\": \"sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-convert\": \"^1.9.0\"\n      },\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/chalk\": {\n      \"version\": \"2.4.2\",\n      \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz\",\n      \"integrity\": \"sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ansi-styles\": \"^3.2.1\",\n        \"escape-string-regexp\": \"^1.0.5\",\n        \"supports-color\": \"^5.3.0\"\n      },\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/color-convert\": {\n      \"version\": \"1.9.3\",\n      \"resolved\": \"https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz\",\n      \"integrity\": \"sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-name\": \"1.1.3\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/color-name\": {\n      \"version\": \"1.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz\",\n      \"integrity\": \"sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==\",\n      \"dev\": true\n    },\n    \"node_modules/@babel/highlight/node_modules/escape-string-regexp\": {\n      \"version\": \"1.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz\",\n      \"integrity\": \"sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.8.0\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/has-flag\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz\",\n      \"integrity\": \"sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/supports-color\": {\n      \"version\": \"5.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz\",\n      \"integrity\": \"sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"has-flag\": \"^3.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@eslint/eslintrc\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz\",\n      \"integrity\": \"sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ajv\": \"^6.12.4\",\n        \"debug\": \"^4.3.2\",\n        \"espree\": \"^9.4.0\",\n        \"globals\": \"^13.19.0\",\n        \"ignore\": \"^5.2.0\",\n        \"import-fresh\": \"^3.2.1\",\n        \"js-yaml\": \"^4.1.0\",\n        \"minimatch\": \"^3.1.2\",\n        \"strip-json-comments\": \"^3.1.1\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://opencollective.com/eslint\"\n      }\n    },\n    \"node_modules/@eslint/js\": {\n      \"version\": \"8.35.0\",\n      \"resolved\": \"https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz\",\n      \"integrity\": \"sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      }\n    },\n    \"node_modules/@humanwhocodes/config-array\": {\n      \"version\": \"0.11.8\",\n      \"resolved\": \"https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz\",\n      \"integrity\": \"sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@humanwhocodes/object-schema\": \"^1.2.1\",\n        \"debug\": \"^4.1.1\",\n        \"minimatch\": \"^3.0.5\"\n      },\n      \"engines\": {\n        \"node\": \">=10.10.0\"\n      }\n    },\n    \"node_modules/@humanwhocodes/module-importer\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz\",\n      \"integrity\": \"sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=12.22\"\n      },\n      \"funding\": {\n        \"type\": \"github\",\n        \"url\": \"https://github.com/sponsors/nzakas\"\n      }\n    },\n    \"node_modules/@humanwhocodes/object-schema\": {\n      \"version\": \"1.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz\",\n      \"integrity\": \"sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==\",\n      \"dev\": true\n    },\n    \"node_modules/@microsoft/vscode-file-downloader-api\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/@microsoft/vscode-file-downloader-api/-/vscode-file-downloader-api-1.0.1.tgz\",\n      \"integrity\": \"sha512-cO9n/IpTMbXizz5YcEkiuRyX5r66SBY/3LnrlroyXbQXrgDdaKecfV3n4viTcvp9O//QF2AxcBfDZex2d4VSTg==\"\n    },\n    \"node_modules/@nodelib/fs.scandir\": {\n      \"version\": \"2.1.5\",\n      \"resolved\": \"https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz\",\n      \"integrity\": \"sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@nodelib/fs.stat\": \"2.0.5\",\n        \"run-parallel\": \"^1.1.9\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/@nodelib/fs.stat\": {\n      \"version\": \"2.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz\",\n      \"integrity\": \"sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/@nodelib/fs.walk\": {\n      \"version\": \"1.2.8\",\n      \"resolved\": \"https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz\",\n      \"integrity\": \"sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@nodelib/fs.scandir\": \"2.1.5\",\n        \"fastq\": \"^1.6.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/@tootallnate/once\": {\n      \"version\": \"1.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz\",\n      \"integrity\": \"sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">= 6\"\n      }\n    },\n    \"node_modules/@types/glob\": {\n      \"version\": \"8.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz\",\n      \"integrity\": \"sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@types/minimatch\": \"^5.1.2\",\n        \"@types/node\": \"*\"\n      }\n    },\n    \"node_modules/@types/json-schema\": {\n      \"version\": \"7.0.11\",\n      \"resolved\": \"https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz\",\n      \"integrity\": \"sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/minimatch\": {\n      \"version\": \"5.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz\",\n      \"integrity\": \"sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/minimist\": {\n      \"version\": \"1.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz\",\n      \"integrity\": \"sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/mocha\": {\n      \"version\": \"10.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz\",\n      \"integrity\": \"sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/node\": {\n      \"version\": \"14.18.54\",\n      \"resolved\": \"https://registry.npmjs.org/@types/node/-/node-14.18.54.tgz\",\n      \"integrity\": \"sha512-uq7O52wvo2Lggsx1x21tKZgqkJpvwCseBBPtX/nKQfpVlEsLOb11zZ1CRsWUKvJF0+lzuA9jwvA7Pr2Wt7i3xw==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/normalize-package-data\": {\n      \"version\": \"2.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz\",\n      \"integrity\": \"sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/semver\": {\n      \"version\": \"7.3.13\",\n      \"resolved\": \"https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz\",\n      \"integrity\": \"sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/vscode\": {\n      \"version\": \"1.76.0\",\n      \"resolved\": \"https://registry.npmjs.org/@types/vscode/-/vscode-1.76.0.tgz\",\n      \"integrity\": \"sha512-CQcY3+Fe5hNewHnOEAVYj4dd1do/QHliXaknAEYSXx2KEHUzFibDZSKptCon+HPgK55xx20pR+PBJjf0MomnBA==\",\n      \"dev\": true\n    },\n    \"node_modules/@typescript-eslint/eslint-plugin\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.1.tgz\",\n      \"integrity\": \"sha512-a2RQAkosH3d3ZIV08s3DcL/mcGc2M/UC528VkPULFxR9VnVPT8pBu0IyBAJJmVsCmhVfwQX1v6q+QGnmSe1bew==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/scope-manager\": \"5.54.1\",\n        \"@typescript-eslint/type-utils\": \"5.54.1\",\n        \"@typescript-eslint/utils\": \"5.54.1\",\n        \"debug\": \"^4.3.4\",\n        \"grapheme-splitter\": \"^1.0.4\",\n        \"ignore\": \"^5.2.0\",\n        \"natural-compare-lite\": \"^1.4.0\",\n        \"regexpp\": \"^3.2.0\",\n        \"semver\": \"^7.3.7\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"@typescript-eslint/parser\": \"^5.0.0\",\n        \"eslint\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz\",\n      \"integrity\": \"sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@types/json-schema\": \"^7.0.7\",\n        \"@typescript-eslint/scope-manager\": \"4.33.0\",\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"@typescript-eslint/typescript-estree\": \"4.33.0\",\n        \"eslint-scope\": \"^5.1.1\",\n        \"eslint-utils\": \"^3.0.0\"\n      },\n      \"engines\": {\n        \"node\": \"^10.12.0 || >=12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"*\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz\",\n      \"integrity\": \"sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"@typescript-eslint/visitor-keys\": \"4.33.0\"\n      },\n      \"engines\": {\n        \"node\": \"^8.10.0 || ^10.13.0 || >=11.10.1\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz\",\n      \"integrity\": \"sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \"^8.10.0 || ^10.13.0 || >=11.10.1\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz\",\n      \"integrity\": \"sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"@typescript-eslint/visitor-keys\": \"4.33.0\",\n        \"debug\": \"^4.3.1\",\n        \"globby\": \"^11.0.3\",\n        \"is-glob\": \"^4.0.1\",\n        \"semver\": \"^7.3.5\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^10.12.0 || >=12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz\",\n      \"integrity\": \"sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"eslint-visitor-keys\": \"^2.0.0\"\n      },\n      \"engines\": {\n        \"node\": \"^8.10.0 || ^10.13.0 || >=11.10.1\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-visitor-keys\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz\",\n      \"integrity\": \"sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@typescript-eslint/parser\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.1.tgz\",\n      \"integrity\": \"sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/scope-manager\": \"5.54.1\",\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/typescript-estree\": \"5.54.1\",\n        \"debug\": \"^4.3.4\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/scope-manager\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz\",\n      \"integrity\": \"sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/visitor-keys\": \"5.54.1\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/type-utils\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.1.tgz\",\n      \"integrity\": \"sha512-WREHsTz0GqVYLIbzIZYbmUUr95DKEKIXZNH57W3s+4bVnuF1TKe2jH8ZNH8rO1CeMY3U4j4UQeqPNkHMiGem3g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/typescript-estree\": \"5.54.1\",\n        \"@typescript-eslint/utils\": \"5.54.1\",\n        \"debug\": \"^4.3.4\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"*\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/types\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz\",\n      \"integrity\": \"sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/typescript-estree\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz\",\n      \"integrity\": \"sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/visitor-keys\": \"5.54.1\",\n        \"debug\": \"^4.3.4\",\n        \"globby\": \"^11.1.0\",\n        \"is-glob\": \"^4.0.3\",\n        \"semver\": \"^7.3.7\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/utils\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.1.tgz\",\n      \"integrity\": \"sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@types/json-schema\": \"^7.0.9\",\n        \"@types/semver\": \"^7.3.12\",\n        \"@typescript-eslint/scope-manager\": \"5.54.1\",\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/typescript-estree\": \"5.54.1\",\n        \"eslint-scope\": \"^5.1.1\",\n        \"eslint-utils\": \"^3.0.0\",\n        \"semver\": \"^7.3.7\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      }\n    },\n    \"node_modules/@typescript-eslint/visitor-keys\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz\",\n      \"integrity\": \"sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"eslint-visitor-keys\": \"^3.3.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@vscode/test-electron\": {\n      \"version\": \"2.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.0.tgz\",\n      \"integrity\": \"sha512-fwzA9RtazH1GT/sckYlbxu6t5e4VaMXwCVtyLv4UAG0hP6NTfnMaaG25XCfWqlVwFhBMcQXHBCy5dmz2eLUnkw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"http-proxy-agent\": \"^4.0.1\",\n        \"https-proxy-agent\": \"^5.0.0\",\n        \"jszip\": \"^3.10.1\",\n        \"semver\": \"^7.3.8\"\n      },\n      \"engines\": {\n        \"node\": \">=16\"\n      }\n    },\n    \"node_modules/acorn\": {\n      \"version\": \"8.8.2\",\n      \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz\",\n      \"integrity\": \"sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==\",\n      \"dev\": true,\n      \"bin\": {\n        \"acorn\": \"bin/acorn\"\n      },\n      \"engines\": {\n        \"node\": \">=0.4.0\"\n      }\n    },\n    \"node_modules/acorn-jsx\": {\n      \"version\": \"5.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz\",\n      \"integrity\": \"sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==\",\n      \"dev\": true,\n      \"peerDependencies\": {\n        \"acorn\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      }\n    },\n    \"node_modules/agent-base\": {\n      \"version\": \"6.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz\",\n      \"integrity\": \"sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"debug\": \"4\"\n      },\n      \"engines\": {\n        \"node\": \">= 6.0.0\"\n      }\n    },\n    \"node_modules/ajv\": {\n      \"version\": \"6.12.6\",\n      \"resolved\": \"https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz\",\n      \"integrity\": \"sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"fast-deep-equal\": \"^3.1.1\",\n        \"fast-json-stable-stringify\": \"^2.0.0\",\n        \"json-schema-traverse\": \"^0.4.1\",\n        \"uri-js\": \"^4.2.2\"\n      },\n      \"funding\": {\n        \"type\": \"github\",\n        \"url\": \"https://github.com/sponsors/epoberezkin\"\n      }\n    },\n    \"node_modules/ansi-colors\": {\n      \"version\": \"4.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz\",\n      \"integrity\": \"sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/ansi-escapes\": {\n      \"version\": \"4.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz\",\n      \"integrity\": \"sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"type-fest\": \"^0.21.3\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/ansi-escapes/node_modules/type-fest\": {\n      \"version\": \"0.21.3\",\n      \"resolved\": \"https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz\",\n      \"integrity\": \"sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/ansi-regex\": {\n      \"version\": \"5.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n      \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/ansi-styles\": {\n      \"version\": \"4.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz\",\n      \"integrity\": \"sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-convert\": \"^2.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n      }\n    },\n    \"node_modules/anymatch\": {\n      \"version\": \"3.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz\",\n      \"integrity\": \"sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"normalize-path\": \"^3.0.0\",\n        \"picomatch\": \"^2.0.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/argparse\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz\",\n      \"integrity\": \"sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==\",\n      \"dev\": true\n    },\n    \"node_modules/array-union\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz\",\n      \"integrity\": \"sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/arrify\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz\",\n      \"integrity\": \"sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/astral-regex\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz\",\n      \"integrity\": \"sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/balanced-match\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz\",\n      \"integrity\": \"sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==\",\n      \"dev\": true\n    },\n    \"node_modules/binary-extensions\": {\n      \"version\": \"2.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz\",\n      \"integrity\": \"sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/brace-expansion\": {\n      \"version\": \"1.1.11\",\n      \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz\",\n      \"integrity\": \"sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"balanced-match\": \"^1.0.0\",\n        \"concat-map\": \"0.0.1\"\n      }\n    },\n    \"node_modules/braces\": {\n      \"version\": \"3.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/braces/-/braces-3.0.3.tgz\",\n      \"integrity\": \"sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"fill-range\": \"^7.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/browser-stdout\": {\n      \"version\": \"1.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz\",\n      \"integrity\": \"sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==\",\n      \"dev\": true\n    },\n    \"node_modules/callsites\": {\n      \"version\": \"3.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz\",\n      \"integrity\": \"sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/camelcase\": {\n      \"version\": \"6.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz\",\n      \"integrity\": \"sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/camelcase-keys\": {\n      \"version\": \"6.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz\",\n      \"integrity\": \"sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"camelcase\": \"^5.3.1\",\n        \"map-obj\": \"^4.0.0\",\n        \"quick-lru\": \"^4.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/camelcase-keys/node_modules/camelcase\": {\n      \"version\": \"5.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz\",\n      \"integrity\": \"sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/chalk\": {\n      \"version\": \"4.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz\",\n      \"integrity\": \"sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ansi-styles\": \"^4.1.0\",\n        \"supports-color\": \"^7.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/chalk/chalk?sponsor=1\"\n      }\n    },\n    \"node_modules/chardet\": {\n      \"version\": \"0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz\",\n      \"integrity\": \"sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==\",\n      \"dev\": true\n    },\n    \"node_modules/chokidar\": {\n      \"version\": \"3.5.3\",\n      \"resolved\": \"https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz\",\n      \"integrity\": \"sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==\",\n      \"dev\": true,\n      \"funding\": [\n        {\n          \"type\": \"individual\",\n          \"url\": \"https://paulmillr.com/funding/\"\n        }\n      ],\n      \"dependencies\": {\n        \"anymatch\": \"~3.1.2\",\n        \"braces\": \"~3.0.2\",\n        \"glob-parent\": \"~5.1.2\",\n        \"is-binary-path\": \"~2.1.0\",\n        \"is-glob\": \"~4.0.1\",\n        \"normalize-path\": \"~3.0.0\",\n        \"readdirp\": \"~3.6.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 8.10.0\"\n      },\n      \"optionalDependencies\": {\n        \"fsevents\": \"~2.3.2\"\n      }\n    },\n    \"node_modules/chokidar/node_modules/glob-parent\": {\n      \"version\": \"5.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz\",\n      \"integrity\": \"sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"is-glob\": \"^4.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 6\"\n      }\n    },\n    \"node_modules/cli-cursor\": {\n      \"version\": \"3.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz\",\n      \"integrity\": \"sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"restore-cursor\": \"^3.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/cli-width\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz\",\n      \"integrity\": \"sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">= 10\"\n      }\n    },\n    \"node_modules/cliui\": {\n      \"version\": \"7.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz\",\n      \"integrity\": \"sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"string-width\": \"^4.2.0\",\n        \"strip-ansi\": \"^6.0.0\",\n        \"wrap-ansi\": \"^7.0.0\"\n      }\n    },\n    \"node_modules/color-convert\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz\",\n      \"integrity\": \"sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-name\": \"~1.1.4\"\n      },\n      \"engines\": {\n        \"node\": \">=7.0.0\"\n      }\n    },\n    \"node_modules/color-name\": {\n      \"version\": \"1.1.4\",\n      \"resolved\": \"https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz\",\n      \"integrity\": \"sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==\",\n      \"dev\": true\n    },\n    \"node_modules/concat-map\": {\n      \"version\": \"0.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz\",\n      \"integrity\": \"sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==\",\n      \"dev\": true\n    },\n    \"node_modules/core-util-is\": {\n      \"version\": \"1.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz\",\n      \"integrity\": \"sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==\",\n      \"dev\": true\n    },\n    \"node_modules/cross-spawn\": {\n      \"version\": \"7.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz\",\n      \"integrity\": \"sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"path-key\": \"^3.1.0\",\n        \"shebang-command\": \"^2.0.0\",\n        \"which\": \"^2.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/debug\": {\n      \"version\": \"4.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/debug/-/debug-4.4.0.tgz\",\n      \"integrity\": \"sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"ms\": \"^2.1.3\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"supports-color\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/decamelize\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz\",\n      \"integrity\": \"sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/decamelize-keys\": {\n      \"version\": \"1.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz\",\n      \"integrity\": \"sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"decamelize\": \"^1.1.0\",\n        \"map-obj\": \"^1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/decamelize-keys/node_modules/decamelize\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz\",\n      \"integrity\": \"sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/decamelize-keys/node_modules/map-obj\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz\",\n      \"integrity\": \"sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/deep-is\": {\n      \"version\": \"0.1.4\",\n      \"resolved\": \"https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz\",\n      \"integrity\": \"sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==\",\n      \"dev\": true\n    },\n    \"node_modules/diff\": {\n      \"version\": \"5.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/diff/-/diff-5.2.0.tgz\",\n      \"integrity\": \"sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==\",\n      \"dev\": true,\n      \"license\": \"BSD-3-Clause\",\n      \"engines\": {\n        \"node\": \">=0.3.1\"\n      }\n    },\n    \"node_modules/dir-glob\": {\n      \"version\": \"3.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz\",\n      \"integrity\": \"sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"path-type\": \"^4.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/doctrine\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz\",\n      \"integrity\": \"sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"esutils\": \"^2.0.2\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0.0\"\n      }\n    },\n    \"node_modules/emoji-regex\": {\n      \"version\": \"8.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n      \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n      \"dev\": true\n    },\n    \"node_modules/enquirer\": {\n      \"version\": \"2.3.6\",\n      \"resolved\": \"https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz\",\n      \"integrity\": \"sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ansi-colors\": \"^4.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8.6\"\n      }\n    },\n    \"node_modules/error-ex\": {\n      \"version\": \"1.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz\",\n      \"integrity\": \"sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"is-arrayish\": \"^0.2.1\"\n      }\n    },\n    \"node_modules/escalade\": {\n      \"version\": \"3.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz\",\n      \"integrity\": \"sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/escape-string-regexp\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz\",\n      \"integrity\": \"sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/eslint\": {\n      \"version\": \"8.35.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz\",\n      \"integrity\": \"sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@eslint/eslintrc\": \"^2.0.0\",\n        \"@eslint/js\": \"8.35.0\",\n        \"@humanwhocodes/config-array\": \"^0.11.8\",\n        \"@humanwhocodes/module-importer\": \"^1.0.1\",\n        \"@nodelib/fs.walk\": \"^1.2.8\",\n        \"ajv\": \"^6.10.0\",\n        \"chalk\": \"^4.0.0\",\n        \"cross-spawn\": \"^7.0.2\",\n        \"debug\": \"^4.3.2\",\n        \"doctrine\": \"^3.0.0\",\n        \"escape-string-regexp\": \"^4.0.0\",\n        \"eslint-scope\": \"^7.1.1\",\n        \"eslint-utils\": \"^3.0.0\",\n        \"eslint-visitor-keys\": \"^3.3.0\",\n        \"espree\": \"^9.4.0\",\n        \"esquery\": \"^1.4.2\",\n        \"esutils\": \"^2.0.2\",\n        \"fast-deep-equal\": \"^3.1.3\",\n        \"file-entry-cache\": \"^6.0.1\",\n        \"find-up\": \"^5.0.0\",\n        \"glob-parent\": \"^6.0.2\",\n        \"globals\": \"^13.19.0\",\n        \"grapheme-splitter\": \"^1.0.4\",\n        \"ignore\": \"^5.2.0\",\n        \"import-fresh\": \"^3.0.0\",\n        \"imurmurhash\": \"^0.1.4\",\n        \"is-glob\": \"^4.0.0\",\n        \"is-path-inside\": \"^3.0.3\",\n        \"js-sdsl\": \"^4.1.4\",\n        \"js-yaml\": \"^4.1.0\",\n        \"json-stable-stringify-without-jsonify\": \"^1.0.1\",\n        \"levn\": \"^0.4.1\",\n        \"lodash.merge\": \"^4.6.2\",\n        \"minimatch\": \"^3.1.2\",\n        \"natural-compare\": \"^1.4.0\",\n        \"optionator\": \"^0.9.1\",\n        \"regexpp\": \"^3.2.0\",\n        \"strip-ansi\": \"^6.0.1\",\n        \"strip-json-comments\": \"^3.1.0\",\n        \"text-table\": \"^0.2.0\"\n      },\n      \"bin\": {\n        \"eslint\": \"bin/eslint.js\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://opencollective.com/eslint\"\n      }\n    },\n    \"node_modules/eslint-config-prettier\": {\n      \"version\": \"7.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz\",\n      \"integrity\": \"sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==\",\n      \"dev\": true,\n      \"bin\": {\n        \"eslint-config-prettier\": \"bin/cli.js\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=7.0.0\"\n      }\n    },\n    \"node_modules/eslint-plugin-es\": {\n      \"version\": \"3.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz\",\n      \"integrity\": \"sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-utils\": \"^2.0.0\",\n        \"regexpp\": \"^3.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8.10.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/mysticatea\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=4.19.1\"\n      }\n    },\n    \"node_modules/eslint-plugin-es/node_modules/eslint-utils\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz\",\n      \"integrity\": \"sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-visitor-keys\": \"^1.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/mysticatea\"\n      }\n    },\n    \"node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz\",\n      \"integrity\": \"sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/eslint-plugin-node\": {\n      \"version\": \"11.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz\",\n      \"integrity\": \"sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-plugin-es\": \"^3.0.0\",\n        \"eslint-utils\": \"^2.0.0\",\n        \"ignore\": \"^5.1.1\",\n        \"minimatch\": \"^3.0.4\",\n        \"resolve\": \"^1.10.1\",\n        \"semver\": \"^6.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8.10.0\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=5.16.0\"\n      }\n    },\n    \"node_modules/eslint-plugin-node/node_modules/eslint-utils\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz\",\n      \"integrity\": \"sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-visitor-keys\": \"^1.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/mysticatea\"\n      }\n    },\n    \"node_modules/eslint-plugin-node/node_modules/eslint-visitor-keys\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz\",\n      \"integrity\": \"sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/eslint-plugin-node/node_modules/semver\": {\n      \"version\": \"6.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/semver/-/semver-6.3.1.tgz\",\n      \"integrity\": \"sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==\",\n      \"dev\": true,\n      \"bin\": {\n        \"semver\": \"bin/semver.js\"\n      }\n    },\n    \"node_modules/eslint-plugin-prettier\": {\n      \"version\": \"3.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz\",\n      \"integrity\": \"sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"prettier-linter-helpers\": \"^1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0.0\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=5.0.0\",\n        \"prettier\": \">=1.13.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"eslint-config-prettier\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/eslint-scope\": {\n      \"version\": \"5.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz\",\n      \"integrity\": \"sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"esrecurse\": \"^4.3.0\",\n        \"estraverse\": \"^4.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8.0.0\"\n      }\n    },\n    \"node_modules/eslint-utils\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz\",\n      \"integrity\": \"sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-visitor-keys\": \"^2.0.0\"\n      },\n      \"engine","isInternal":false,"tokens":19843,"sizeBytes":50000},{"name":"package.json","path":"tools/vscode-extension/package.json","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/package.json","title":"OSS-Fuzz","category":"anthropic-skill","format":"json","content":"{\n  \"name\": \"OSS-Fuzz\",\n  \"displayName\": \"OSS-Fuzz\",\n  \"description\": \"\",\n  \"version\": \"0.0.5\",\n  \"publisher\": \"OSS-FuzzMaintainers\",\n  \"icon\": \"images/thumbnail.png\",\n  \"engines\": {\n    \"vscode\": \"^1.76.0\"\n  },\n  \"repository\": \"https://github.com/google/oss-fuzz\",\n  \"categories\": [\n    \"Other\"\n  ],\n  \"extensionDependencies\": [\n    \"mindaro-dev.file-downloader\"\n  ],\n  \"activationEvents\": [],\n  \"main\": \"./build/src/extension.js\",\n  \"contributes\": {\n    \"configurations\": [\n      {\n        \"id\": \"OSS-Fuzz-Base\",\n        \"title\": \"Base path to OSS-Fuzz\",\n        \"properties\": {\n          \"oss-fuzz.OSS.Path\": {\n            \"type\": \"string\"\n          }\n        }\n      }\n    ],\n    \"viewsWelcome\": [\n      {\n        \"view\": \"workbench.explorer.emptyView\",\n        \"contents\": \"You can have paragraphs of text here. You can have [links](https://code.visualstudio.com) to external sources or [internal commands](command:welcome-view-content-sample.hello).\\nUse new lines to have new paragraphs.\\nPlace a link alone in a paragraph to make it a button\\n[Hello](command:welcome-view-content-sample.hello)\"\n      }\n    ],\n    \"commands\": [\n      {\n        \"command\": \"oss-fuzz.SetUp\",\n        \"title\": \"OSS-Fuzz: Set Up OSS-Fuzz\",\n        \"description\": \"Downloads the OSS-Fuzz repository and places it under /tmp/oss-fuzz. This will then be the OSS-Fuzz repository used by vscode.\"\n      },\n      {\n        \"command\": \"oss-fuzz.RunFuzzer\",\n        \"title\": \"OSS-Fuzz: Run Fuzzer\",\n        \"description\": \"Runs a single fuzzer from a given project. The fuzzer must already be build, meaning the project should be build first.\"\n      },\n      {\n        \"command\": \"oss-fuzz.ListFuzzers\",\n        \"title\": \"OSS-Fuzz: List Fuzzers\",\n        \"description\": \"Lists the fuzzers built for a given project. The project must be build first.\"\n      },\n      {\n        \"command\": \"oss-fuzz.GetCodeCoverage\",\n        \"title\": \"OSS-Fuzz: Display Code Coverage (Python only)\",\n        \"description\": \"Downloads the latest code coverage from OSS-Fuzz's cloud data (can find at https://introspector.oss-fuzz.com).\"\n      },\n      {\n        \"command\": \"oss-fuzz.ClearCodeCoverage\",\n        \"title\": \"OSS-Fuzz: Clear Code Coverage\",\n        \"description\": \"Clears code coverage visualization in the editor.\"\n      },\n      {\n        \"command\": \"oss-fuzz.CreateOSSFuzzSetup\",\n        \"title\": \"OSS-Fuzz: Initialize OSS-Fuzz Set Up\",\n        \"description\": \"Creates the relevant files using templates to set up an OSS-Fuzz project. Uses minor heuristics e.g. detection of language.\"\n      },\n      {\n        \"command\": \"oss-fuzz.WSBuildFuzzers\",\n        \"title\": \"OSS-Fuzz: Build Fuzzers In Workspace\",\n        \"description\": \"Builds the fuzzers from the project in the current VSCode workspace.\"\n      },\n      {\n        \"command\": \"oss-fuzz.SetupCIFuzz\",\n        \"title\": \"OSS-Fuzz: Set up CIFuzz\",\n        \"description\": \"Creates the files necessary for a CIFuzz set up.\"\n      },\n      {\n        \"command\": \"oss-fuzz.testFuzzer\",\n        \"title\": \"OSS-Fuzz: Test Specific Fuzzer\",\n        \"description\": \"Tests if a given fuzzer works by running it for 10 seconds.\"\n      },\n      {\n        \"command\": \"oss-fuzz.testCodeCoverage\",\n        \"title\": \"OSS-Fuzz: End-To-End Code Coverage Generation\",\n        \"description\": \"Builds the fuzzers in a ASAN mode for a project, collects corpus using the ASAN fuzzers and then generates an HTLM code coverage report using the generated corpus.\"\n      },\n      {\n        \"command\": \"oss-fuzz.Redo\",\n        \"title\": \"OSS-Fuzz: Redo Previous Command\",\n        \"description\": \"Performs the exact same command as the most recent one. Will provide the same input to the command as the previous one. This is efficient when e.g. continuously generating code coverage reports while working on improving a fuzzing set up.\"\n      },\n      {\n        \"command\": \"oss-fuzz.Template\",\n        \"title\": \"OSS-Fuzz: Fuzzer Creation Using Templates\",\n        \"description\": \"Creates a template fuzzer file using a catalogue of templates available.\"\n      },\n      {\n        \"command\": \"oss-fuzz.GenerateClusterfuzzLite\",\n        \"title\": \"OSS-Fuzz: [CFLite] Generate ClusterfuzzLite setup\",\n        \"description\": \"Creates the files needed for ClusterfuzzLite integration.\"\n      },\n      {\n        \"command\": \"oss-fuzz.WSBuildFuzzersCFLite\",\n        \"title\": \"OSS-Fuzz: [CFLite] Build Fuzzers In Workspace\",\n        \"description\": \"Builds the ClusterfuzzLite fuzzers from the project in the current VSCode workspace.\"\n      },\n      {\n        \"command\": \"oss-fuzz.testFuzzerCFLite\",\n        \"title\": \"OSS-Fuzz: [CFLite] Test running a specific fuzzer.\",\n        \"description\": \"Builds the CFLite setup and runs a fuzzer for a short period of time.\"\n      },\n      {\n        \"command\": \"oss-fuzz.setupFuzzIntrospector\",\n        \"title\": \"OSS-Fuzz: Set up Fuzz Introspector\",\n        \"description\": \"Install fuzz introspector on the system\"\n      },\n      {\n        \"command\": \"oss-fuzz.runFuzzIntrospector\",\n        \"title\": \"OSS-Fuzz: Run Full Fuzz Introspector\",\n        \"description\": \"Runs a full Fuzz Introspector\"\n      },\n      {\n        \"command\": \"oss-fuzz.GetOptimalTargets\",\n        \"title\": \"OSS-Fuzz: Get optimal targets\",\n        \"description\": \"Gets the optimal targets of this project\"\n      }\n    ],\n    \"walkthroughs\":[\n      {\n        \"id\": \"BuildAndRunExisting Project\",\n        \"title\": \"Set up OSS-Fuzz\",\n        \"description\": \"This walkthrough takes you through how to set up OSS-Fuzz in the VSCode extension and proceeding to build the fuzzers of an existing project as well as running a fuzzer from the project.\",\n        \"steps\": [\n          {\n            \"id\": \"s1\",\n            \"title\": \"Set up OSS-Fuzz\",\n            \"description\": \"This step sets up OSS-Fuzz in the folder /tmp/oss-fuzz\",\n            \"completionEvents\": [\"onCommand:oss-fuzz.SetUp\"],\n            \"media\": {\"altText\": \".\", \"image\": \"images/workflow-1-s-1\"}\n          }\n        ]\n      }\n    ]\n  },\n  \"scripts\": {\n    \"vscode:prepublish\": \"npm run compile\",\n    \"compile\": \"tsc\",\n    \"watch\": \"tsc -watch -p ./\",\n    \"pretest\": \"npm run compile\",\n    \"lint\": \"gts lint\",\n    \"clean\": \"gts clean\",\n    \"fix\": \"gts fix\",\n    \"prepare\": \"npm run compile\",\n    \"posttest\": \"npm run lint\"\n  },\n  \"devDependencies\": {\n    \"@types/glob\": \"^8.1.0\",\n    \"@types/mocha\": \"^10.0.1\",\n    \"@types/node\": \"^14.11.2\",\n    \"@types/vscode\": \"^1.76.0\",\n    \"@typescript-eslint/eslint-plugin\": \"^5.53.0\",\n    \"@typescript-eslint/parser\": \"^5.53.0\",\n    \"@vscode/test-electron\": \"^2.2.3\",\n    \"eslint\": \"^8.34.0\",\n    \"glob\": \"^8.1.0\",\n    \"mocha\": \"^10.8.2\",\n    \"typescript\": \"~4.7.0\",\n    \"gts\": \"^3.1.1\"\n  },\n  \"dependencies\": {\n    \"@microsoft/vscode-file-downloader-api\": \"^1.0.1\"\n  }\n}\n","frontmatter":{"name":"OSS-Fuzz","displayName":"OSS-Fuzz","description":"","version":"0.0.5","publisher":"OSS-FuzzMaintainers","icon":"images/thumbnail.png","engines":{"vscode":"^1.76.0"},"repository":"https://github.com/google/oss-fuzz","categories":["Other"],"extensionDependencies":["mindaro-dev.file-downloader"],"activationEvents":[],"main":"./build/src/extension.js","contributes":{"configurations":[{"id":"OSS-Fuzz-Base","title":"Base path to OSS-Fuzz","properties":{"oss-fuzz.OSS.Path":{"type":"string"}}}],"viewsWelcome":[{"view":"workbench.explorer.emptyView","contents":"You can have paragraphs of text here. You can have [links](https://code.visualstudio.com) to external sources or [internal commands](command:welcome-view-content-sample.hello).\nUse new lines to have new paragraphs.\nPlace a link alone in a paragraph to make it a button\n[Hello](command:welcome-view-content-sample.hello)"}],"commands":[{"command":"oss-fuzz.SetUp","title":"OSS-Fuzz: Set Up OSS-Fuzz","description":"Downloads the OSS-Fuzz repository and places it under /tmp/oss-fuzz. This will then be the OSS-Fuzz repository used by vscode."},{"command":"oss-fuzz.RunFuzzer","title":"OSS-Fuzz: Run Fuzzer","description":"Runs a single fuzzer from a given project. The fuzzer must already be build, meaning the project should be build first."},{"command":"oss-fuzz.ListFuzzers","title":"OSS-Fuzz: List Fuzzers","description":"Lists the fuzzers built for a given project. The project must be build first."},{"command":"oss-fuzz.GetCodeCoverage","title":"OSS-Fuzz: Display Code Coverage (Python only)","description":"Downloads the latest code coverage from OSS-Fuzz's cloud data (can find at https://introspector.oss-fuzz.com)."},{"command":"oss-fuzz.ClearCodeCoverage","title":"OSS-Fuzz: Clear Code Coverage","description":"Clears code coverage visualization in the editor."},{"command":"oss-fuzz.CreateOSSFuzzSetup","title":"OSS-Fuzz: Initialize OSS-Fuzz Set Up","description":"Creates the relevant files using templates to set up an OSS-Fuzz project. Uses minor heuristics e.g. detection of language."},{"command":"oss-fuzz.WSBuildFuzzers","title":"OSS-Fuzz: Build Fuzzers In Workspace","description":"Builds the fuzzers from the project in the current VSCode workspace."},{"command":"oss-fuzz.SetupCIFuzz","title":"OSS-Fuzz: Set up CIFuzz","description":"Creates the files necessary for a CIFuzz set up."},{"command":"oss-fuzz.testFuzzer","title":"OSS-Fuzz: Test Specific Fuzzer","description":"Tests if a given fuzzer works by running it for 10 seconds."},{"command":"oss-fuzz.testCodeCoverage","title":"OSS-Fuzz: End-To-End Code Coverage Generation","description":"Builds the fuzzers in a ASAN mode for a project, collects corpus using the ASAN fuzzers and then generates an HTLM code coverage report using the generated corpus."},{"command":"oss-fuzz.Redo","title":"OSS-Fuzz: Redo Previous Command","description":"Performs the exact same command as the most recent one. Will provide the same input to the command as the previous one. This is efficient when e.g. continuously generating code coverage reports while working on improving a fuzzing set up."},{"command":"oss-fuzz.Template","title":"OSS-Fuzz: Fuzzer Creation Using Templates","description":"Creates a template fuzzer file using a catalogue of templates available."},{"command":"oss-fuzz.GenerateClusterfuzzLite","title":"OSS-Fuzz: [CFLite] Generate ClusterfuzzLite setup","description":"Creates the files needed for ClusterfuzzLite integration."},{"command":"oss-fuzz.WSBuildFuzzersCFLite","title":"OSS-Fuzz: [CFLite] Build Fuzzers In Workspace","description":"Builds the ClusterfuzzLite fuzzers from the project in the current VSCode workspace."},{"command":"oss-fuzz.testFuzzerCFLite","title":"OSS-Fuzz: [CFLite] Test running a specific fuzzer.","description":"Builds the CFLite setup and runs a fuzzer for a short period of time."},{"command":"oss-fuzz.setupFuzzIntrospector","title":"OSS-Fuzz: Set up Fuzz Introspector","description":"Install fuzz introspector on the system"},{"command":"oss-fuzz.runFuzzIntrospector","title":"OSS-Fuzz: Run Full Fuzz Introspector","description":"Runs a full Fuzz Introspector"},{"command":"oss-fuzz.GetOptimalTargets","title":"OSS-Fuzz: Get optimal targets","description":"Gets the optimal targets of this project"}],"walkthroughs":[{"id":"BuildAndRunExisting Project","title":"Set up OSS-Fuzz","description":"This walkthrough takes you through how to set up OSS-Fuzz in the VSCode extension and proceeding to build the fuzzers of an existing project as well as running a fuzzer from the project.","steps":[{"id":"s1","title":"Set up OSS-Fuzz","description":"This step sets up OSS-Fuzz in the folder /tmp/oss-fuzz","completionEvents":["onCommand:oss-fuzz.SetUp"],"media":{"altText":".","image":"images/workflow-1-s-1"}}]}]},"scripts":{"vscode:prepublish":"npm run compile","compile":"tsc","watch":"tsc -watch -p ./","pretest":"npm run compile","lint":"gts lint","clean":"gts clean","fix":"gts fix","prepare":"npm run compile","posttest":"npm run lint"},"devDependencies":{"@types/glob":"^8.1.0","@types/mocha":"^10.0.1","@types/node":"^14.11.2","@types/vscode":"^1.76.0","@typescript-eslint/eslint-plugin":"^5.53.0","@typescript-eslint/parser":"^5.53.0","@vscode/test-electron":"^2.2.3","eslint":"^8.34.0","glob":"^8.1.0","mocha":"^10.8.2","typescript":"~4.7.0","gts":"^3.1.1"},"dependencies":{"@microsoft/vscode-file-downloader-api":"^1.0.1"}},"isInternal":false,"tokens":1820,"sizeBytes":6772},{"name":"tsconfig.json","path":"tools/vscode-extension/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/tsconfig.json","title":"Vscode-extension Skill","category":"anthropic-skill","format":"json","content":"{\n  \"extends\": \"./node_modules/gts/tsconfig-google.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \".\",\n    \"outDir\": \"build\"\n  },\n  \"include\": [\n    \"src/**/*.ts\",\n    \"test/**/*.ts\"\n  ]\n}\n","frontmatter":{"extends":"./node_modules/gts/tsconfig-google.json","compilerOptions":{"rootDir":".","outDir":"build"},"include":["src/**/*.ts","test/**/*.ts"]},"isInternal":false,"tokens":58,"sizeBytes":187},{"name":"README.md","path":"tools/vscode-extension/README.md","rawUrl":"https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/README.md","title":"vscode-extension Documentation","category":"plugin-manifest","format":"markdown","content":"# OSS-Fuzz VSCode extension\n\n[OSS-Fuzz](https://github.com/google/oss-fuzz) is a fuzzing toolkit and service for fuzzing open source projects. This VSCode extension provides features and capabilities for interacting with the OSS-Fuzz toolkit and also to compare local changes to the OSS-Fuzz cloud database by way of [Open source fuzz introspection](https://introspector.oss-fuzz.com).\n\n## Features\n\nThe VSCode extension is largely driven by commands at this point. The featues of these commands includes:\n\n- Easily setting up OSS-Fuzz\n- Templates for easily setting up a new OSS-Fuzz project\n- Building arbitrary projects from OSS-Fuzz\n- Modify a project from VSCode and test changes in OSS-Fuzz\n- Easily extract code coverage of fuzzers, including local-only fuzzers\n- Compare local code coverage to what is currently achieved by OSS-Fuzz\n- Auto-generation of fuzzer templates\n\nFor a full list of commands and their features, please check the commands page.","isInternal":false,"tokens":210,"sizeBytes":959}],"systemPromptSnippet":"<yakaai_skills repo=\"google/oss-fuzz\">\n<!-- File: AGENTS.md (Tokens: ~76 | Category: root-instruction) -->\n* Use python3 infra/helper.py to build projects and run fuzzers.\n* If doing development on infra/ you should use a venv and if it doesn't already exist, install deps from infra/ci/requirements.txt build/functions/requirements.txt with pip.\n* If doing development on infra/ run python infra/presubmit.py to format, lint and run tests.\n\n<!-- File: infra/experimental/agent-skills/fuzzing-go-expert/SKILL.md (Tokens: ~1335 | Category: anthropic-skill) -->\n---\nname: fuzzing-go-expert\ndescription:\n  Use this skill to fuzz open source Go software projects.\n---\n\n# Fuzzing Go expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for Go projects integrated into OSS-Fuzz. Go fuzzing uses\nthe native Go fuzzing framework introduced in Go 1.18, which OSS-Fuzz drives\nvia libFuzzer under the hood using `compile_native_go_fuzzer`.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nGo projects must use the Go base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-go\n```\n\nSet `language: go` in `project.yaml`.\n\n### Harness structure\n\nGo fuzz targets are standard Go test functions with the prefix `Fuzz`, placed\nin `_test.go` files (or plain `.go` files that import the testing package):\n\n```go\npackage mypkg\n\nimport (\n    \"testing\"\n    _ \"github.com/AdamKorcz/go-118-fuzz-build/testing\" // required for OSS-Fuzz native fuzzing\n)\n\nfunc FuzzMyTarget(f *testing.F) {\n    // Seed corpus: add representative valid inputs so the fuzzer starts\n    // from a meaningful state rather than empty bytes.\n    f.Add([]byte(\"example input\"))\n    f.Add([]byte(\"another seed\"))\n\n    f.Fuzz(func(t *testing.T, data []byte) {\n        // Call into the target. Ignore expected errors; let unexpected\n        // panics surface as findings.\n        _, _ = ParseSomething(data)\n    })\n}\n```\n\nThe inner `f.Fuzz` callback signature can use typed parameters instead of\n`[]byte` when the target expects structured input:\n\n```go\nf.Fuzz(func(t *testing.T, s string, n int, b bool) {\n    _ = ProcessRecord(s, n, b)\n})\n```\n\n### Building in OSS-Fuzz\n\nUse the `compile_native_go_fuzzer` helper in `build.sh`. It takes the package\nimport path, the function name, and the output binary name:\n\n```bash\n# build.sh\ncp $SRC/fuzz_test.go ./          # copy harness into the module if needed\nprintf \"package mypkg\\nimport _ \\\"github.com/AdamKorcz/go-118-fuzz-build/testing\\\"\\n\" \\\n    > register.go                # required registration shim\ngo mod tidy\ncompile_native_go_fuzzer github.com/owner/repo/pkg FuzzMyTarget fuzz_my_target\n```\n\nFor projects with multiple packages or multiple fuzz targets repeat the call:\n\n```bash\ncompile_native_go_fuzzer github.com/owner/repo/pkg1 FuzzFoo fuzz_foo\ncompile_native_go_fuzzer github.com/owner/repo/pkg2 FuzzBar fuzz_bar\n```\n\n### Seed corpus and dictionaries\n\n- Seed corpus entries go in `$OUT/<fuzzer_name>_seed_corpus/` as individual\n  files, or as a zip at `$OUT/<fuzzer_name>_seed_corpus.zip`.\n- Dictionaries go in `$OUT/<fuzzer_name>.dict` as plaintext token files.\n- Alternatively, add seeds directly via `f.Add(...)` in the harness — these\n  are compiled in and used as the initial corpus.\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks. See the [structured seed generation\n  reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good Go fuzzing harnesses\n\n1. **Targets attack surface**: focus on parsers, decoders, protocol handlers,\n   serialisation/deserialisation, and any API that accepts untrusted bytes or\n   strings.\n2. **Handles expected errors gracefully**: wrap calls in error checks and ignore\n   expected error returns. Only genuine panics and unexpected behaviour are\n   findings.\n3. **Uses typed fuzz parameters** when the target is not purely byte-oriented —\n   Go's fuzzer can mutate `string`, `int`, `bool`, `float64`, etc. directly.\n4. **Avoids non-determinism**: do not use random sources, time, goroutines, or\n   global state that persists between calls.\n5. **Keeps the callback fast**: expensive setup (e.g. parsing config, opening\n   files) belongs outside `f.Fuzz(...)`, not inside the inner function.\n6. **Provides meaningful seeds**: `f.Add(...)` entries should be valid\n   representative inputs so coverage grows from the start.\n7. **Does not get stuck**: avoid code paths that busy-loop or block on I/O\n   inside the fuzz function.\n8. **Includes the registration shim**: the `import _\n   \"github.com/AdamKorcz/go-118-fuzz-build/testing\"` blank import is required\n   for OSS-Fuzz to hook into native Go fuzzing — never omit it.\n\n## What Go fuzzing finds\n\nGo is memory-safe, so the focus shifts from memory-corruption bugs to:\n\n- **Panics**: index out of range, nil pointer dereference, type assertion\n  failures, stack overflows — any unrecovered `panic` is a crash.\n- **Logic bugs**: incorrect parsing, silent data corruption, wrong output for\n  valid input.\n- **Infinite loops / hangs**: code that never returns on certain inputs\n  (detected by OSS-Fuzz's timeout).\n- **Incorrect error handling**: code that should return an error but panics\n  instead, or vice versa.\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash almost always means the harness itself is wrong (e.g.\n  missing error handling, bad seed, wrong package path).\n- Run `go vet ./...` and `go build ./...` inside the module before wrapping in\n  an OSS-Fuzz build to catch compile errors early.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- Document why each entry point was chosen and what class of bugs it may find.\n\n<!-- File: infra/experimental/agent-skills/fuzzing-jvm-expert/SKILL.md (Tokens: ~1757 | Category: anthropic-skill) -->\n---\nname: fuzzing-jvm-expert\ndescription:\n  Use this skill to fuzz open source JVM projects (Java, Kotlin, Scala, etc.)\n  using Jazzer.\n---\n\n# Fuzzing JVM expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for JVM-based projects (Java, Kotlin, Scala, Groovy)\nintegrated into OSS-Fuzz. JVM fuzzing uses\n[Jazzer](https://github.com/CodeIntelligenceTesting/jazzer), which wraps\nlibFuzzer and instruments JVM bytecode for coverage guidance.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nJVM projects must use the JVM base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-jvm\n```\n\nSet `language: jvm` in `project.yaml`.\n\n### Harness structure — raw bytes\n\nThe simplest Jazzer harness receives raw bytes via `fuzzerTestOneInput`:\n\n```java\nimport com.code_intelligence.jazzer.api.FuzzedDataProvider;\n\npublic class MyTargetFuzzer {\n    public static void fuzzerTestOneInput(byte[] data) {\n        try {\n            MyLibrary.parse(data);\n        } catch (ExpectedExceptionType e) {\n            // Ignore expected exceptions; they are not bugs.\n        }\n    }\n}\n```\n\n### Harness structure — typed input via FuzzedDataProvider\n\n`FuzzedDataProvider` splits the raw byte stream into typed values, which is\nessential for targets that require structured input:\n\n```java\nimport com.code_intelligence.jazzer.api.FuzzedDataProvider;\n\npublic class MyTargetFuzzer {\n    public static void fuzzerTestOneInput(FuzzedDataProvider data) {\n        String header    = data.consumeString(64);\n        int    version   = data.consumeInt();\n        byte[] payload   = data.consumeRemainingAsBytes();\n\n        try {\n            MyLibrary.process(header, version, payload);\n        } catch (IllegalArgumentException | IOException e) {\n            // Expected — not a finding.\n        }\n    }\n}\n```\n\nUseful `FuzzedDataProvider` methods:\n\n| Method | Description |\n|---|---|\n| `consumeBytes(n)` | `byte[]` of length n |\n| `consumeRemainingAsBytes()` | all remaining bytes |\n| `consumeString(maxLen)` | arbitrary String |\n| `consumeAsciiString(maxLen)` | ASCII-only String |\n| `consumeInt()` / `consumeInt(min, max)` | int |\n| `consumeLong()` | long |\n| `consumeBoolean()` | boolean |\n| `consumeDouble()` | double |\n| `pickValue(collection)` | random element |\n\n### One-time setup with `fuzzerInitialize`\n\nIf initialisation is expensive (loading config, creating DB connections, etc.),\nput it in an optional static method that Jazzer calls once before fuzzing:\n\n```java\npublic class MyTargetFuzzer {\n    private static MyClient client;\n\n    public static void fuzzerInitialize() {\n        client = new MyClient(/* static config */);\n    }\n\n    public static void fuzzerTestOneInput(FuzzedDataProvider data) {\n        client.process(data.consumeRemainingAsBytes());\n    }\n}\n```\n\n### Building in OSS-Fuzz\n\nThe `build.sh` pattern for Maven projects:\n\n```bash\n# Build the project JARs.\n$MVN package -DskipTests -Dmaven.javadoc.skip=true\n\n# Collect JARs needed at runtime.\nALL_JARS=\"mylib-1.0.jar\"\nBUILD_CLASSPATH=$(echo $ALL_JARS | xargs printf -- \"$OUT/%s:\"):$JAZZER_API_PATH\nRUNTIME_CLASSPATH=$(echo $ALL_JARS | xargs printf -- \"\\$this_dir/%s:\"):\\$this_dir\n\nfor fuzzer in $(find $SRC -maxdepth 1 -name '*Fuzzer.java'); do\n    fuzzer_basename=$(basename -s .java \"$fuzzer\")\n    javac -cp $BUILD_CLASSPATH \"$fuzzer\"\n    cp $SRC/$fuzzer_basename.class $OUT/\n\n    # Wrapper script that launches jazzer_driver with the right arguments.\n    echo \"#!/bin/bash\nthis_dir=\\$(dirname \\\"\\$0\\\")\nif [[ \\\"\\$@\\\" =~ (^| )-runs=[0-9]+($| ) ]]; then\n  mem_settings='-Xmx1900m:-Xss900k'\nelse\n  mem_settings='-Xmx2048m:-Xss1024k'\nfi\nLD_LIBRARY_PATH=\\\"$JVM_LD_LIBRARY_PATH\\\":\\$this_dir \\\\\n\\$this_dir/jazzer_driver --agent_path=\\$this_dir/jazzer_agent_deploy.jar \\\\\n--instrumentation_includes=com.example.** \\\\\n--cp=$RUNTIME_CLASSPATH \\\\\n--target_class=$fuzzer_basename \\\\\n--jvm_args=\\\"\\$mem_settings\\\" \\\\\n\\$@\" > $OUT/$fuzzer_basename\n    chmod u+x $OUT/$fuzzer_basename\ndone\n```\n\nFor Gradle projects replace `$MVN package` with the appropriate Gradle command\nand adjust JAR paths accordingly.\n\n### Seed corpus and dictionaries\n\n- Zip seed files to `$OUT/<fuzzer_name>_seed_corpus.zip`.\n- Place dictionaries at `$OUT/<fuzzer_name>.dict`.\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks. See the [structured seed generation\n  reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good JVM fuzzing harnesses\n\n1. **Targets attack surface**: parsers, deserializers (JSON, XML, Protobuf,\n   custom binary formats), network protocol handlers, template engines, and\n   any API that accepts untrusted bytes or strings.\n2. **Catches expected exceptions**: wrap calls in `try/catch` for all\n   documented exception types. Only unexpected exceptions and crashes are\n   findings.\n3. **Uses `FuzzedDataProvider`** for structured input rather than passing raw\n   bytes to methods that expect well-formed data.\n4. **Initialises heavy state in `fuzzerInitialize`**: client connections,\n   parsers with complex configuration, and loaded schemas should be set up once.\n5. **Avoids non-determinism**: no `Math.random()`, no `System.currentTimeMillis()`\n   in the fuzzing path, no thread spawning.\n6. **Sets `--instrumentation_includes`** to the package prefix of the target\n   library in the wrapper script — without this Jazzer cannot guide fuzzing.\n7. **Configures JVM memory appropriately**: use the `mem_settings` pattern\n   shown above to avoid OOM kills during runs vs. crash reproduction.\n8. **Avoids false positives**: `OutOfMemoryError`, `StackOverflowError`, and\n   `NullPointerException` on invalid input are usually expected — decide which\n   are genuine bugs for this project.\n\n## What JVM fuzzing finds\n\n- **Unexpected exceptions**: `NullPointerException`, `ArrayIndexOutOfBoundsException`,\n  `ClassCastException`, `NumberFormatException` on paths that should not throw.\n- **Assertion errors and contract violations**: internal consistency checks\n  that fail on adversarial input.\n- **Hang / infinite loops**: detected by OSS-Fuzz's timeout.\n- **Security bugs**: deserialization gadgets, path traversal via crafted\n  filenames, SSRF via crafted URLs — depends on the library.\n- **Logic bugs**: incorrect output for valid-ish input.\n\nJazzer can also detect:\n- SQL injection (via JDBC hooks)\n- Path traversal (via file API hooks)\n- Command injection (via `Runtime.exec` hooks)\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash usually means a missing JAR on the classpath or an\n  uncaught expected exception — check `check_build` output carefully.\n- Build the project outside the fuzzing harness first (`mvn package` or\n  `gradle build`) to ensure the project itself compiles cleanly.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- Document why each entry point was chosen and what class of bugs it may find.\n\n<!-- File: infra/experimental/agent-skills/fuzzing-memory-unsafe-expert/SKILL.md (Tokens: ~4895 | Category: anthropic-skill) -->\n---\nname: fuzzing-memory-unsafe-expert\ndescription:\n  Use this skill to fuzz open source C/C++ software projects.\n---\n\n# Fuzzing memory-unsafe expert\n\nThis skill provides the agent with the necessary knowledge and tools to fuzz open source software projects, particularly those that are part of the OSS-Fuzz program. The agent can use this skill to build fuzzers, run fuzzing campaigns, analyze results, and improve the fuzzing posture of projects.\n\nThe fuzzing abilities focused on here is libFuzzer-style harnesses, which are commonly used in OSS-Fuzz.\n\n## Threat modelling and attack surface\n\nBefore writing a single line of harness code, decide **what you are trying to\nfind and where an attacker's input actually enters the code**. A harness is\nonly as good as the entry point it targets: a technically-correct harness\npointed at code no attacker can influence finds bugs no maintainer will fix.\nThis step is what separates a valuable harness from a noisy one.\n\n### What a threat model answers\n\nFor the target project, answer these four questions explicitly and write the\nanswers into the harness's rationale doc:\n\n1. **What input is untrusted?** The data an attacker can control — a file\n   downloaded and opened, bytes arriving on a socket, a message from another\n   process, a document pasted into an editor. Trusted input (a config file the\n   admin wrote, a compile-time constant, a path only the program itself\n   constructs) is *not* an attacker's lever and is usually out of scope.\n2. **Where does that input cross a trust boundary?** The exact function(s)\n   where untrusted bytes first reach parsing/processing logic. This is the\n   entry point your harness should call.\n3. **What does the attacker control at that boundary?** The whole buffer? Only\n   a length field, with the rest validated upstream? A filename but not its\n   contents? This determines what your harness should mutate and what it should\n   hold fixed.\n4. **What would count as a real bug here?** A memory-safety violation (ASan/\n   MSan/UBSan finding) on attacker-reachable input is almost always in scope. A\n   crash that requires trusted/malformed *developer* input, or an\n   `assert()`-guarded programmer-error precondition, usually is not — fuzzing it\n   produces findings maintainers reject.\n\n### Identifying the attack surface\n\nConcrete, common attack surfaces in C/C++ projects, and the entry points to\ntarget for each:\n\n- **File-format parsers / loaders** (image, audio, video, fonts, archives,\n  documents). Entry point: the function that takes a buffer or file and decodes\n  it — e.g. `png_read_info`, `TIFFClientOpen`, `av_read_frame`,\n  `archive_read_open_memory`. Attacker controls the whole file. High-value,\n  classic OSS-Fuzz target.\n- **Network / wire-protocol handlers** (packet parsers, TLS records, HTTP,\n  DNS, RPC deserialisation). Entry point: the function fed raw bytes off the\n  wire, e.g. `SSL_read`, `parse_packet`, `deserialize_message`. Attacker\n  controls the byte stream; often you must also drive a state machine (see the\n  reachability note below).\n- **Serialisation / IPC boundaries** (protobuf/JSON/CBOR/ASN.1 decoders,\n  shared-memory messages, clipboard, environment when spawned by another\n  privilege domain). Entry point: the *decode* direction — the untrusted side\n  is bytes-in, not object-out.\n- **Text / query languages** (SQL, regex, template engines, config-language\n  parsers, expression evaluators). Entry point: the compile/parse function that\n  accepts an arbitrary string.\n- **Decompression and codecs** (zlib, lz4, zstd, JPEG/HEIF bitstreams). Entry\n  point: the decompress/decode call on attacker-supplied compressed data —\n  these are prime targets because a small input expands into large, structured\n  work.\n\n### Deriving the harness from the threat model\n\nThe threat model dictates the harness shape:\n\n- **Target the untrusted-input direction only.** Fuzz the *decoder*, not the\n  encoder; the *reader*, not the writer — unless the writer also consumes\n  attacker-controlled data.\n- **Mutate exactly what the attacker controls; fix the rest.** If the attacker\n  controls a document but not the parser's configuration, mutate the document\n  bytes and hold the config constant (set it once in `LLVMFuzzerInitialize`).\n  Fuzzing the config too invents a threat that does not exist and yields\n  rejected findings.\n- **Enter at the real trust boundary, not below it.** Calling a deep internal\n  helper directly may crash on inputs the public API would have rejected\n  upstream — a false positive. Prefer the outermost function an attacker's data\n  actually reaches. If you must call an internal function for coverage, first\n  confirm the upstream validation it assumes, and reproduce that precondition\n  in the harness.\n- **Honour the API contract to avoid false positives.** If a function is\n  documented to require NUL-terminated input, a valid handle, or a\n  pre-allocated output buffer, supply those — a crash from violating the\n  contract is a harness bug, not a target bug (this is the \"True Positives\"\n  characteristic below).\n\n### Reachability: entry point is not enough\n\nAn entry point that is untrusted-reachable in production may still be\n*unreachable* from your harness if getting to the interesting code requires\nstate the harness never sets up — an open session, a completed handshake, a\nprior header packet, a registered codec. Two consequences:\n\n- If the deep code needs prior state, **build that state in the harness**\n  (e.g. feed a valid header, complete the handshake) before feeding the mutated\n  bytes — otherwise the fuzzer never gets past the front door and coverage\n  stays shallow.\n- Cross-check with the coverage data (see the OSS-Fuzz engineer skill): if a\n  file you believe is attacker-reachable sits dark in `summary.json`, decide\n  whether it is *seed-limited* (a better corpus would reach it — write seeds) or\n  *harness-limited* (no input reaches it as the harness stands — the harness\n  itself must set up more state).\n\n### A worked example\n\nConsider a library that loads a custom image format via\n`int img_load(const uint8_t *buf, size_t len, img_opts *opts)`, where `opts`\ncomes from the application, not the file:\n\n- **Untrusted input:** `buf`/`len` (the image file). **Trusted:** `opts`.\n- **Trust boundary / entry point:** `img_load` — the outermost public function\n  an attacker's bytes reach.\n- **Attacker controls:** the entire image buffer, not the options.\n- **Real bug:** any ASan/UBSan finding decoding a crafted image.\n\nThe harness therefore fixes `opts` to a representative default once, and feeds\nthe mutated bytes as `buf`/`len`:\n\n```cpp\n#include <fuzzer/FuzzedDataProvider.h>\n\nstatic img_opts g_opts;  // trusted config, set once — not fuzzed.\n\nextern \"C\" int LLVMFuzzerInitialize(int *argc, char ***argv) {\n    img_opts_default(&g_opts);   // represents the real application's setup\n    return 0;\n}\n\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {\n    // Attacker controls the whole file; feed it directly.\n    img_load(data, size, &g_opts);\n    return 0;\n}\n```\n\nFuzzing `opts` instead, or calling an internal `decode_scanline` directly with\nraw bytes, would either invent a non-existent threat or trip asserts the public\nAPI prevents — both produce findings maintainers will not act on.\n\n## Fundamental Concepts\n\n### Fuzzing harness core function\n\nA fuzzing harness is a function that takes a byte array as input and processes it in a way that can trigger bugs or vulnerabilities in the software being tested. The core function of a fuzzing harness typically looks like this:\n\n```cpp\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {\n    // Process the input data and trigger potential bugs\n    return 0; // Return 0 to indicate successful processing\n}\n```\n\nReturn `0` in all normal cases. Return `-1` to tell libFuzzer to reject an\ninput and not add it to the corpus (rarely needed). Never `exit()` on bad\ninput — it aborts the whole run and breaks coverage tooling.\n\n### Extracting typed input with FuzzedDataProvider\n\nMost non-trivial targets do not take a single flat byte buffer — they need an\ninteger here, a length there, a string, several sub-buffers. Passing the raw\n`data`/`size` directly to such an API means the fuzzer almost never produces a\nwell-formed call. `FuzzedDataProvider` splits the one input stream into typed\nvalues, so libFuzzer's mutations map onto the parameters the target actually\nexpects. It is the standard tool for this in OSS-Fuzz (used by well over a\nhundred projects) and is shipped in the base image — no dependency to add:\n\n```cpp\n#include <fuzzer/FuzzedDataProvider.h>\n\nextern \"C\" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {\n    FuzzedDataProvider fdp(data, size);\n\n    // Consume typed, bounded values up front...\n    int         width  = fdp.ConsumeIntegralInRange<int>(1, 4096);\n    bool        strict = fdp.ConsumeBool();\n    std::string name   = fdp.ConsumeRandomLengthString(64);\n    // ...then hand the rest of the bytes to the payload argument.\n    std::vector<uint8_t> payload = fdp.ConsumeRemainingBytes<uint8_t>();\n\n    my_decode(name.c_str(), width, strict, payload.data(), payload.size());\n    return 0;\n}\n```\n\nCommonly used methods (see `compiler-rt`'s `FuzzedDataProvider.h` for the full\nset):\n\n| Method | Description |\n|---|---|\n| `ConsumeIntegral<T>()` | one integer of type `T` |\n| `ConsumeIntegralInRange<T>(min, max)` | integer bounded to `[min, max]` — use this to pick sizes, indices, enum values |\n| `ConsumeBool()` | one boolean |\n| `ConsumeEnum<E>()` | a value of a scoped enum with `kMaxValue` |\n| `ConsumeFloatingPoint<T>()` / `...InRange(min, max)` | float/double |\n| `ConsumeRandomLengthString(max)` | a `std::string` whose length the fuzzer controls (stops at an escaped `\\`) |\n| `ConsumeBytes<T>(count)` / `ConsumeBytesAsString(count)` | exactly `count` bytes |\n| `ConsumeRemainingBytes<T>()` / `ConsumeRemainingBytesAsString()` | everything left |\n| `remaining_bytes()` | how many bytes are left to consume |\n\nGuidance:\n\n- **Consume in a fixed order and document it.** The mapping from bytes to\n  parameters must be stable, or a saved crash will not reproduce.\n- **Consume the variable-length / \"rest of the input\" argument last** with\n  `ConsumeRemaining...`. Consuming a fixed count first and the remainder last\n  keeps the layout robust to mutation.\n- **Bound sizes and indices with `ConsumeIntegralInRange`** rather than masking\n  a raw integer — it wastes fewer inputs and keeps allocations sane.\n- Use FDP when the target needs structure; for a target that genuinely takes\n  one opaque buffer (a single `parse(data, size)`), pass `data`/`size` straight\n  through — FDP would only add noise.\n\n### One-time setup with LLVMFuzzerInitialize\n\nIf the harness needs setup that must happen once before fuzzing (parsing\n`argv`, setting environment variables, initialising a library global), put it\nin the optional `LLVMFuzzerInitialize` hook, which libFuzzer calls once at\nstartup — never do per-input work there:\n\n```cpp\nextern \"C\" int LLVMFuzzerInitialize(int *argc, char ***argv) {\n    setenv(\"HOME\", \"/tmp\", 1);\n    my_library_global_init();\n    return 0;\n}\n```\n\nKeep expensive but per-process-constant state (loaded config, a compiled\nschema, an allocated context reused across inputs) in a file-scope\n`static`/global initialised once — either here or lazily on the first\n`LLVMFuzzerTestOneInput` call — so it is not rebuilt on every iteration.\n\n### Sanitizers are the bug oracle\n\nA C/C++ harness rarely detects a bug by itself — the sanitizer the project is\nbuilt with is what turns silent memory corruption into a crash the fuzzer can\ncatch. OSS-Fuzz builds each target under a sanitizer (default AddressSanitizer;\nalso UndefinedBehaviorSanitizer and MemorySanitizer):\n\n- **ASan** — heap/stack/global buffer overflows, use-after-free, double-free,\n  leaks. The default and highest-value oracle.\n- **UBSan** — signed overflow, invalid shifts, misaligned/`null` pointer use,\n  bad casts, invalid enum values.\n- **MSan** — reads of uninitialised memory. Requires *all* linked code\n  (including dependencies) to be instrumented, or it reports false positives —\n  only enable it when the whole dependency chain is built under MSan.\n\nDesign implication: the harness's job is to *reach* untrusted-input-driven\nmemory operations with enough variety; the sanitizer reports the violation.\n`build.sh` must compile both the target library and the harness with the\nOSS-Fuzz `$CFLAGS`/`$CXXFLAGS` (which carry the sanitizer + coverage flags) —\nlinking against a separately, non-instrumented build silently disables the\noracle and coverage guidance.\n\n### Building in OSS-Fuzz\n\n`build.sh` compiles the project (as a static library where possible) and then\ncompiles + links each harness against it with `$LIB_FUZZING_ENGINE`. Always use\nthe OSS-Fuzz-provided `$CC`/`$CXX` and `$CFLAGS`/`$CXXFLAGS` so instrumentation\nand the sanitizer are applied:\n\n```bash\n# build.sh — build the library with instrumentation, statically.\nmkdir build && cd build\ncmake -DBUILD_SHARED_LIBS=OFF ..     # a static .a is easiest to link the harness against\nmake -j$(nproc)\ncd ..\n\n# Compile and link each harness against the instrumented library.\nfor f in $SRC/project/fuzz/*_fuzzer.cc; do\n    fuzzer=$(basename \"$f\" _fuzzer.cc)\n    $CXX $CXXFLAGS -std=c++17 -I$SRC/project/include \\\n        \"$f\" -o \"$OUT/${fuzzer}\" \\\n        $LIB_FUZZING_ENGINE \"$SRC/project/build/libproject.a\"\ndone\n```\n\nKey points:\n\n- Link the harness with **`$LIB_FUZZING_ENGINE`**, not a hardcoded\n  `-fsanitize=fuzzer` — this lets OSS-Fuzz swap the engine (libFuzzer, AFL++,\n  Centipede, or the coverage/`check_build` no-op engine).\n- Prefer a **static** project build; it avoids `LD_LIBRARY_PATH` juggling at\n  run time and ensures the linked code is instrumented.\n- Copy seed corpora (`$OUT/<fuzzer>_seed_corpus.zip`) and dictionaries\n  (`$OUT/<fuzzer>.dict`) in the same script.\n\n### Examples of good harnesses already in OSS-Fuzz\n\nStudy existing harnesses before writing your own — they show the idioms above\napplied to real projects, and matching an established style makes your harness\neasier for maintainers to accept. Each example below is checked into this\nrepository; open the file and read it in full.\n\n- **`projects/sentencepiece/sample_encode_fuzzer.cc`** — the canonical\n  `FuzzedDataProvider` split. It carves the one input into an `int`\n  (`ConsumeIntegral`), a `float` (`ConsumeFloatingPoint`) and the remaining\n  bytes as the text argument (`ConsumeRemainingBytesAsString`), then calls\n  `SampleEncodeAsSerializedProto(text, nbest, alpha)`. Note the ordering: the\n  fixed-size scalars are consumed first and the variable-length string last.\n  This is the template whenever the target API takes several typed parameters\n  rather than one buffer.\n\n- **`projects/spdlog/fuzz/pattern_fuzzer.cc`** — lazy one-time initialisation\n  and a tightly-scoped threat model. A `static` logger is created on the first\n  call and reused across iterations (never rebuilt per input), it guards\n  `size == 0`, and it fuzzes exactly one attacker-relevant entry point:\n  `spdlog::set_pattern(str)`, the format-pattern parser. It does *not* fuzz the\n  logging config — a clean example of \"mutate only what the attacker controls.\"\n\n- **`projects/file/magic_fuzzer_fd.cc`** — `LLVMFuzzerInitialize` for expensive\n  setup, and feeding an API that needs a real file descriptor. The magic\n  database is loaded once in an `Environment` built from `argv[0]`'s directory\n  (setup that must not repeat per input), and each input is written to a\n  `FuzzerTemporaryFile` so it can be handed to `magic_descriptor(fd)`. Use this\n  pattern when the target only accepts a path/`fd` rather than an in-memory\n  buffer — but note that going through a temp file is slower, so prefer an\n  in-memory entry point when the library exposes one.\n\nWhen extending an existing OSS-Fuzz project, the best reference is that\nproject's *own* existing harnesses: match their file layout, naming\n(`*_fuzzer.cc`), build-script wiring and error-handling conventions.\n\n### Characteristics found in good fuzzing harnesses\n\nThe below are characteristics commonly found in good fuzzing harnesses, which contribute to their effectiveness in finding bugs. They are not all necessary for a good harness and at times it may even be desirable to actively not pursue some of them.\n\n1. **Simplicity**: The harness should be simple and focused on processing the input data without unnecessary complexity.\n2. **Coverage**: The harness should aim to cover as much of the codebase as possible, including edge cases and error handling paths.\n3. **Determinism**: The harness should produce consistent results for the same input, allowing for reliable reproduction of bugs.\n4. **Performance**: The harness should be efficient in processing inputs to maximize the number of test cases that can be executed in a given time frame.\n5. **Error Handling**: The harness should include robust error handling to capture and report any issues that arise during fuzzing.\n6. **True Positives**: The harness should be designed to have no false positives, ensuring that reported issues are genuine bugs. This means all issues found by the fuzzer is something the maintainers are interested in fixing.\n7. **Matches threat model**: The harness should be designed to target specific types of vulnerabilities that are relevant to the project being fuzzed.\n8. **Hits code on the attack surface**: The harness should be designed to target code that is exposed to untrusted input, such as network interfaces, file parsers, or APIs.\n9. **Enough entropy**: The harness should be designed to allow for a wide range of inputs, providing enough variability to trigger different code paths and potential bugs.\n10. **Follows the code structure**: The harness should be designed to follow the structure of the codebase, making it easier to identify and target specific areas of interest.\n11. **Follows code conventions**: The harness should follow the coding conventions of the project, making it easier for maintainers to understand and integrate the harness into the codebase.\n12. **Does not get stuck**: The harness should be designed to avoid getting stuck on certain inputs or code paths, allowing the fuzzer to continue exploring other areas of the codebase.\n13. **Includes dictionary**: The harness should include a dictionary of known inputs or patterns that are relevant to the project, helping the fuzzer to generate more effective test cases.\n\n### Operational guidelines\n\n- Always build and run fuzzing harnesses to validate they work. This can for example be done in a oss-fuzz environment:\n\n```\npython3 infra/helper.py build_fuzzers <project_name>\npython3 infra/helper.py run_fuzzer <project_name> <fuzzer_name> -- -max_total_time=30 # run the fuzzer for 30 seconds to validate it works\npython3 infra/helper.py check_build <project_name>\n```\n\n- If a fuzzer runs into a crash instantly, it's very likely wrong.\n- Always document the rationale for design decisions in the fuzzing harness, and the rationale for why the harness is expected to find bugs. This can be done in a markdown file in the same directory as the fuzzing harness, or in comments in the code of the fuzzing harness itself.\n- Look for function entrypoints that are exposed to untrusted input, and try to design fuzzing harnesses that target these entrypoints. This is often the most effective way to find security bugs.\n- When extending existing fuzzing harnesses, always validate that the existing code coverage does not digress. You should empirically evaluate this and give a justification that no digression has happened, or if it has happened then you should give a justification for why the digression is acceptable in light of the achieved extension.\n- When extending fuzzing harnesses you should give justification for the impact of bugs that they will find.\n\n### Seed corpus and structured generation\n\nA good harness needs a good initial corpus. Place seed files in\n`$OUT/<fuzzer_name>_seed_corpus.zip` and dictionaries in\n`$OUT/<fuzzer_name>.dict`.\n\nFor targets that parse a structured format (binary containers like ELF/PE, or\ncodec/network bitstreams, or text grammars), a few hand-picked sample files\nare rarely enough: random mutation almost never gets past the parser's magic /\nlength / checksum checks, so the deep parsing code stays dark. The most\neffective approach is a **script that constructs structurally-valid inputs\nfrom scratch**, run from `build.sh` and appended to the corpus. It is\nreproducible, needs no external samples, and lets you target specific\ndark-but-reachable code identified from coverage. See the OSS-Fuzz engineer\nskill's [structured seed generation\nreference](../oss-fuzz-engineer/references/structured_seed_generation.md) for\nthe full workflow and `projects/vlc/generate_seeds.py` for a worked example.\n\n<!-- File: infra/experimental/agent-skills/fuzzing-python-expert/SKILL.md (Tokens: ~1605 | Category: anthropic-skill) -->\n---\nname: fuzzing-python-expert\ndescription:\n  Use this skill to fuzz open source Python software projects using Atheris.\n---\n\n# Fuzzing Python expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for Python projects integrated into OSS-Fuzz. Python\nfuzzing uses [Atheris](https://github.com/google/atheris), which wraps libFuzzer\nand instruments Python bytecode for coverage-guided fuzzing.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nPython projects must use the Python base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-python\n```\n\nSet `language: python` in `project.yaml`.\n\n### Harness structure\n\nA Python fuzz target is a `.py` file (named `fuzz_<target>.py` by convention)\nthat follows this pattern:\n\n```python\n#!/usr/bin/python3\nimport sys\nimport atheris\n\n# Import the module under test after atheris.instrument_imports() or within\n# the atheris.instrument_all() context so bytecode is instrumented.\n\ndef TestOneInput(data):\n    fdp = atheris.FuzzedDataProvider(data)\n    # Extract typed values from the raw fuzzer bytes.\n    value = fdp.ConsumeString(128)\n    try:\n        my_module.parse(value)\n    except (ValueError, TypeError, KeyError):\n        # Expected exceptions from invalid input are not bugs.\n        pass\n\ndef main():\n    atheris.instrument_all()   # instrument all loaded Python modules\n    atheris.Setup(sys.argv, TestOneInput, enable_python_coverage=True)\n    atheris.Fuzz()\n\nif __name__ == \"__main__\":\n    main()\n```\n\n### Instrumenting imports selectively\n\nWhen `instrument_all()` is too broad (e.g. causes conflicts with C extensions),\ninstrument specific modules using the `instrument_imports()` context manager:\n\n```python\nimport atheris\nwith atheris.instrument_imports():\n    import my_module\n    import my_module.subpackage\n```\n\n### FuzzedDataProvider reference\n\n`atheris.FuzzedDataProvider` splits the raw byte stream into typed values:\n\n| Method | Description |\n|---|---|\n| `ConsumeBytes(count)` | `bytes` of length count |\n| `ConsumeByteList(count)` | `list[int]` of length count |\n| `ConsumeString(count)` | decoded `str` (may contain surrogates) |\n| `ConsumeUnicode(count)` | `str` without surrogates |\n| `ConsumeUnicodeNoSurrogates(count)` | strict `str` |\n| `ConsumeInt(nbytes)` | signed int from nbytes |\n| `ConsumeIntInRange(min, max)` | int in range |\n| `ConsumeFloat()` | float |\n| `ConsumeBool()` | bool |\n| `ConsumeIntList(count, nbytes)` | list of ints |\n| `PickValueInList(lst)` | random element |\n| `ConsumeRemainingBytes()` | all remaining bytes |\n\n### Building in OSS-Fuzz\n\n`build.sh` installs the target package and uses the `compile_python_fuzzer`\nhelper to turn each `fuzz_*.py` file into a standalone fuzzer binary in `$OUT`:\n\n```bash\n# build.sh\n\n# Install the package under test.\npip3 install .\n\n# Compile all fuzz targets found in $SRC.\nfor fuzzer in $(find $SRC -name 'fuzz_*.py'); do\n    compile_python_fuzzer \"$fuzzer\"\ndone\n```\n\n`compile_python_fuzzer` handles linking against Atheris and libFuzzer and\nproduces an executable in `$OUT` named after the `.py` file.\n\n### Seed corpus and dictionaries\n\n- Place seed files in `$OUT/<fuzzer_name>_seed_corpus/` or zip them as\n  `$OUT/<fuzzer_name>_seed_corpus.zip`.\n- Dictionaries go to `$OUT/<fuzzer_name>.dict` — especially valuable for\n  text-format parsers (JSON, XML, YAML, CSV, etc.).\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks. See the [structured seed generation\n  reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good Python fuzzing harnesses\n\n1. **Instruments the right modules**: use `instrument_all()` for simplicity or\n   `instrument_imports()` for targeted instrumentation. Without instrumentation\n   coverage guidance is blind.\n2. **Targets attack surface**: parsers, template engines, serialisation\n   (pickle, JSON, YAML, XML), network protocol handling, and any API that\n   accepts untrusted strings or bytes.\n3. **Catches expected exceptions**: wrap target calls in `try/except` for the\n   documented exception types the target raises on bad input. Only unexpected\n   exceptions and hard crashes are findings.\n4. **Uses `FuzzedDataProvider` for structured input** rather than feeding raw\n   bytes directly to APIs that expect text — most Python APIs work on strings,\n   not bytes.\n5. **Avoids importing under test inside `TestOneInput`**: imports should happen\n   at module level (inside the `instrument_imports()` block if used) so they\n   are instrumented and not re-executed per iteration.\n6. **Is fast**: avoid file I/O, network calls, or subprocess invocations inside\n   `TestOneInput`.\n7. **Avoids non-determinism**: no `random`, no `datetime.now()`, no\n   `os.urandom()` inside the fuzz function.\n8. **Enables Python coverage**: pass `enable_python_coverage=True` to\n   `atheris.Setup` for bytecode-level coverage tracking.\n\n## What Python fuzzing finds\n\nPython is memory-safe, so the focus is on:\n\n- **Unhandled exceptions**: `ValueError`, `RecursionError`, `MemoryError`,\n  `UnicodeDecodeError`, and any exception the library should have caught and\n  converted to a clean error.\n- **`AssertionError`**: internal invariant violations triggered by crafted\n  input.\n- **Hangs / infinite loops**: detected by OSS-Fuzz's timeout.\n- **Crashes in C extensions**: Python libraries that wrap C code (e.g. lxml,\n  Pillow, cryptography) can still have memory-corruption bugs in their C layer,\n  which Atheris will surface because libFuzzer runs the whole process.\n- **Logic errors**: incorrect output, silent data corruption, wrong parsing\n  results on edge-case inputs.\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash usually means an exception is being raised on every input.\n  Run the harness locally (`python3 fuzz_target.py`) on a sample input to\n  debug before building through OSS-Fuzz.\n- Test the harness locally before the OSS-Fuzz build:\n  ```python\n  python3 fuzz_target.py <seed_file>\n  ```\n  Atheris supports running in single-input mode outside libFuzzer.\n- Install the package locally (`pip3 install .`) and iterate quickly before\n  going through the Docker build.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- Document why each entry point was chosen and what class of bugs it may find.\n\n<!-- File: infra/experimental/agent-skills/fuzzing-rust-expert/SKILL.md (Tokens: ~1472 | Category: anthropic-skill) -->\n---\nname: fuzzing-rust-expert\ndescription:\n  Use this skill to fuzz open source Rust software projects.\n---\n\n# Fuzzing Rust expert\n\nThis skill provides the agent with the knowledge and tools to write, build, and\nvalidate fuzz targets for Rust projects integrated into OSS-Fuzz. Rust fuzzing\nuses cargo-fuzz with the `libfuzzer_sys` crate, which drives libFuzzer.\n\n## Fundamental Concepts\n\n### OSS-Fuzz base image\n\nRust projects must use the Rust base builder image:\n\n```dockerfile\nFROM gcr.io/oss-fuzz-base/base-builder-rust\n```\n\nSet `language: rust` in `project.yaml`.\n\n### Harness structure\n\nRust fuzz targets live in `fuzz/fuzz_targets/<name>.rs` within the crate being\nfuzzed. The minimal harness using raw bytes:\n\n```rust\n#![no_main]\nuse libfuzzer_sys::fuzz_target;\n\nfuzz_target!(|data: &[u8]| {\n    // Call into the target. The fuzzer will mutate `data` on every iteration.\n    let _ = my_crate::parse(data);\n});\n```\n\nFor structured fuzzing using the `arbitrary` crate (preferred when the target\nexpects typed input):\n\n```rust\n#![no_main]\nuse libfuzzer_sys::fuzz_target;\nuse arbitrary::Arbitrary;\n\n#[derive(Debug, Arbitrary)]\nstruct MyInput {\n    header: u8,\n    payload: Vec<u8>,\n    flags: u32,\n}\n\nfuzz_target!(|input: MyInput| {\n    let _ = my_crate::process(input.header, &input.payload, input.flags);\n});\n```\n\nThe `Cargo.toml` for the fuzz directory must declare dependencies:\n\n```toml\n# fuzz/Cargo.toml\n[package]\nname = \"my-crate-fuzz\"\nversion = \"0.0.0\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nlibfuzzer-sys = \"0.4\"\narbitrary = { version = \"1\", features = [\"derive\"] }   # only if using structured fuzzing\n\n[dependencies.my-crate]\npath = \"..\"\n\n[[bin]]\nname = \"fuzz_target_name\"\npath = \"fuzz_targets/fuzz_target_name.rs\"\ntest = false\ndoc = false\n```\n\n### Building in OSS-Fuzz\n\n`build.sh` uses `cargo fuzz build` and then copies binaries to `$OUT`:\n\n```bash\n# build.sh\ncd $SRC/<crate-dir>\ncargo fuzz build -O   # -O enables release optimisations; important for performance\n\nFUZZ_TARGET_OUTPUT_DIR=$SRC/<crate-dir>/target/x86_64-unknown-linux-gnu/release\nfor f in fuzz/fuzz_targets/*.rs; do\n    name=$(basename \"${f%.*}\")\n    cp \"$FUZZ_TARGET_OUTPUT_DIR/$name\" \"$OUT/\"\ndone\n```\n\nIf the project requires a nightly toolchain, set it in the Dockerfile:\n\n```dockerfile\nENV RUSTUP_TOOLCHAIN=nightly\n```\n\nOr pin to a specific nightly for reproducibility:\n\n```dockerfile\nENV RUSTUP_TOOLCHAIN=nightly-2025-07-03\n```\n\n### Seed corpus and dictionaries\n\n- Place seed files in `fuzz/corpus/<target_name>/` within the repo; they are\n  automatically picked up by cargo-fuzz and can be zipped for OSS-Fuzz.\n- To ship a corpus with OSS-Fuzz copy a zip to `$OUT/<target_name>_seed_corpus.zip`.\n- Dictionaries go to `$OUT/<target_name>.dict`.\n- For targets that parse a structured format, generating seeds with a script\n  beats hand-picking a few files — random mutation rarely passes the parser's\n  early checks (note: cargo-fuzz's `arbitrary` is the better route when the\n  target takes typed data rather than a byte format). See the [structured seed\n  generation reference](../oss-fuzz-engineer/references/structured_seed_generation.md).\n\n## Characteristics of good Rust fuzzing harnesses\n\n1. **Targets attack surface**: parsers, deserializers, protocol implementations,\n   unsafe blocks, and any API that processes untrusted bytes.\n2. **Uses structured fuzzing** (`arbitrary`) when the target expects typed data\n   rather than raw bytes — this dramatically improves coverage.\n3. **Handles expected errors**: `Result` and `Option` should be let-bound and\n   ignored (`let _ = ...`). Only actual panics are findings.\n4. **Avoids panicking on every input**: do not use `.unwrap()` or `.expect()`\n   on fallible operations driven by fuzz input — these create false positives.\n5. **Avoids non-determinism**: no `rand`, no system time, no thread spawning\n   inside the fuzz callback.\n6. **Is fast**: avoid I/O, heavy allocations, or expensive setup inside the\n   callback; do those outside the `fuzz_target!` macro if needed with\n   `LazyLock` / `OnceLock`.\n7. **Considers `unsafe` code**: if the crate has `unsafe` blocks, write\n   harnesses that exercise those paths — this is where memory bugs can still\n   occur in Rust.\n8. **Builds in release mode** (`-O`): fuzzing in debug mode is much slower.\n\n## What Rust fuzzing finds\n\nRust's ownership model prevents most memory-corruption bugs, but fuzzing still\nfinds:\n\n- **Panics**: `unwrap`/`expect` on `None`/`Err`, index out of bounds,\n  arithmetic overflow in debug mode, explicit `panic!` calls.\n- **`unsafe` bugs**: use-after-free, out-of-bounds reads/writes, undefined\n  behaviour in `unsafe` blocks — these are real memory bugs.\n- **Logic errors**: incorrect parsing, data corruption, wrong output.\n- **Hangs**: infinite loops triggered by crafted input.\n- **Stack overflows**: deep recursion on adversarial input.\n\n## Operational guidelines\n\n- Always validate with:\n  ```\n  python3 infra/helper.py build_fuzzers <project>\n  python3 infra/helper.py check_build <project>\n  python3 infra/helper.py run_fuzzer <project> <fuzzer_name> -- -max_total_time=30\n  ```\n- An instant crash usually means a `panic!` on every input — check for\n  `.unwrap()` calls on fuzz-driven paths and replace with `if let` or `?`.\n- Run `cargo build` and `cargo test` inside the crate before adding the fuzz\n  harness to catch pre-existing compilation errors.\n- When iterating locally clone the upstream repo and switch the Dockerfile from\n  `RUN git clone` to `COPY` to avoid network round-trips.\n- If the crate uses `no_std`, use `libfuzzer-sys`'s `no_std` feature and ensure\n  the harness does not rely on `std`.\n- Document why each entry point was chosen and what class of bugs it may find.\n\n<!-- File: infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/code_coverage.md)\n\n<!-- File: infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/helper.md)\n\n<!-- File: infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/oss_fuzz_project_structure.md)\n\n<!-- File: infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/infra/experimental/agent-skills/oss-fuzz-engineer/references/structured_seed_generation.md)\n\n<!-- File: infra/experimental/agent-skills/oss-fuzz-engineer/SKILL.md (Tokens: ~2891 | Category: anthropic-skill) -->\n---\nname: oss-fuzz-engineer\ndescription:\n  Use this skill to interact with the OSS-Fuzz infrastructure.\n---\n\n# OSS-Fuzz engineer\n\nThis skill guides the agent how to use the OSS-Fuzz infrastructure to find and report bugs in open source software. The agent can use this skill to integrate new projects, extend and improve the fuzzing posture of projects, run fuzzing campaigns, and fix broken existing OSS-Fuzz projects.\n\nWhen working on OSS-Fuzz tasks then you should also use any fuzzing related skills you have, such as code analysis and fuzzing harness writing skills, to achieve the best results.\n\n## Workflows\n\nThere are multiple common workflows that an OSS-Fuzz engineer might follow and we describe some imporant ones here.\n\n### Integrating a new project\n\nGiven a reference to an open source project, such as a link to a GitHub repository, the agent can follow these steps to integrate the project into OSS-Fuzz:\n1. **Assess the project**: The agent should first assess whether the project is suitable for fuzzing. This includes checking if the project is open source, has a significant user base, and contains code that can be fuzzed (e.g., C/C++ code).\n2. **Set up the environment**: The agent should set up the necessary environment for fuzzing the project. This includes:\n- A Dockerfile that defines the build environment for the project, using the OSS-Fuzz base images.\n- A build script that compiles the project with the necessary instrumentation for fuzzing.\n- A project.yaml that provides the necessary OSS-Fuzz meta data.\n3. **Write fuzz targets**: The agent should write fuzz targets for the project. Fuzz targets are small programs that call into the project's code and are used by the fuzzing engine to generate inputs and find bugs.\n4. **Test the integration**: The agent should test the integration by running the fuzz targets locally and ensuring that they work correctly. This project should be continue until the fuzz targets build and run well, and the OSS-Fuzz `check_build` script passes without errors.\n5. **Conclude the integration**: Once the integration is complete, the agent should conclude with a message of the results achieved and the next steps the security engineer guiding the agent should take. The agent should *not* make any commits or push anything to GitHub, but should conclude on the work for the security engineer to review. The agent should never submit any changes to OSS-Fuzz's Github.\n\nWhen doing this type of work it's crucial the agent uses any skills it has related to code analysis and fuzzing harness writing.\n\n### Extending and improving fuzzing posture\n\nThe agent can also be used to extend and improve the fuzzing posture of existing OSS-Fuzz projects. This can include:\n- Adding new fuzz targets to cover more code paths and functionality.\n- Improving existing fuzz targets to make them more effective at finding bugs.\n- Updating the build environment to include new dependencies or tools that can enhance fuzzing.\n- Analyzing fuzzing results and identifying areas of the code that are not well covered by existing fuzz targets, and then writing new fuzz targets to cover those areas.\n\nA useful approach for extending a project is to study the latest code coverage report for the project, which is publicly available, to identify areas of the code that are not well covered by existing fuzz targets. The agent can then write new fuzz targets to cover those areas, and test them locally before concluding on the work for the security engineer to review.\n\n**Critical: avoid targeting already-covered code.** The most common mistake when extending an OSS-Fuzz project is writing harnesses that target functions already well-exercised by the existing production fuzzer corpus. Before selecting any target function:\n\n1. Fetch the latest public `summary.json` via the `latest_report_info/<project>.json` pointer (never guess the date). See the [code coverage reference](references/code_coverage.md) for the pointer, the JSON schema, and how to read it.\n2. Parse the per-file metrics. Line % is triage only — use the **functions** metric (which functions are never entered ⇒ a new harness may be needed) and the **regions/branches** metric (reached function, dark branches ⇒ a corpus/seed problem) to decide *what kind* of gap each file has. Relying on line % alone throws away the signals that tell harness-work from seed-work apart.\n3. Build an explicit blocklist of already-covered files (≥ 50% lines with most functions covered) — do NOT write harnesses whose primary target lives in one of these files.\n4. Only select targets from files with genuinely low coverage (< 30% lines hit), and classify the gap with the functions-vs-branches split before acting.\n\nReading the source code and identifying \"important-looking\" functions is not sufficient — important functions are frequently already covered. Coverage data is the authoritative source of truth for what needs work, and Fuzz Introspector (<https://introspector.oss-fuzz.com>) additionally surfaces reachable-but-unfuzzed functions — see the code coverage reference for the full workflow.\n\n**Structured seed generation.** Adding a new harness is not the only way to extend coverage — often the existing harnesses already reach dark code, but the corpus never produces inputs valid enough to enter it. When a target parses a structured format (binary containers, codec/network bitstreams, text grammars), a script that constructs structurally-valid inputs from scratch is frequently the highest-leverage, lowest-review-cost improvement: random bytes rarely pass a parser's early magic/length/checksum checks, so the deep logic stays dark until seeded. Drive this the same coverage-first way: pick reachable files that are dark in `summary.json`, generate seeds that target them, validate each one actually parses, append them to the existing corpora (never replace), and confirm the union does not digress. See the [structured seed generation reference](references/structured_seed_generation.md) for the full workflow, construction techniques, per-fuzzer tailoring, and pitfalls, and `projects/vlc/generate_seeds.py` for a worked example.\n\nUse the local code coverage feature of the `python3 infra/helper.py` tool to generate code coverage reports for fuzz targets locally, for example to validate the code coverage achieved by a new fuzz target. This can be done by running `python3 infra/helper.py introspector --coverage-only PROJECT_NAME` and then studying the generated report in e.g. build/out/PROJECT_NAME/report. Some examples of this include:\n\n```\n# Generate a coverage report for htslib OSS-Fuzz project from running each\n# fuzzer for 30 seconds, and store coverage directory in `htslib-cov-1`.\npython3 infra/helper.py introspector --coverage-only --seconds 30 --out htslib-cov-1 htslib\n\n# Generate a coverage report for leveldb OSS-Fuzz project from running each\n# fuzzer for 45 seconds, and store coverage directory in `leveldb-cov-1`.\npython3 infra/helper.py introspector --coverage-only --seconds 45 --out leveldb-cov-1 leveldb\n```\n\nThe user may provide directions on how to extend the fuzzing, and it's crucial to follow instructions on this matter. For example, the user may ask to focus on a specific area of the code, or to target specific types of vulnerabilities. The agent should always provide a clear explanation of the rationale for each extension or improvement made to the fuzzing posture of the project.\n\nWhen extending an OSS-Fuzz project it's crucial to have a good understanding of the target code. To this end, it's often useful to get a local version of the target source code into the OSS-Fuzz project structure to make working with the target project easy. This involves e.g. studying the `Dockerfile` of the target project, finding the e.g. `git clone` of the target project, and then cloning this repository locally and using e.g. `COPY` instead of `RUN git clone` in the Dockerfile to get the source code into the container.\n\nThe agent should always provide clear technical justification for each extension.\n\nWhen doing this type of work it's crucial the agent uses any skills it has related to code analysis and fuzzing harness writing. It's important each extension is done through a personal assessment of the current fuzzing posture of the project, and a clear explanation of the rationale for each extension or improvement. The agent should never make any commits or push anything to GitHub, but should conclude on the work for the security engineer to review. The agent should never submit any changes to OSS-Fuzz's Github.\n\nIt is crucial when extending existing OSS-Fuzz project you must validate the existing code coverage does not digress. You should empirically evaluate this and give a justification that no digression has happened, or if it has happened then you should give a justification for why the digression is acceptable in light of the achieved extension.\n\nUnless otherwise specified, the agent should focus on improving a single fuzzing harness for the target project, and not focus on making broad changes that will take a long time to review. Simple changes are often more effective than broad large changes.\n\n### Fixing broken existing OSS-Fuzz projects\n\nThe agent can also be used to fix broken existing OSS-Fuzz projects. This can include:\n- Identifying and fixing build issues that prevent fuzz targets from running correctly.\n- Updating dependencies or build scripts to ensure that the project can be fuzzed effectively.\n- Analyzing fuzzing results to identify and fix issues that are causing the fuzzing campaign to fail or produce unreliable results.\n\nA given OSS-Fuzz project must succeed with:\n\n```\npython3 infra/helper.py build_fuzzers PROJECT_NAME\npython3 infra/helper.py check_build PROJECT_NAME\n```\n\nThe agent should never make any commits or push anything to GitHub, but should conclude on the work for the security engineer to review. The agent should never submit any changes to OSS-Fuzz's Github.\n\n\n### Chronos integration\n\nA common task for an OSS-Fuzz engineer is to add Chronos support for a given OSS-Fuzz project.\n\nChronos is a feature of OSS-Fuzz that makes it possible to quickly rebuild OSS-Fuzz projects and run unit tests of a given OSS-Fuzz project. This is used to efficiently validate e.g. patches of a project without having to rebuild the entire target project image.\n\nTo add Chronos support a project needs to have two key scripts:\n\n- replay_build.sh: used to quickly rebuild the project without network access.\n- run_tests.sh: used to run unit tests of the project without network access.\n\nThere are several constraints on these scripts, e.g. no network access, and it's important to always check the infra/chronos/README.md file to understand the specifics.\n\nA given Chronos integration must succeed with:\n\n```sh\npython3 infra/experimental/chronos/manager.py check-replay PROJECT_NAME\npython3 infra/experimental/chronos/manager.py check-tests PROJECT_NAME\n```\n\nThe above two commands must succeed without error, and when integrating a new project these commands must be run before concluding on the work for the security engineer to review.\n\nIn addition to the above, there are some constraints on Chronos worth mentioning:\n- If the tests fail when `run_tests.sh` is run, then `check-tests` *must* fail as well. This is a crucial invariant that is used to validate if wrong patches lead to wrong outcomes, and we must be able to check wrong patches that break tests.\n- The `run_tests.sh` script should leave a given repository in the state it was before the script was run. For example, `git diff` should be the same before and after `run_tests.sh` is run inside the target repository.\n- `run_tests.sh` has no network connection, so if any tests requires network connection then these tests should be skipped in `run_tests.sh` and this should be clearly documented in the script.\n\n\n# Guidelines for working locally on OSS-Fuzz projects\n\n1. Always work from the base folder of the current OSS-Fuzz project unless otherwise specified.\n2. Make a local checkout of the target source code to make working with the target project easy. This involves e.g. studying the `Dockerfile` of the target project, finding the e.g. `git clone` of the target project, and then cloning this repository locally and using e.g. `COPY` instead of `RUN git clone` in the Dockerfile to get the source code into the container.\n3. Use the `python3 infra/helper.py` tool to build and test fuzz targets locally.\n4. Analyse if build scripts can be optimized to improve local building efficiency.\n\n\n# Public data available for OSS-Fuzz projects\n\nThe OSS-Fuzz infrastructure provides a lot of public data that can be used to guide the work of an OSS-Fuzz engineer. This includes:\n\n- Current build status of all OSS-Fuzz projects:\n  - html page: https://oss-fuzz-build-logs.storage.googleapis.com/index.html\n  - json file: https://oss-fuzz-build-logs.storage.googleapis.com/status.json\n  - use this reference to identify latest build status of a given project, and to identify if there are any build issues that need to be fixed.\n  - If you are tasked with fixing the build of a project, then use this data to identify the latest build error.\n  - If you are tasked with fixing the build of a project, then use this data to identify the conditions of the latest build error, e.g. which architecture, fuzzing engine and sanitizer is failing.\n  - Some build errors are due to the harnesses running into an issue immediately, meaning they build but `check_build` fails. These are bugs that likely indicate the fuzzing harnesses have a deficiency.\n- in the references section guidance is provided on code coverage reports, helper script used for interacting with OSS-Fuzz projects and documentation on the structure of OSS-Fuzz projects.\n- https://introspector.oss-fuzz.com : details insights on macro and micro level stats on OSS-Fuzz.\n\n<!-- File: tools/vscode-extension/.eslintrc.json (Tokens: ~12 | Category: anthropic-skill) -->\n{\n  \"extends\": \"./node_modules/gts/\"\n}\n\n<!-- File: tools/vscode-extension/.vscode/extensions.json (Tokens: ~300 | Category: anthropic-skill) -->\n# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/extensions.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/extensions.json)\n\n<!-- File: tools/vscode-extension/.vscode/launch.json (Tokens: ~300 | Category: anthropic-skill) -->\n# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/launch.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/launch.json)\n\n<!-- File: tools/vscode-extension/.vscode/settings.json (Tokens: ~300 | Category: anthropic-skill) -->\n# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/settings.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/settings.json)\n\n<!-- File: tools/vscode-extension/.vscode/tasks.json (Tokens: ~300 | Category: anthropic-skill) -->\n# .vscode Skill\n\nPath: `tools/vscode-extension/.vscode/tasks.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/google/oss-fuzz/HEAD/tools/vscode-extension/.vscode/tasks.json)\n\n<!-- File: tools/vscode-extension/package-lock.json (Tokens: ~19843 | Category: anthropic-skill) -->\n{\n  \"name\": \"OSS-Fuzz\",\n  \"version\": \"0.0.5\",\n  \"lockfileVersion\": 2,\n  \"requires\": true,\n  \"packages\": {\n    \"\": {\n      \"name\": \"OSS-Fuzz\",\n      \"version\": \"0.0.5\",\n      \"dependencies\": {\n        \"@microsoft/vscode-file-downloader-api\": \"^1.0.1\"\n      },\n      \"devDependencies\": {\n        \"@types/glob\": \"^8.1.0\",\n        \"@types/mocha\": \"^10.0.1\",\n        \"@types/node\": \"^14.11.2\",\n        \"@types/vscode\": \"^1.76.0\",\n        \"@typescript-eslint/eslint-plugin\": \"^5.53.0\",\n        \"@typescript-eslint/parser\": \"^5.53.0\",\n        \"@vscode/test-electron\": \"^2.2.3\",\n        \"eslint\": \"^8.34.0\",\n        \"glob\": \"^8.1.0\",\n        \"gts\": \"^3.1.1\",\n        \"mocha\": \"^10.8.2\",\n        \"typescript\": \"~4.7.0\"\n      },\n      \"engines\": {\n        \"vscode\": \"^1.76.0\"\n      }\n    },\n    \"node_modules/@babel/code-frame\": {\n      \"version\": \"7.22.5\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz\",\n      \"integrity\": \"sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@babel/highlight\": \"^7.22.5\"\n      },\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@babel/helper-validator-identifier\": {\n      \"version\": \"7.22.5\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz\",\n      \"integrity\": \"sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@babel/highlight\": {\n      \"version\": \"7.22.5\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz\",\n      \"integrity\": \"sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@babel/helper-validator-identifier\": \"^7.22.5\",\n        \"chalk\": \"^2.0.0\",\n        \"js-tokens\": \"^4.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/ansi-styles\": {\n      \"version\": \"3.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz\",\n      \"integrity\": \"sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-convert\": \"^1.9.0\"\n      },\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/chalk\": {\n      \"version\": \"2.4.2\",\n      \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz\",\n      \"integrity\": \"sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ansi-styles\": \"^3.2.1\",\n        \"escape-string-regexp\": \"^1.0.5\",\n        \"supports-color\": \"^5.3.0\"\n      },\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/color-convert\": {\n      \"version\": \"1.9.3\",\n      \"resolved\": \"https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz\",\n      \"integrity\": \"sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-name\": \"1.1.3\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/color-name\": {\n      \"version\": \"1.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz\",\n      \"integrity\": \"sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==\",\n      \"dev\": true\n    },\n    \"node_modules/@babel/highlight/node_modules/escape-string-regexp\": {\n      \"version\": \"1.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz\",\n      \"integrity\": \"sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.8.0\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/has-flag\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz\",\n      \"integrity\": \"sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@babel/highlight/node_modules/supports-color\": {\n      \"version\": \"5.5.0\",\n      \"resolved\": \"https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz\",\n      \"integrity\": \"sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"has-flag\": \"^3.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/@eslint/eslintrc\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz\",\n      \"integrity\": \"sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ajv\": \"^6.12.4\",\n        \"debug\": \"^4.3.2\",\n        \"espree\": \"^9.4.0\",\n        \"globals\": \"^13.19.0\",\n        \"ignore\": \"^5.2.0\",\n        \"import-fresh\": \"^3.2.1\",\n        \"js-yaml\": \"^4.1.0\",\n        \"minimatch\": \"^3.1.2\",\n        \"strip-json-comments\": \"^3.1.1\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://opencollective.com/eslint\"\n      }\n    },\n    \"node_modules/@eslint/js\": {\n      \"version\": \"8.35.0\",\n      \"resolved\": \"https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz\",\n      \"integrity\": \"sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      }\n    },\n    \"node_modules/@humanwhocodes/config-array\": {\n      \"version\": \"0.11.8\",\n      \"resolved\": \"https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz\",\n      \"integrity\": \"sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@humanwhocodes/object-schema\": \"^1.2.1\",\n        \"debug\": \"^4.1.1\",\n        \"minimatch\": \"^3.0.5\"\n      },\n      \"engines\": {\n        \"node\": \">=10.10.0\"\n      }\n    },\n    \"node_modules/@humanwhocodes/module-importer\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz\",\n      \"integrity\": \"sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=12.22\"\n      },\n      \"funding\": {\n        \"type\": \"github\",\n        \"url\": \"https://github.com/sponsors/nzakas\"\n      }\n    },\n    \"node_modules/@humanwhocodes/object-schema\": {\n      \"version\": \"1.2.1\",\n      \"resolved\": \"https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz\",\n      \"integrity\": \"sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==\",\n      \"dev\": true\n    },\n    \"node_modules/@microsoft/vscode-file-downloader-api\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/@microsoft/vscode-file-downloader-api/-/vscode-file-downloader-api-1.0.1.tgz\",\n      \"integrity\": \"sha512-cO9n/IpTMbXizz5YcEkiuRyX5r66SBY/3LnrlroyXbQXrgDdaKecfV3n4viTcvp9O//QF2AxcBfDZex2d4VSTg==\"\n    },\n    \"node_modules/@nodelib/fs.scandir\": {\n      \"version\": \"2.1.5\",\n      \"resolved\": \"https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz\",\n      \"integrity\": \"sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@nodelib/fs.stat\": \"2.0.5\",\n        \"run-parallel\": \"^1.1.9\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/@nodelib/fs.stat\": {\n      \"version\": \"2.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz\",\n      \"integrity\": \"sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/@nodelib/fs.walk\": {\n      \"version\": \"1.2.8\",\n      \"resolved\": \"https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz\",\n      \"integrity\": \"sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@nodelib/fs.scandir\": \"2.1.5\",\n        \"fastq\": \"^1.6.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/@tootallnate/once\": {\n      \"version\": \"1.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz\",\n      \"integrity\": \"sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">= 6\"\n      }\n    },\n    \"node_modules/@types/glob\": {\n      \"version\": \"8.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz\",\n      \"integrity\": \"sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@types/minimatch\": \"^5.1.2\",\n        \"@types/node\": \"*\"\n      }\n    },\n    \"node_modules/@types/json-schema\": {\n      \"version\": \"7.0.11\",\n      \"resolved\": \"https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz\",\n      \"integrity\": \"sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/minimatch\": {\n      \"version\": \"5.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz\",\n      \"integrity\": \"sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/minimist\": {\n      \"version\": \"1.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz\",\n      \"integrity\": \"sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/mocha\": {\n      \"version\": \"10.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz\",\n      \"integrity\": \"sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/node\": {\n      \"version\": \"14.18.54\",\n      \"resolved\": \"https://registry.npmjs.org/@types/node/-/node-14.18.54.tgz\",\n      \"integrity\": \"sha512-uq7O52wvo2Lggsx1x21tKZgqkJpvwCseBBPtX/nKQfpVlEsLOb11zZ1CRsWUKvJF0+lzuA9jwvA7Pr2Wt7i3xw==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/normalize-package-data\": {\n      \"version\": \"2.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz\",\n      \"integrity\": \"sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/semver\": {\n      \"version\": \"7.3.13\",\n      \"resolved\": \"https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz\",\n      \"integrity\": \"sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==\",\n      \"dev\": true\n    },\n    \"node_modules/@types/vscode\": {\n      \"version\": \"1.76.0\",\n      \"resolved\": \"https://registry.npmjs.org/@types/vscode/-/vscode-1.76.0.tgz\",\n      \"integrity\": \"sha512-CQcY3+Fe5hNewHnOEAVYj4dd1do/QHliXaknAEYSXx2KEHUzFibDZSKptCon+HPgK55xx20pR+PBJjf0MomnBA==\",\n      \"dev\": true\n    },\n    \"node_modules/@typescript-eslint/eslint-plugin\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.1.tgz\",\n      \"integrity\": \"sha512-a2RQAkosH3d3ZIV08s3DcL/mcGc2M/UC528VkPULFxR9VnVPT8pBu0IyBAJJmVsCmhVfwQX1v6q+QGnmSe1bew==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/scope-manager\": \"5.54.1\",\n        \"@typescript-eslint/type-utils\": \"5.54.1\",\n        \"@typescript-eslint/utils\": \"5.54.1\",\n        \"debug\": \"^4.3.4\",\n        \"grapheme-splitter\": \"^1.0.4\",\n        \"ignore\": \"^5.2.0\",\n        \"natural-compare-lite\": \"^1.4.0\",\n        \"regexpp\": \"^3.2.0\",\n        \"semver\": \"^7.3.7\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"@typescript-eslint/parser\": \"^5.0.0\",\n        \"eslint\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz\",\n      \"integrity\": \"sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@types/json-schema\": \"^7.0.7\",\n        \"@typescript-eslint/scope-manager\": \"4.33.0\",\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"@typescript-eslint/typescript-estree\": \"4.33.0\",\n        \"eslint-scope\": \"^5.1.1\",\n        \"eslint-utils\": \"^3.0.0\"\n      },\n      \"engines\": {\n        \"node\": \"^10.12.0 || >=12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"*\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz\",\n      \"integrity\": \"sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"@typescript-eslint/visitor-keys\": \"4.33.0\"\n      },\n      \"engines\": {\n        \"node\": \"^8.10.0 || ^10.13.0 || >=11.10.1\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz\",\n      \"integrity\": \"sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \"^8.10.0 || ^10.13.0 || >=11.10.1\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz\",\n      \"integrity\": \"sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"@typescript-eslint/visitor-keys\": \"4.33.0\",\n        \"debug\": \"^4.3.1\",\n        \"globby\": \"^11.0.3\",\n        \"is-glob\": \"^4.0.1\",\n        \"semver\": \"^7.3.5\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^10.12.0 || >=12.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys\": {\n      \"version\": \"4.33.0\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz\",\n      \"integrity\": \"sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"4.33.0\",\n        \"eslint-visitor-keys\": \"^2.0.0\"\n      },\n      \"engines\": {\n        \"node\": \"^8.10.0 || ^10.13.0 || >=11.10.1\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-visitor-keys\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz\",\n      \"integrity\": \"sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/@typescript-eslint/parser\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.54.1.tgz\",\n      \"integrity\": \"sha512-8zaIXJp/nG9Ff9vQNh7TI+C3nA6q6iIsGJ4B4L6MhZ7mHnTMR4YP5vp2xydmFXIy8rpyIVbNAG44871LMt6ujg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/scope-manager\": \"5.54.1\",\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/typescript-estree\": \"5.54.1\",\n        \"debug\": \"^4.3.4\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/scope-manager\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.1.tgz\",\n      \"integrity\": \"sha512-zWKuGliXxvuxyM71UA/EcPxaviw39dB2504LqAmFDjmkpO8qNLHcmzlh6pbHs1h/7YQ9bnsO8CCcYCSA8sykUg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/visitor-keys\": \"5.54.1\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/type-utils\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.1.tgz\",\n      \"integrity\": \"sha512-WREHsTz0GqVYLIbzIZYbmUUr95DKEKIXZNH57W3s+4bVnuF1TKe2jH8ZNH8rO1CeMY3U4j4UQeqPNkHMiGem3g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/typescript-estree\": \"5.54.1\",\n        \"@typescript-eslint/utils\": \"5.54.1\",\n        \"debug\": \"^4.3.4\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"*\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/types\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.1.tgz\",\n      \"integrity\": \"sha512-G9+1vVazrfAfbtmCapJX8jRo2E4MDXxgm/IMOF4oGh3kq7XuK3JRkOg6y2Qu1VsTRmWETyTkWt1wxy7X7/yLkw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@typescript-eslint/typescript-estree\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.1.tgz\",\n      \"integrity\": \"sha512-bjK5t+S6ffHnVwA0qRPTZrxKSaFYocwFIkZx5k7pvWfsB1I57pO/0M0Skatzzw1sCkjJ83AfGTL0oFIFiDX3bg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/visitor-keys\": \"5.54.1\",\n        \"debug\": \"^4.3.4\",\n        \"globby\": \"^11.1.0\",\n        \"is-glob\": \"^4.0.3\",\n        \"semver\": \"^7.3.7\",\n        \"tsutils\": \"^3.21.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependenciesMeta\": {\n        \"typescript\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/@typescript-eslint/utils\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.1.tgz\",\n      \"integrity\": \"sha512-IY5dyQM8XD1zfDe5X8jegX6r2EVU5o/WJnLu/znLPWCBF7KNGC+adacXnt5jEYS9JixDcoccI6CvE4RCjHMzCQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@types/json-schema\": \"^7.0.9\",\n        \"@types/semver\": \"^7.3.12\",\n        \"@typescript-eslint/scope-manager\": \"5.54.1\",\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"@typescript-eslint/typescript-estree\": \"5.54.1\",\n        \"eslint-scope\": \"^5.1.1\",\n        \"eslint-utils\": \"^3.0.0\",\n        \"semver\": \"^7.3.7\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      }\n    },\n    \"node_modules/@typescript-eslint/visitor-keys\": {\n      \"version\": \"5.54.1\",\n      \"resolved\": \"https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.1.tgz\",\n      \"integrity\": \"sha512-q8iSoHTgwCfgcRJ2l2x+xCbu8nBlRAlsQ33k24Adj8eoVBE0f8dUeI+bAa8F84Mv05UGbAx57g2zrRsYIooqQg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@typescript-eslint/types\": \"5.54.1\",\n        \"eslint-visitor-keys\": \"^3.3.0\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"type\": \"opencollective\",\n        \"url\": \"https://opencollective.com/typescript-eslint\"\n      }\n    },\n    \"node_modules/@vscode/test-electron\": {\n      \"version\": \"2.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.0.tgz\",\n      \"integrity\": \"sha512-fwzA9RtazH1GT/sckYlbxu6t5e4VaMXwCVtyLv4UAG0hP6NTfnMaaG25XCfWqlVwFhBMcQXHBCy5dmz2eLUnkw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"http-proxy-agent\": \"^4.0.1\",\n        \"https-proxy-agent\": \"^5.0.0\",\n        \"jszip\": \"^3.10.1\",\n        \"semver\": \"^7.3.8\"\n      },\n      \"engines\": {\n        \"node\": \">=16\"\n      }\n    },\n    \"node_modules/acorn\": {\n      \"version\": \"8.8.2\",\n      \"resolved\": \"https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz\",\n      \"integrity\": \"sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==\",\n      \"dev\": true,\n      \"bin\": {\n        \"acorn\": \"bin/acorn\"\n      },\n      \"engines\": {\n        \"node\": \">=0.4.0\"\n      }\n    },\n    \"node_modules/acorn-jsx\": {\n      \"version\": \"5.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz\",\n      \"integrity\": \"sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==\",\n      \"dev\": true,\n      \"peerDependencies\": {\n        \"acorn\": \"^6.0.0 || ^7.0.0 || ^8.0.0\"\n      }\n    },\n    \"node_modules/agent-base\": {\n      \"version\": \"6.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz\",\n      \"integrity\": \"sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"debug\": \"4\"\n      },\n      \"engines\": {\n        \"node\": \">= 6.0.0\"\n      }\n    },\n    \"node_modules/ajv\": {\n      \"version\": \"6.12.6\",\n      \"resolved\": \"https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz\",\n      \"integrity\": \"sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"fast-deep-equal\": \"^3.1.1\",\n        \"fast-json-stable-stringify\": \"^2.0.0\",\n        \"json-schema-traverse\": \"^0.4.1\",\n        \"uri-js\": \"^4.2.2\"\n      },\n      \"funding\": {\n        \"type\": \"github\",\n        \"url\": \"https://github.com/sponsors/epoberezkin\"\n      }\n    },\n    \"node_modules/ansi-colors\": {\n      \"version\": \"4.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz\",\n      \"integrity\": \"sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/ansi-escapes\": {\n      \"version\": \"4.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz\",\n      \"integrity\": \"sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"type-fest\": \"^0.21.3\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/ansi-escapes/node_modules/type-fest\": {\n      \"version\": \"0.21.3\",\n      \"resolved\": \"https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz\",\n      \"integrity\": \"sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/ansi-regex\": {\n      \"version\": \"5.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz\",\n      \"integrity\": \"sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/ansi-styles\": {\n      \"version\": \"4.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz\",\n      \"integrity\": \"sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-convert\": \"^2.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/chalk/ansi-styles?sponsor=1\"\n      }\n    },\n    \"node_modules/anymatch\": {\n      \"version\": \"3.1.3\",\n      \"resolved\": \"https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz\",\n      \"integrity\": \"sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"normalize-path\": \"^3.0.0\",\n        \"picomatch\": \"^2.0.4\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/argparse\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz\",\n      \"integrity\": \"sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==\",\n      \"dev\": true\n    },\n    \"node_modules/array-union\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz\",\n      \"integrity\": \"sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/arrify\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz\",\n      \"integrity\": \"sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/astral-regex\": {\n      \"version\": \"2.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz\",\n      \"integrity\": \"sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/balanced-match\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz\",\n      \"integrity\": \"sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==\",\n      \"dev\": true\n    },\n    \"node_modules/binary-extensions\": {\n      \"version\": \"2.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz\",\n      \"integrity\": \"sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/brace-expansion\": {\n      \"version\": \"1.1.11\",\n      \"resolved\": \"https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz\",\n      \"integrity\": \"sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"balanced-match\": \"^1.0.0\",\n        \"concat-map\": \"0.0.1\"\n      }\n    },\n    \"node_modules/braces\": {\n      \"version\": \"3.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/braces/-/braces-3.0.3.tgz\",\n      \"integrity\": \"sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"fill-range\": \"^7.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/browser-stdout\": {\n      \"version\": \"1.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz\",\n      \"integrity\": \"sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==\",\n      \"dev\": true\n    },\n    \"node_modules/callsites\": {\n      \"version\": \"3.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz\",\n      \"integrity\": \"sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/camelcase\": {\n      \"version\": \"6.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz\",\n      \"integrity\": \"sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/camelcase-keys\": {\n      \"version\": \"6.2.2\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz\",\n      \"integrity\": \"sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"camelcase\": \"^5.3.1\",\n        \"map-obj\": \"^4.0.0\",\n        \"quick-lru\": \"^4.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/camelcase-keys/node_modules/camelcase\": {\n      \"version\": \"5.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz\",\n      \"integrity\": \"sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/chalk\": {\n      \"version\": \"4.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz\",\n      \"integrity\": \"sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ansi-styles\": \"^4.1.0\",\n        \"supports-color\": \"^7.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/chalk/chalk?sponsor=1\"\n      }\n    },\n    \"node_modules/chardet\": {\n      \"version\": \"0.7.0\",\n      \"resolved\": \"https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz\",\n      \"integrity\": \"sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==\",\n      \"dev\": true\n    },\n    \"node_modules/chokidar\": {\n      \"version\": \"3.5.3\",\n      \"resolved\": \"https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz\",\n      \"integrity\": \"sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==\",\n      \"dev\": true,\n      \"funding\": [\n        {\n          \"type\": \"individual\",\n          \"url\": \"https://paulmillr.com/funding/\"\n        }\n      ],\n      \"dependencies\": {\n        \"anymatch\": \"~3.1.2\",\n        \"braces\": \"~3.0.2\",\n        \"glob-parent\": \"~5.1.2\",\n        \"is-binary-path\": \"~2.1.0\",\n        \"is-glob\": \"~4.0.1\",\n        \"normalize-path\": \"~3.0.0\",\n        \"readdirp\": \"~3.6.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 8.10.0\"\n      },\n      \"optionalDependencies\": {\n        \"fsevents\": \"~2.3.2\"\n      }\n    },\n    \"node_modules/chokidar/node_modules/glob-parent\": {\n      \"version\": \"5.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz\",\n      \"integrity\": \"sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"is-glob\": \"^4.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 6\"\n      }\n    },\n    \"node_modules/cli-cursor\": {\n      \"version\": \"3.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz\",\n      \"integrity\": \"sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"restore-cursor\": \"^3.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/cli-width\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz\",\n      \"integrity\": \"sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">= 10\"\n      }\n    },\n    \"node_modules/cliui\": {\n      \"version\": \"7.0.4\",\n      \"resolved\": \"https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz\",\n      \"integrity\": \"sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"string-width\": \"^4.2.0\",\n        \"strip-ansi\": \"^6.0.0\",\n        \"wrap-ansi\": \"^7.0.0\"\n      }\n    },\n    \"node_modules/color-convert\": {\n      \"version\": \"2.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz\",\n      \"integrity\": \"sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"color-name\": \"~1.1.4\"\n      },\n      \"engines\": {\n        \"node\": \">=7.0.0\"\n      }\n    },\n    \"node_modules/color-name\": {\n      \"version\": \"1.1.4\",\n      \"resolved\": \"https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz\",\n      \"integrity\": \"sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==\",\n      \"dev\": true\n    },\n    \"node_modules/concat-map\": {\n      \"version\": \"0.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz\",\n      \"integrity\": \"sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==\",\n      \"dev\": true\n    },\n    \"node_modules/core-util-is\": {\n      \"version\": \"1.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz\",\n      \"integrity\": \"sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==\",\n      \"dev\": true\n    },\n    \"node_modules/cross-spawn\": {\n      \"version\": \"7.0.3\",\n      \"resolved\": \"https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz\",\n      \"integrity\": \"sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"path-key\": \"^3.1.0\",\n        \"shebang-command\": \"^2.0.0\",\n        \"which\": \"^2.0.1\"\n      },\n      \"engines\": {\n        \"node\": \">= 8\"\n      }\n    },\n    \"node_modules/debug\": {\n      \"version\": \"4.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/debug/-/debug-4.4.0.tgz\",\n      \"integrity\": \"sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==\",\n      \"dev\": true,\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"ms\": \"^2.1.3\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"supports-color\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/decamelize\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz\",\n      \"integrity\": \"sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/decamelize-keys\": {\n      \"version\": \"1.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz\",\n      \"integrity\": \"sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"decamelize\": \"^1.1.0\",\n        \"map-obj\": \"^1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/decamelize-keys/node_modules/decamelize\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz\",\n      \"integrity\": \"sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/decamelize-keys/node_modules/map-obj\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz\",\n      \"integrity\": \"sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=0.10.0\"\n      }\n    },\n    \"node_modules/deep-is\": {\n      \"version\": \"0.1.4\",\n      \"resolved\": \"https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz\",\n      \"integrity\": \"sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==\",\n      \"dev\": true\n    },\n    \"node_modules/diff\": {\n      \"version\": \"5.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/diff/-/diff-5.2.0.tgz\",\n      \"integrity\": \"sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==\",\n      \"dev\": true,\n      \"license\": \"BSD-3-Clause\",\n      \"engines\": {\n        \"node\": \">=0.3.1\"\n      }\n    },\n    \"node_modules/dir-glob\": {\n      \"version\": \"3.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz\",\n      \"integrity\": \"sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"path-type\": \"^4.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8\"\n      }\n    },\n    \"node_modules/doctrine\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz\",\n      \"integrity\": \"sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"esutils\": \"^2.0.2\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0.0\"\n      }\n    },\n    \"node_modules/emoji-regex\": {\n      \"version\": \"8.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz\",\n      \"integrity\": \"sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==\",\n      \"dev\": true\n    },\n    \"node_modules/enquirer\": {\n      \"version\": \"2.3.6\",\n      \"resolved\": \"https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz\",\n      \"integrity\": \"sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"ansi-colors\": \"^4.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8.6\"\n      }\n    },\n    \"node_modules/error-ex\": {\n      \"version\": \"1.3.2\",\n      \"resolved\": \"https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz\",\n      \"integrity\": \"sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"is-arrayish\": \"^0.2.1\"\n      }\n    },\n    \"node_modules/escalade\": {\n      \"version\": \"3.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz\",\n      \"integrity\": \"sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=6\"\n      }\n    },\n    \"node_modules/escape-string-regexp\": {\n      \"version\": \"4.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz\",\n      \"integrity\": \"sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=10\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/sindresorhus\"\n      }\n    },\n    \"node_modules/eslint\": {\n      \"version\": \"8.35.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz\",\n      \"integrity\": \"sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"@eslint/eslintrc\": \"^2.0.0\",\n        \"@eslint/js\": \"8.35.0\",\n        \"@humanwhocodes/config-array\": \"^0.11.8\",\n        \"@humanwhocodes/module-importer\": \"^1.0.1\",\n        \"@nodelib/fs.walk\": \"^1.2.8\",\n        \"ajv\": \"^6.10.0\",\n        \"chalk\": \"^4.0.0\",\n        \"cross-spawn\": \"^7.0.2\",\n        \"debug\": \"^4.3.2\",\n        \"doctrine\": \"^3.0.0\",\n        \"escape-string-regexp\": \"^4.0.0\",\n        \"eslint-scope\": \"^7.1.1\",\n        \"eslint-utils\": \"^3.0.0\",\n        \"eslint-visitor-keys\": \"^3.3.0\",\n        \"espree\": \"^9.4.0\",\n        \"esquery\": \"^1.4.2\",\n        \"esutils\": \"^2.0.2\",\n        \"fast-deep-equal\": \"^3.1.3\",\n        \"file-entry-cache\": \"^6.0.1\",\n        \"find-up\": \"^5.0.0\",\n        \"glob-parent\": \"^6.0.2\",\n        \"globals\": \"^13.19.0\",\n        \"grapheme-splitter\": \"^1.0.4\",\n        \"ignore\": \"^5.2.0\",\n        \"import-fresh\": \"^3.0.0\",\n        \"imurmurhash\": \"^0.1.4\",\n        \"is-glob\": \"^4.0.0\",\n        \"is-path-inside\": \"^3.0.3\",\n        \"js-sdsl\": \"^4.1.4\",\n        \"js-yaml\": \"^4.1.0\",\n        \"json-stable-stringify-without-jsonify\": \"^1.0.1\",\n        \"levn\": \"^0.4.1\",\n        \"lodash.merge\": \"^4.6.2\",\n        \"minimatch\": \"^3.1.2\",\n        \"natural-compare\": \"^1.4.0\",\n        \"optionator\": \"^0.9.1\",\n        \"regexpp\": \"^3.2.0\",\n        \"strip-ansi\": \"^6.0.1\",\n        \"strip-json-comments\": \"^3.1.0\",\n        \"text-table\": \"^0.2.0\"\n      },\n      \"bin\": {\n        \"eslint\": \"bin/eslint.js\"\n      },\n      \"engines\": {\n        \"node\": \"^12.22.0 || ^14.17.0 || >=16.0.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://opencollective.com/eslint\"\n      }\n    },\n    \"node_modules/eslint-config-prettier\": {\n      \"version\": \"7.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz\",\n      \"integrity\": \"sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==\",\n      \"dev\": true,\n      \"bin\": {\n        \"eslint-config-prettier\": \"bin/cli.js\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=7.0.0\"\n      }\n    },\n    \"node_modules/eslint-plugin-es\": {\n      \"version\": \"3.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz\",\n      \"integrity\": \"sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-utils\": \"^2.0.0\",\n        \"regexpp\": \"^3.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8.10.0\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/mysticatea\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=4.19.1\"\n      }\n    },\n    \"node_modules/eslint-plugin-es/node_modules/eslint-utils\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz\",\n      \"integrity\": \"sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-visitor-keys\": \"^1.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/mysticatea\"\n      }\n    },\n    \"node_modules/eslint-plugin-es/node_modules/eslint-visitor-keys\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz\",\n      \"integrity\": \"sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/eslint-plugin-node\": {\n      \"version\": \"11.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz\",\n      \"integrity\": \"sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-plugin-es\": \"^3.0.0\",\n        \"eslint-utils\": \"^2.0.0\",\n        \"ignore\": \"^5.1.1\",\n        \"minimatch\": \"^3.0.4\",\n        \"resolve\": \"^1.10.1\",\n        \"semver\": \"^6.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=8.10.0\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=5.16.0\"\n      }\n    },\n    \"node_modules/eslint-plugin-node/node_modules/eslint-utils\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz\",\n      \"integrity\": \"sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-visitor-keys\": \"^1.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/mysticatea\"\n      }\n    },\n    \"node_modules/eslint-plugin-node/node_modules/eslint-visitor-keys\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz\",\n      \"integrity\": \"sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==\",\n      \"dev\": true,\n      \"engines\": {\n        \"node\": \">=4\"\n      }\n    },\n    \"node_modules/eslint-plugin-node/node_modules/semver\": {\n      \"version\": \"6.3.1\",\n      \"resolved\": \"https://registry.npmjs.org/semver/-/semver-6.3.1.tgz\",\n      \"integrity\": \"sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==\",\n      \"dev\": true,\n      \"bin\": {\n        \"semver\": \"bin/semver.js\"\n      }\n    },\n    \"node_modules/eslint-plugin-prettier\": {\n      \"version\": \"3.4.1\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz\",\n      \"integrity\": \"sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"prettier-linter-helpers\": \"^1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">=6.0.0\"\n      },\n      \"peerDependencies\": {\n        \"eslint\": \">=5.0.0\",\n        \"prettier\": \">=1.13.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"eslint-config-prettier\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/eslint-scope\": {\n      \"version\": \"5.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz\",\n      \"integrity\": \"sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"esrecurse\": \"^4.3.0\",\n        \"estraverse\": \"^4.1.1\"\n      },\n      \"engines\": {\n        \"node\": \">=8.0.0\"\n      }\n    },\n    \"node_modules/eslint-utils\": {\n      \"version\": \"3.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz\",\n      \"integrity\": \"sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==\",\n      \"dev\": true,\n      \"dependencies\": {\n        \"eslint-visitor-keys\": \"^2.0.0\"\n      },\n      \"engine\n\n<!-- File: tools/vscode-extension/package.json (Tokens: ~1820 | Category: anthropic-skill) -->\n{\n  \"name\": \"OSS-Fuzz\",\n  \"displayName\": \"OSS-Fuzz\",\n  \"description\": \"\",\n  \"version\": \"0.0.5\",\n  \"publisher\": \"OSS-FuzzMaintainers\",\n  \"icon\": \"images/thumbnail.png\",\n  \"engines\": {\n    \"vscode\": \"^1.76.0\"\n  },\n  \"repository\": \"https://github.com/google/oss-fuzz\",\n  \"categories\": [\n    \"Other\"\n  ],\n  \"extensionDependencies\": [\n    \"mindaro-dev.file-downloader\"\n  ],\n  \"activationEvents\": [],\n  \"main\": \"./build/src/extension.js\",\n  \"contributes\": {\n    \"configurations\": [\n      {\n        \"id\": \"OSS-Fuzz-Base\",\n        \"title\": \"Base path to OSS-Fuzz\",\n        \"properties\": {\n          \"oss-fuzz.OSS.Path\": {\n            \"type\": \"string\"\n          }\n        }\n      }\n    ],\n    \"viewsWelcome\": [\n      {\n        \"view\": \"workbench.explorer.emptyView\",\n        \"contents\": \"You can have paragraphs of text here. You can have [links](https://code.visualstudio.com) to external sources or [internal commands](command:welcome-view-content-sample.hello).\\nUse new lines to have new paragraphs.\\nPlace a link alone in a paragraph to make it a button\\n[Hello](command:welcome-view-content-sample.hello)\"\n      }\n    ],\n    \"commands\": [\n      {\n        \"command\": \"oss-fuzz.SetUp\",\n        \"title\": \"OSS-Fuzz: Set Up OSS-Fuzz\",\n        \"description\": \"Downloads the OSS-Fuzz repository and places it under /tmp/oss-fuzz. This will then be the OSS-Fuzz repository used by vscode.\"\n      },\n      {\n        \"command\": \"oss-fuzz.RunFuzzer\",\n        \"title\": \"OSS-Fuzz: Run Fuzzer\",\n        \"description\": \"Runs a single fuzzer from a given project. The fuzzer must already be build, meaning the project should be build first.\"\n      },\n      {\n        \"command\": \"oss-fuzz.ListFuzzers\",\n        \"title\": \"OSS-Fuzz: List Fuzzers\",\n        \"description\": \"Lists the fuzzers built for a given project. The project must be build first.\"\n      },\n      {\n        \"command\": \"oss-fuzz.GetCodeCoverage\",\n        \"title\": \"OSS-Fuzz: Display Code Coverage (Python only)\",\n        \"description\": \"Downloads the latest code coverage from OSS-Fuzz's cloud data (can find at https://introspector.oss-fuzz.com).\"\n      },\n      {\n        \"command\": \"oss-fuzz.ClearCodeCoverage\",\n        \"title\": \"OSS-Fuzz: Clear Code Coverage\",\n        \"description\": \"Clears code coverage visualization in the editor.\"\n      },\n      {\n        \"command\": \"oss-fuzz.CreateOSSFuzzSetup\",\n        \"title\": \"OSS-Fuzz: Initialize OSS-Fuzz Set Up\",\n        \"description\": \"Creates the relevant files using templates to set up an OSS-Fuzz project. Uses minor heuristics e.g. detection of language.\"\n      },\n      {\n        \"command\": \"oss-fuzz.WSBuildFuzzers\",\n        \"title\": \"OSS-Fuzz: Build Fuzzers In Workspace\",\n        \"description\": \"Builds the fuzzers from the project in the current VSCode workspace.\"\n      },\n      {\n        \"command\": \"oss-fuzz.SetupCIFuzz\",\n        \"title\": \"OSS-Fuzz: Set up CIFuzz\",\n        \"description\": \"Creates the files necessary for a CIFuzz set up.\"\n      },\n      {\n        \"command\": \"oss-fuzz.testFuzzer\",\n        \"title\": \"OSS-Fuzz: Test Specific Fuzzer\",\n        \"description\": \"Tests if a given fuzzer works by running it for 10 seconds.\"\n      },\n      {\n        \"command\": \"oss-fuzz.testCodeCoverage\",\n        \"title\": \"OSS-Fuzz: End-To-End Code Coverage Generation\",\n        \"description\": \"Builds the fuzzers in a ASAN mode for a project, collects corpus using the ASAN fuzzers and then generates an HTLM code coverage report using the generated corpus.\"\n      },\n      {\n        \"command\": \"oss-fuzz.Redo\",\n        \"title\": \"OSS-Fuzz: Redo Previous Command\",\n        \"description\": \"Performs the exact same command as the most recent one. Will provide the same input to the command as the previous one. This is efficient when e.g. continuously generating code coverage reports while working on improving a fuzzing set up.\"\n      },\n      {\n        \"command\": \"oss-fuzz.Template\",\n        \"title\": \"OSS-Fuzz: Fuzzer Creation Using Templates\",\n        \"description\": \"Creates a template fuzzer file using a catalogue of templates available.\"\n      },\n      {\n        \"command\": \"oss-fuzz.GenerateClusterfuzzLite\",\n        \"title\": \"OSS-Fuzz: [CFLite] Generate ClusterfuzzLite setup\",\n        \"description\": \"Creates the files needed for ClusterfuzzLite integration.\"\n      },\n      {\n        \"command\": \"oss-fuzz.WSBuildFuzzersCFLite\",\n        \"title\": \"OSS-Fuzz: [CFLite] Build Fuzzers In Workspace\",\n        \"description\": \"Builds the ClusterfuzzLite fuzzers from the project in the current VSCode workspace.\"\n      },\n      {\n        \"command\": \"oss-fuzz.testFuzzerCFLite\",\n        \"title\": \"OSS-Fuzz: [CFLite] Test running a specific fuzzer.\",\n        \"description\": \"Builds the CFLite setup and runs a fuzzer for a short period of time.\"\n      },\n      {\n        \"command\": \"oss-fuzz.setupFuzzIntrospector\",\n        \"title\": \"OSS-Fuzz: Set up Fuzz Introspector\",\n        \"description\": \"Install fuzz introspector on the system\"\n      },\n      {\n        \"command\": \"oss-fuzz.runFuzzIntrospector\",\n        \"title\": \"OSS-Fuzz: Run Full Fuzz Introspector\",\n        \"description\": \"Runs a full Fuzz Introspector\"\n      },\n      {\n        \"command\": \"oss-fuzz.GetOptimalTargets\",\n        \"title\": \"OSS-Fuzz: Get optimal targets\",\n        \"description\": \"Gets the optimal targets of this project\"\n      }\n    ],\n    \"walkthroughs\":[\n      {\n        \"id\": \"BuildAndRunExisting Project\",\n        \"title\": \"Set up OSS-Fuzz\",\n        \"description\": \"This walkthrough takes you through how to set up OSS-Fuzz in the VSCode extension and proceeding to build the fuzzers of an existing project as well as running a fuzzer from the project.\",\n        \"steps\": [\n          {\n            \"id\": \"s1\",\n            \"title\": \"Set up OSS-Fuzz\",\n            \"description\": \"This step sets up OSS-Fuzz in the folder /tmp/oss-fuzz\",\n            \"completionEvents\": [\"onCommand:oss-fuzz.SetUp\"],\n            \"media\": {\"altText\": \".\", \"image\": \"images/workflow-1-s-1\"}\n          }\n        ]\n      }\n    ]\n  },\n  \"scripts\": {\n    \"vscode:prepublish\": \"npm run compile\",\n    \"compile\": \"tsc\",\n    \"watch\": \"tsc -watch -p ./\",\n    \"pretest\": \"npm run compile\",\n    \"lint\": \"gts lint\",\n    \"clean\": \"gts clean\",\n    \"fix\": \"gts fix\",\n    \"prepare\": \"npm run compile\",\n    \"posttest\": \"npm run lint\"\n  },\n  \"devDependencies\": {\n    \"@types/glob\": \"^8.1.0\",\n    \"@types/mocha\": \"^10.0.1\",\n    \"@types/node\": \"^14.11.2\",\n    \"@types/vscode\": \"^1.76.0\",\n    \"@typescript-eslint/eslint-plugin\": \"^5.53.0\",\n    \"@typescript-eslint/parser\": \"^5.53.0\",\n    \"@vscode/test-electron\": \"^2.2.3\",\n    \"eslint\": \"^8.34.0\",\n    \"glob\": \"^8.1.0\",\n    \"mocha\": \"^10.8.2\",\n    \"typescript\": \"~4.7.0\",\n    \"gts\": \"^3.1.1\"\n  },\n  \"dependencies\": {\n    \"@microsoft/vscode-file-downloader-api\": \"^1.0.1\"\n  }\n}\n\n<!-- File: tools/vscode-extension/tsconfig.json (Tokens: ~58 | Category: anthropic-skill) -->\n{\n  \"extends\": \"./node_modules/gts/tsconfig-google.json\",\n  \"compilerOptions\": {\n    \"rootDir\": \".\",\n    \"outDir\": \"build\"\n  },\n  \"include\": [\n    \"src/**/*.ts\",\n    \"test/**/*.ts\"\n  ]\n}\n\n<!-- File: tools/vscode-extension/README.md (Tokens: ~210 | Category: plugin-manifest) -->\n# OSS-Fuzz VSCode extension\n\n[OSS-Fuzz](https://github.com/google/oss-fuzz) is a fuzzing toolkit and service for fuzzing open source projects. This VSCode extension provides features and capabilities for interacting with the OSS-Fuzz toolkit and also to compare local changes to the OSS-Fuzz cloud database by way of [Open source fuzz introspection](https://introspector.oss-fuzz.com).\n\n## Features\n\nThe VSCode extension is largely driven by commands at this point. The featues of these commands includes:\n\n- Easily setting up OSS-Fuzz\n- Templates for easily setting up a new OSS-Fuzz project\n- Building arbitrary projects from OSS-Fuzz\n- Modify a project from VSCode and test changes in OSS-Fuzz\n- Easily extract code coverage of fuzzers, including local-only fuzzers\n- Compare local code coverage to what is currently achieved by OSS-Fuzz\n- Auto-generation of fuzzer templates\n\nFor a full list of commands and their features, please check the commands page.\n</yakaai_skills>"}