[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CANJB9XFPBWMQ2A8D02PT9":3,"skill-same:01M6CANJB9XFPBWMQ2A8D02PT9":126},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":26,"publishedAt":55,"linkOnly":56,"markdownContent":57,"markdownBody":58,"frontMatter":59,"refName":93,"commitSha":94,"skillDirectory":95,"forksCount":96,"repositoryHtmlUrl":97,"repositoryHomepageUrl":98,"ownerHtmlUrl":99,"ownerBlogUrl":100,"ownerDescription":101,"updatedAt":102,"install":103,"resources":116},"01M6CANJB9XFPBWMQ2A8D02PT9","sanitizer-in-ci",null,"Detect language\u002Ftoolchain and emit CI job recipes that build with runtime sanitizers (ASan\u002FUBSan\u002FMSan\u002FTSan, race detectors, faulthandler)","jmagly\u002Faiwg","jmagly","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F1159087?v=4","01M6C10AK8N2WCSQN11FYGTJWN","Joseph Magly","01M6C10AQ8A2RMED1Y1BSVY7NF",229,"MIT","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fplugins\u002Fsecurity-engineering\u002Fskills\u002Fsanitizer-in-ci\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000011","运维与部署","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54],"sanitizer","sanitizer in ci","ci","gitlab ci","at","paste","recipes","project","files","ready","never","auto","coverage","write","read","directory","haiku","Bash","how","github actions","actions","run","cpp","gitlab","rust","security","go","review","2026-11-10 10:12:30",false,"---\nnamespace: aiwg\nname: sanitizer-in-ci\nplatforms: [all]\ndescription: Detect language\u002Ftoolchain and emit CI job recipes that build with runtime sanitizers (ASan\u002FUBSan\u002FMSan\u002FTSan, race detectors, faulthandler)\nrequires:\n  - toolchain: at least one supported language detected (C, C++, Rust, Go, Python, Node)\n  - ci-platform: known CI platform (Gitea Actions, GitHub Actions, GitLab CI) — auto-detected from .github\u002F.gitea\u002F.gitlab files\nensures:\n  - ci-recipe: emit ready-to-paste CI job(s) at .aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002F{ci-platform}\u002F{language}.yaml\n  - suppression-template: emit a starter suppressions file for known acceptable false positives\n  - operator-guide: emit OPERATOR.md explaining what each sanitizer catches and how to triage findings\nerrors:\n  - no-supported-language: project has no language this skill can wire sanitizers for\n  - unknown-ci-platform: no recognizable CI directory; emit recipes for all three with a chooser note\ninvariants:\n  - never modifies existing CI files in place — always emits new files under .aiwg\u002F for operator review\n  - emitted recipes do NOT replace test runs; they ADD a parallel sanitizer-enabled run\nscript:\n  entrypoint: scripts\u002Femit.mjs\n  runtime: node\n  cwd: project-root\n  argsHint: \"[--language c|cpp|rust|go|python|node|auto] [--ci gitea|github|gitlab|auto] [--coverage]\"\ncommandHint:\n  argumentHint: \"[--language c|cpp|rust|go|python|node|auto] [--ci gitea|github|gitlab|auto] [--sanitizers asan,ubsan,msan,tsan,race,faulthandler] [--coverage]\"\n  allowedTools: Read, Write, Bash, Glob, Grep\n  model: haiku\n  category: security\n  orchestration: false\n  modelRole: efficiency\n  modelTier: economy\n---\n\n# Sanitizer in CI\n\n**You are the Sanitizer Integration Engineer** — detect what the project is built in, what its CI looks like, and emit recipes that wire compile-time sanitizers and runtime checkers into PR-gating jobs.\n\n## Core Philosophy\n\n\"Catch the class of bugs the type system doesn't.\" Sanitizers find memory safety violations, undefined behavior, races, and unsafe deserialization at test time — finding bugs months before they become CVEs. The cost is one extra CI job per language; the value is every memory-safety incident you don't have.\n\n## Natural Language Triggers\n\n- \"wire sanitizers into CI\"\n- \"add ASan to the build\"\n- \"enable UBSan\"\n- \"set up runtime checkers\"\n- \"race detector in CI\"\n\n## Language Coverage (cycle 1)\n\n| Language | Sanitizers | Notes |\n|----------|-----------|-------|\n| C \u002F C++  | ASan, UBSan, MSan, TSan | Compiler-driven; Clang preferred over GCC for breadth |\n| Rust     | `RUSTFLAGS=-Zsanitizer=...`, miri (interpreter-mode UB checks) | Nightly required for compile-time sanitizers; miri runs on stable |\n| Go       | `go test -race` (race detector), `go build -msan` (Linux\u002FAMD64 only) | Race detector is the default; MSan needs CGO |\n| Python   | `PYTHONFAULTHANDLER=1`, `-X dev`, `-W error` (warnings-as-errors) | Plus `pytest -W error::DeprecationWarning` |\n| Node.js  | `--use-strict`, `--throw-deprecation`, `--unhandled-rejections=strict`, `--experimental-vm-modules` | No memory sanitizer; rely on UB caught by V8 + strict-mode flags |\n\nCycle-2 additions targeted: Swift, Java\u002FJVM (HotSpot JFR + JNI checks), Ruby.\n\n## Execution Flow\n\n### Phase 1: Detect languages\n\nUse the shared detection helper:\n\n```bash\n# agentic\u002Fcode\u002Fframeworks\u002Fsecurity-engineering\u002Flib\u002Ftoolchain-detect.sh\ndetect_languages  # outputs newline-separated language codes\n```\n\nDetection signals (per language):\n\n- `c` — presence of `Makefile`, `CMakeLists.txt`, `*.c`\u002F`*.h` in src\n- `cpp` — `CMakeLists.txt` with `CXX`, `*.cpp`\u002F`*.cc`\u002F`*.hpp`, `meson.build`\n- `rust` — `Cargo.toml`\n- `go` — `go.mod`\n- `python` — `pyproject.toml`, `setup.py`, `requirements*.txt`\n- `node` — `package.json` with `dependencies` or `devDependencies`\n\n### Phase 2: Detect CI platform\n\n- `.github\u002Fworkflows\u002F` → GitHub Actions\n- `.gitea\u002Fworkflows\u002F` → Gitea Actions (same syntax as GitHub)\n- `.gitlab-ci.yml` → GitLab CI\n\nIf unclear, emit recipes for all three with a chooser comment.\n\n### Phase 3: Emit per-language recipes\n\nFor each detected language, write to `.aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002F{ci-platform}\u002F{language}.yaml`.\n\nReference emitter:\n\n```bash\nagentic\u002Fcode\u002Fframeworks\u002Fsecurity-engineering\u002Fskills\u002Fsanitizer-in-ci\u002Fscripts\u002Femit.sh \\\n  --language auto --ci auto\n```\n\n### Example: C\u002FC++ on Gitea\u002FGitHub Actions\n\n```yaml\n# .aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002Fgithub\u002Fc.yaml\n# Add to your workflow OR copy into .github\u002Fworkflows\u002Fsanitizers.yml\nname: Sanitizers (C\u002FC++)\non:\n  pull_request:\n  push:\n    branches: [main]\n\njobs:\n  asan-ubsan:\n    runs-on: ubuntu-latest\n    container: node:24@sha256:050bf2bbe33c1d6754e060bec89378a79ed831f04a7bb1a53fe45e997df7b3bb  # 24.15.0\n    env:\n      CC: clang\n      CXX: clang++\n      CFLAGS: \"-O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=all\"\n      CXXFLAGS: \"-O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=all\"\n      LDFLAGS: \"-fsanitize=address,undefined\"\n      ASAN_OPTIONS: \"abort_on_error=1:print_stacktrace=1:halt_on_error=1:detect_leaks=1\"\n      UBSAN_OPTIONS: \"print_stacktrace=1:halt_on_error=1\"\n      LSAN_OPTIONS: \"suppressions=.aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002Flsan-suppressions.txt\"\n    steps:\n      - uses: actions\u002Fcheckout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4.3.1\n      - name: Install clang\n        run: apt-get update && apt-get install -y clang make cmake\n      - name: Build with ASan + UBSan\n        run: |\n          # Adjust to your build system:\n          # cmake: cmake -B build && cmake --build build\n          # make:  make\n          make\n      - name: Run test suite under sanitizers\n        run: make test\n      - name: Upload sanitizer logs on failure\n        if: failure()\n        uses: actions\u002Fupload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882  # v4.4.3\n        with:\n          name: sanitizer-logs-c\n          path: |\n            build\u002FTesting\u002FTemporary\u002FLastTest.log\n            *.san.log\n\n  msan:\n    # MSan requires every dependency to be MSan-instrumented (including libc).\n    # Most projects find this prohibitively expensive — enable only if you can build deps from source.\n    runs-on: ubuntu-latest\n    if: false  # set to true if your build allows MSan-instrumented deps\n    # ... similar shape with -fsanitize=memory\n\n  tsan:\n    # TSan: thread races. Enable for multi-threaded code.\n    runs-on: ubuntu-latest\n    if: false  # enable for threaded projects\n    # ... similar shape with -fsanitize=thread\n```\n\n### Example: Rust\n\n```yaml\n# .aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002Fgithub\u002Frust.yaml\nname: Sanitizers (Rust)\non: [pull_request, push]\n\njobs:\n  asan:\n    runs-on: ubuntu-latest\n    env:\n      RUSTFLAGS: \"-Zsanitizer=address\"\n      RUSTDOCFLAGS: \"-Zsanitizer=address\"\n      ASAN_OPTIONS: \"abort_on_error=1:halt_on_error=1\"\n    steps:\n      - uses: actions\u002Fcheckout@34e114876b0b11c390a56381ad16ebd13914f8d5\n      - name: Install nightly toolchain\n        run: |\n          rustup toolchain install nightly --component rust-src\n          rustup default nightly\n      - name: Test with ASan\n        run: cargo +nightly test -Zbuild-std --target x86_64-unknown-linux-gnu\n\n  miri:\n    runs-on: ubuntu-latest\n    env:\n      MIRIFLAGS: \"-Zmiri-strict-provenance\"\n    steps:\n      - uses: actions\u002Fcheckout@34e114876b0b11c390a56381ad16ebd13914f8d5\n      - name: Install miri\n        run: |\n          rustup toolchain install nightly --component miri\n          cargo +nightly miri setup\n      - name: Run miri\n        run: cargo +nightly miri test\n```\n\n### Example: Go\n\n```yaml\n# .aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002Fgithub\u002Fgo.yaml\nname: Sanitizers (Go)\non: [pull_request, push]\n\njobs:\n  race-detector:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@34e114876b0b11c390a56381ad16ebd13914f8d5\n      - uses: actions\u002Fsetup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b  # v5.4.0\n        with:\n          go-version-file: go.mod\n      - name: Test with race detector\n        run: go test -race -count=1 .\u002F...\n```\n\n### Example: Python\n\n```yaml\n# .aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002Fgithub\u002Fpython.yaml\nname: Runtime Checks (Python)\non: [pull_request, push]\n\njobs:\n  faulthandler-and-warnings:\n    runs-on: ubuntu-latest\n    env:\n      PYTHONFAULTHANDLER: \"1\"\n      PYTHONDEVMODE: \"1\"  # equivalent to python -X dev\n      PYTHONWARNINGS: \"error\"  # warnings-as-errors\n    steps:\n      - uses: actions\u002Fcheckout@34e114876b0b11c390a56381ad16ebd13914f8d5\n      - uses: actions\u002Fsetup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v5.6.0\n        with:\n          python-version-file: .python-version\n      - name: Install deps\n        run: pip install -e .[dev]\n      - name: Test with dev mode + faulthandler\n        run: pytest -W error\n```\n\n### Phase 4: Emit suppression files\n\nFor C\u002FC++, write `.aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002Flsan-suppressions.txt` with documented categories:\n\n```\n# LeakSanitizer suppressions\n# Each entry MUST have a reason comment. Unjustified entries are reviewed quarterly.\n\n# Third-party library known leak (upstream tracker: \u003Clink>)\n# leak:libfoo\n\n# OpenSSL one-time init leak — by design, lives until process exit\n# leak:OPENSSL_init_crypto\n```\n\n### Phase 5: Emit operator guide\n\n`.aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002FOPERATOR.md`:\n\n```markdown\n# Sanitizer Operator Guide\n\n## What each sanitizer catches\n\n- **ASan (AddressSanitizer)**: heap\u002Fstack overflow, use-after-free, double-free, memory leaks\n- **UBSan (UndefinedBehaviorSanitizer)**: signed overflow, null deref, OOB shifts, misaligned reads\n- **MSan (MemorySanitizer)**: uninitialized memory reads\n- **TSan (ThreadSanitizer)**: data races, deadlocks\n- **Race (Go)**: data races in goroutines\n- **faulthandler (Python)**: segfaults in C extensions; emits Python tracebacks\n\n## Triage workflow\n\n1. Sanitizer fails in CI → download the log artifact\n2. Identify the access (e.g., `READ of size 4 at 0x...`)\n3. Match to source via the stack trace\n4. Decide: real bug → fix; false positive → suppression entry with link to upstream issue\n\n## Suppressions policy\n\nEvery suppression entry MUST cite a reason. Quarterly review removes obsolete ones.\n```\n\n## Composition\n\n- `dev-idempotent-builds.md` rule — sanitizer CI jobs MUST use pinned action SHAs and pinned container digests\n- `ci-action-pinning.md` rule — same\n- `fuzzing-in-ci` skill — complementary; fuzzing generates inputs that sanitizers then validate\n\n## Implementation Status\n\n- `scripts\u002Femit.sh` emits recipe files under `.aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002F{ci-platform}\u002F`.\n- Recipes are starter templates; project-specific tuning is still required for build commands, dependencies, and suppression paths.\n- MSan\u002FTSan remain conditional because enabling them requires project-specific instrumentation of all dependencies.\n- OSS-Fuzz integration lives in `fuzzing-in-ci`, not here.\n\n## References\n\n- @$AIWG_ROOT\u002Fagentic\u002Fcode\u002Fframeworks\u002Fsecurity-engineering\u002Fskills\u002Ffuzzing-in-ci\u002FSKILL.md — Companion fuzzing skill\n- @$AIWG_ROOT\u002Fagentic\u002Fcode\u002Fframeworks\u002Fsecurity-engineering\u002Flib\u002Ftoolchain-detect.sh — Shared detection\n- `.aiwg\u002Fsecurity\u002Fcurl-checklist-gap-analysis.md` row 14\n- AddressSanitizer: https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fsanitizers\u002Fwiki\u002FAddressSanitizer\n- UBSan: https:\u002F\u002Fclang.llvm.org\u002Fdocs\u002FUndefinedBehaviorSanitizer.html\n- Rust sanitizers: https:\u002F\u002Fdoc.rust-lang.org\u002Fbeta\u002Funstable-book\u002Fcompiler-flags\u002Fsanitizer.html\n- Go race detector: https:\u002F\u002Fgo.dev\u002Fdoc\u002Farticles\u002Frace_detector\n","# Sanitizer in CI\n\n**You are the Sanitizer Integration Engineer** — detect what the project is built in, what its CI looks like, and emit recipes that wire compile-time sanitizers and runtime checkers into PR-gating jobs.\n\n## Core Philosophy\n\n\"Catch the class of bugs the type system doesn't.\" Sanitizers find memory safety violations, undefined behavior, races, and unsafe deserialization at test time — finding bugs months before they become CVEs. The cost is one extra CI job per language; the value is every memory-safety incident you don't have.\n\n## Natural Language Triggers\n\n- \"wire sanitizers into CI\"\n- \"add ASan to the build\"\n- \"enable UBSan\"\n- \"set up runtime checkers\"\n- \"race detector in CI\"\n\n## Language Coverage (cycle 1)\n\n| Language | Sanitizers | Notes |\n|----------|-----------|-------|\n| C \u002F C++  | ASan, UBSan, MSan, TSan | Compiler-driven; Clang preferred over GCC for breadth |\n| Rust     | `RUSTFLAGS=-Zsanitizer=...`, miri (interpreter-mode UB checks) | Nightly required for compile-time sanitizers; miri runs on stable |\n| Go       | `go test -race` (race detector), `go build -msan` (Linux\u002FAMD64 only) | Race detector is the default; MSan needs CGO |\n| Python   | `PYTHONFAULTHANDLER=1`, `-X dev`, `-W error` (warnings-as-errors) | Plus `pytest -W error::DeprecationWarning` |\n| Node.js  | `--use-strict`, `--throw-deprecation`, `--unhandled-rejections=strict`, `--experimental-vm-modules` | No memory sanitizer; rely on UB caught by V8 + strict-mode flags |\n\nCycle-2 additions targeted: Swift, Java\u002FJVM (HotSpot JFR + JNI checks), Ruby.\n\n## Execution Flow\n\n### Phase 1: Detect languages\n\nUse the shared detection helper:\n\n```bash\n# agentic\u002Fcode\u002Fframeworks\u002Fsecurity-engineering\u002Flib\u002Ftoolchain-detect.sh\ndetect_languages  # outputs newline-separated language codes\n```\n\nDetection signals (per language):\n\n- `c` — presence of `Makefile`, `CMakeLists.txt`, `*.c`\u002F`*.h` in src\n- `cpp` — `CMakeLists.txt` with `CXX`, `*.cpp`\u002F`*.cc`\u002F`*.hpp`, `meson.build`\n- `rust` — `Cargo.toml`\n- `go` — `go.mod`\n- `python` — `pyproject.toml`, `setup.py`, `requirements*.txt`\n- `node` — `package.json` with `dependencies` or `devDependencies`\n\n### Phase 2: Detect CI platform\n\n- `.github\u002Fworkflows\u002F` → GitHub Actions\n- `.gitea\u002Fworkflows\u002F` → Gitea Actions (same syntax as GitHub)\n- `.gitlab-ci.yml` → GitLab CI\n\nIf unclear, emit recipes for all three with a chooser comment.\n\n### Phase 3: Emit per-language recipes\n\nFor each detected language, write to `.aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002F{ci-platform}\u002F{language}.yaml`.\n\nReference emitter:\n\n```bash\nagentic\u002Fcode\u002Fframeworks\u002Fsecurity-engineering\u002Fskills\u002Fsanitizer-in-ci\u002Fscripts\u002Femit.sh \\\n  --language auto --ci auto\n```\n\n### Example: C\u002FC++ on Gitea\u002FGitHub Actions\n\n```yaml\n# .aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002Fgithub\u002Fc.yaml\n# Add to your workflow OR copy into .github\u002Fworkflows\u002Fsanitizers.yml\nname: Sanitizers (C\u002FC++)\non:\n  pull_request:\n  push:\n    branches: [main]\n\njobs:\n  asan-ubsan:\n    runs-on: ubuntu-latest\n    container: node:24@sha256:050bf2bbe33c1d6754e060bec89378a79ed831f04a7bb1a53fe45e997df7b3bb  # 24.15.0\n    env:\n      CC: clang\n      CXX: clang++\n      CFLAGS: \"-O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=all\"\n      CXXFLAGS: \"-O1 -g -fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=all\"\n      LDFLAGS: \"-fsanitize=address,undefined\"\n      ASAN_OPTIONS: \"abort_on_error=1:print_stacktrace=1:halt_on_error=1:detect_leaks=1\"\n      UBSAN_OPTIONS: \"print_stacktrace=1:halt_on_error=1\"\n      LSAN_OPTIONS: \"suppressions=.aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002Flsan-suppressions.txt\"\n    steps:\n      - uses: actions\u002Fcheckout@34e114876b0b11c390a56381ad16ebd13914f8d5  # v4.3.1\n      - name: Install clang\n        run: apt-get update && apt-get install -y clang make cmake\n      - name: Build with ASan + UBSan\n        run: |\n          # Adjust to your build system:\n          # cmake: cmake -B build && cmake --build build\n          # make:  make\n          make\n      - name: Run test suite under sanitizers\n        run: make test\n      - name: Upload sanitizer logs on failure\n        if: failure()\n        uses: actions\u002Fupload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882  # v4.4.3\n        with:\n          name: sanitizer-logs-c\n          path: |\n            build\u002FTesting\u002FTemporary\u002FLastTest.log\n            *.san.log\n\n  msan:\n    # MSan requires every dependency to be MSan-instrumented (including libc).\n    # Most projects find this prohibitively expensive — enable only if you can build deps from source.\n    runs-on: ubuntu-latest\n    if: false  # set to true if your build allows MSan-instrumented deps\n    # ... similar shape with -fsanitize=memory\n\n  tsan:\n    # TSan: thread races. Enable for multi-threaded code.\n    runs-on: ubuntu-latest\n    if: false  # enable for threaded projects\n    # ... similar shape with -fsanitize=thread\n```\n\n### Example: Rust\n\n```yaml\n# .aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002Fgithub\u002Frust.yaml\nname: Sanitizers (Rust)\non: [pull_request, push]\n\njobs:\n  asan:\n    runs-on: ubuntu-latest\n    env:\n      RUSTFLAGS: \"-Zsanitizer=address\"\n      RUSTDOCFLAGS: \"-Zsanitizer=address\"\n      ASAN_OPTIONS: \"abort_on_error=1:halt_on_error=1\"\n    steps:\n      - uses: actions\u002Fcheckout@34e114876b0b11c390a56381ad16ebd13914f8d5\n      - name: Install nightly toolchain\n        run: |\n          rustup toolchain install nightly --component rust-src\n          rustup default nightly\n      - name: Test with ASan\n        run: cargo +nightly test -Zbuild-std --target x86_64-unknown-linux-gnu\n\n  miri:\n    runs-on: ubuntu-latest\n    env:\n      MIRIFLAGS: \"-Zmiri-strict-provenance\"\n    steps:\n      - uses: actions\u002Fcheckout@34e114876b0b11c390a56381ad16ebd13914f8d5\n      - name: Install miri\n        run: |\n          rustup toolchain install nightly --component miri\n          cargo +nightly miri setup\n      - name: Run miri\n        run: cargo +nightly miri test\n```\n\n### Example: Go\n\n```yaml\n# .aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002Fgithub\u002Fgo.yaml\nname: Sanitizers (Go)\non: [pull_request, push]\n\njobs:\n  race-detector:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@34e114876b0b11c390a56381ad16ebd13914f8d5\n      - uses: actions\u002Fsetup-go@0aaccfd150d50ccaeb58ebd88d36e91967a5f35b  # v5.4.0\n        with:\n          go-version-file: go.mod\n      - name: Test with race detector\n        run: go test -race -count=1 .\u002F...\n```\n\n### Example: Python\n\n```yaml\n# .aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002Fgithub\u002Fpython.yaml\nname: Runtime Checks (Python)\non: [pull_request, push]\n\njobs:\n  faulthandler-and-warnings:\n    runs-on: ubuntu-latest\n    env:\n      PYTHONFAULTHANDLER: \"1\"\n      PYTHONDEVMODE: \"1\"  # equivalent to python -X dev\n      PYTHONWARNINGS: \"error\"  # warnings-as-errors\n    steps:\n      - uses: actions\u002Fcheckout@34e114876b0b11c390a56381ad16ebd13914f8d5\n      - uses: actions\u002Fsetup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v5.6.0\n        with:\n          python-version-file: .python-version\n      - name: Install deps\n        run: pip install -e .[dev]\n      - name: Test with dev mode + faulthandler\n        run: pytest -W error\n```\n\n### Phase 4: Emit suppression files\n\nFor C\u002FC++, write `.aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002Flsan-suppressions.txt` with documented categories:\n\n```\n# LeakSanitizer suppressions\n# Each entry MUST have a reason comment. Unjustified entries are reviewed quarterly.\n\n# Third-party library known leak (upstream tracker: \u003Clink>)\n# leak:libfoo\n\n# OpenSSL one-time init leak — by design, lives until process exit\n# leak:OPENSSL_init_crypto\n```\n\n### Phase 5: Emit operator guide\n\n`.aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002FOPERATOR.md`:\n\n```markdown\n# Sanitizer Operator Guide\n\n## What each sanitizer catches\n\n- **ASan (AddressSanitizer)**: heap\u002Fstack overflow, use-after-free, double-free, memory leaks\n- **UBSan (UndefinedBehaviorSanitizer)**: signed overflow, null deref, OOB shifts, misaligned reads\n- **MSan (MemorySanitizer)**: uninitialized memory reads\n- **TSan (ThreadSanitizer)**: data races, deadlocks\n- **Race (Go)**: data races in goroutines\n- **faulthandler (Python)**: segfaults in C extensions; emits Python tracebacks\n\n## Triage workflow\n\n1. Sanitizer fails in CI → download the log artifact\n2. Identify the access (e.g., `READ of size 4 at 0x...`)\n3. Match to source via the stack trace\n4. Decide: real bug → fix; false positive → suppression entry with link to upstream issue\n\n## Suppressions policy\n\nEvery suppression entry MUST cite a reason. Quarterly review removes obsolete ones.\n```\n\n## Composition\n\n- `dev-idempotent-builds.md` rule — sanitizer CI jobs MUST use pinned action SHAs and pinned container digests\n- `ci-action-pinning.md` rule — same\n- `fuzzing-in-ci` skill — complementary; fuzzing generates inputs that sanitizers then validate\n\n## Implementation Status\n\n- `scripts\u002Femit.sh` emits recipe files under `.aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002F{ci-platform}\u002F`.\n- Recipes are starter templates; project-specific tuning is still required for build commands, dependencies, and suppression paths.\n- MSan\u002FTSan remain conditional because enabling them requires project-specific instrumentation of all dependencies.\n- OSS-Fuzz integration lives in `fuzzing-in-ci`, not here.\n\n## References\n\n- @$AIWG_ROOT\u002Fagentic\u002Fcode\u002Fframeworks\u002Fsecurity-engineering\u002Fskills\u002Ffuzzing-in-ci\u002FSKILL.md — Companion fuzzing skill\n- @$AIWG_ROOT\u002Fagentic\u002Fcode\u002Fframeworks\u002Fsecurity-engineering\u002Flib\u002Ftoolchain-detect.sh — Shared detection\n- `.aiwg\u002Fsecurity\u002Fcurl-checklist-gap-analysis.md` row 14\n- AddressSanitizer: https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fsanitizers\u002Fwiki\u002FAddressSanitizer\n- UBSan: https:\u002F\u002Fclang.llvm.org\u002Fdocs\u002FUndefinedBehaviorSanitizer.html\n- Rust sanitizers: https:\u002F\u002Fdoc.rust-lang.org\u002Fbeta\u002Funstable-book\u002Fcompiler-flags\u002Fsanitizer.html\n- Go race detector: https:\u002F\u002Fgo.dev\u002Fdoc\u002Farticles\u002Frace_detector\n",{"name":5,"errors":60,"script":65,"ensures":70,"requires":77,"namespace":82,"platforms":83,"invariants":85,"commandHint":88,"description":7},[61,63],{"no-supported-language":62},"project has no language this skill can wire sanitizers for",{"unknown-ci-platform":64},"no recognizable CI directory; emit recipes for all three with a chooser note",{"cwd":66,"runtime":67,"argsHint":68,"entrypoint":69},"project-root","node","[--language c|cpp|rust|go|python|node|auto] [--ci gitea|github|gitlab|auto] [--coverage]","scripts\u002Femit.mjs",[71,73,75],{"ci-recipe":72},"emit ready-to-paste CI job(s) at .aiwg\u002Fsecurity-engineering\u002Fsanitizers\u002F{ci-platform}\u002F{language}.yaml",{"suppression-template":74},"emit a starter suppressions file for known acceptable false positives",{"operator-guide":76},"emit OPERATOR.md explaining what each sanitizer catches and how to triage findings",[78,80],{"toolchain":79},"at least one supported language detected (C, C++, Rust, Go, Python, Node)",{"ci-platform":81},"known CI platform (Gitea Actions, GitHub Actions, GitLab CI) — auto-detected from .github\u002F.gitea\u002F.gitlab files","aiwg",[84],"all",[86,87],"never modifies existing CI files in place — always emits new files under .aiwg\u002F for operator review","emitted recipes do NOT replace test runs; they ADD a parallel sanitizer-enabled run",{"model":43,"category":52,"modelRole":89,"modelTier":90,"allowedTools":91,"argumentHint":92,"orchestration":56},"efficiency","economy","Read, Write, Bash, Glob, Grep","[--language c|cpp|rust|go|python|node|auto] [--ci gitea|github|gitlab|auto] [--sanitizers asan,ubsan,msan,tsan,race,faulthandler] [--coverage]","main","6754967c344ccb087a8de06972f55a41067b291b","agentic\u002Fcode\u002Fplugins\u002Fsecurity-engineering\u002Fskills\u002Fsanitizer-in-ci",36,"https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg","https:\u002F\u002Faiwg.io","https:\u002F\u002Fgithub.com\u002Fjmagly","https:\u002F\u002Fintegrolabs.io","ml\u002Fai, industrial automation, safety\u002Fsecurity, ssi\r\n\r\nmagly.net\r\nintegrolabs.io\r\naiwg.io\r\nfortemi.com\r\npagenary.com\r\nbytecask.com","2026-11-12 00:33:10",{"source":8,"skillName":5,"commands":104,"prompt":114,"zipAvailable":115},[105,108,111],{"tool":106,"command":107},"npx","npx skills add jmagly\u002Faiwg --skill sanitizer-in-ci",{"tool":109,"command":110},"bunx","bunx skills add jmagly\u002Faiwg --skill sanitizer-in-ci",{"tool":112,"command":113},"pnpm","pnpm dlx skills add jmagly\u002Faiwg --skill sanitizer-in-ci","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fplugins\u002Fsecurity-engineering\u002Fskills\u002Fsanitizer-in-ci\u002FSKILL.md",true,[117,122],{"path":69,"resourceType":118,"resourceTypeDesc":119,"sizeBytes":120,"sourceHtmlUrl":121},"SCRIPT","脚本",4697,"https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fplugins\u002Fsecurity-engineering\u002Fskills\u002Fsanitizer-in-ci\u002Fscripts\u002Femit.mjs",{"path":123,"resourceType":118,"resourceTypeDesc":119,"sizeBytes":124,"sourceHtmlUrl":125},"scripts\u002Femit.sh",135,"https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fplugins\u002Fsecurity-engineering\u002Fskills\u002Fsanitizer-in-ci\u002Fscripts\u002Femit.sh",[127,152,173,179,186,200],{"skillNo":128,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":131,"categories":132,"keywords":134,"publishedAt":55},"01M70QA0BSYJ49EES9V4RE8QH1","host-hardening","Read-only system hardening baseline and plan-first host hardening recommendations for SSH, Docker bind addresses, firewall persistence, datastores, exporters and audit retention.","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fplugins\u002Fsecurity-engineering\u002Fskills\u002Fhost-hardening\u002FSKILL.md",[133],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[135,136,137,41,138,139,140,141,142,143,44,144,145,146,147,37,148,149,150,151],"host","host hardening","hardening","re","recommendations","remediation","plan","port","verification","access","only","retention","audit","firewall","bind","secrets","request",{"skillNo":153,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":156,"categories":157,"keywords":160,"publishedAt":55},"01M70PNT2Z4HMZPRBTAF6073NN","exposure-analysis","Read-only firewall analysis and effective host exposure reconstruction for Docker published ports, UFW bypass, stale rules, CDN scope, IPv6 asymmetry and external probe allowlists.","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fplugins\u002Fforensics\u002Fskills\u002Fexposure-analysis\u002FSKILL.md",[158,159],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[161,162,163,41,164,142,165,166,44,167,135,168,145,169,170,37,148,171,172,40],"exposure analysis","analysis","unknown","credentials","collection","ufw","ports","internet","local","scope","reconstruction","operator",{"skillNo":174,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":175,"categories":176,"keywords":178,"publishedAt":55},"01M70P8QATMPKA78E4FT5D2TNA","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fframeworks\u002Fsecurity-engineering\u002Fskills\u002Fhost-hardening\u002FSKILL.md",[177],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[137,135,136,144,41,151,140,139,147,141,142,143,44,150,145,146,138,37,148,149],{"skillNo":180,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":181,"categories":182,"keywords":185,"publishedAt":55},"01M70NMPVJ5H0JH131P60FW4R8","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fframeworks\u002Fforensics-complete\u002Fskills\u002Fexposure-analysis\u002FSKILL.md",[183,184],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[162,161,37,164,142,165,44,163,135,168,145,169,170,41,148,167,166,171,172,40],{"skillNo":187,"name":188,"nameZh":6,"description":189,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":190,"categories":191,"keywords":193,"publishedAt":55},"01M6CB4DDR0B4NNCFK7ZK7449H","fixture-skill","Exercise rule delivery.","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Ftest\u002Ffixtures\u002Frule-delivery\u002Fskills\u002Ffixture-skill\u002FSKILL.md",[192],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[194,195,196,197,198,199],"fixture skill","fixture","rule","delivery","true","exercise",{"skillNo":201,"name":202,"nameZh":6,"description":203,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":204,"categories":205,"keywords":207,"publishedAt":55},"01M6CB4AVK1W76MFMPP0JP32CJ","pi-local","Pi-local duplicate-precedence fixture.","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Ftest\u002Ffixtures\u002Fproviders\u002Fpi\u002Fproject\u002F.pi\u002Fskills\u002Fpi-local\u002FSKILL.md",[206],{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[208,209,169,210,195],"pi","pi local","duplicate"]