Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Android の静的解析における SARIF ファイルの活用

Hiroyuki Kusu
January 31, 2024

Android の静的解析における SARIF ファイルの活用

Android Test Night #9 ( https://testnight.connpass.com/event/305270 ) の資料

Hiroyuki Kusu

January 31, 2024
Tweet

More Decks by Hiroyuki Kusu

Other Decks in Technology

Transcript

  1. ຊ೔ͷ಺༰ • GitHub code scanning ͷ֓ཁ • CIʢGitHub ActionsʣͰ֤छ ੩తղੳπʔϧͱ

    GitHub code scanning Λ ࿈ܞ͢Δํ๏ͷઆ໌ • Android Lint • ktlint • mobsfscan • Qodana • CodeQL • GitHub code scanning Λ࢖Θͳ͍৔߹ͷ SARIF ϑΝΠϧͷ׆༻ 
  2.  GitHub code scanning • ϦϙδτϦ಺ͷίʔυΛ෼ੳͯ͠ɺηΩϡϦςΟͷ੬ऑੑͱίʔσΟϯά ΤϥʔΛݟ͚ͭΔ͜ͱ͕Ͱ͖Δػೳ • CodeQLʢGitHub ͕։ൃͨ͠ίʔυ෼ੳΤϯδϯʣΛ࢖༻ͯ͠ίʔυΛ

    ෼ੳ͠ɺ݁ՌΛΞϥʔτͱͯ͠දࣔ͢Δ͜ͱ͕ग़དྷΔ • private ϦϙδτϦͰ͸ GitHub Advanced Security ͷϥΠηϯεʢ༗ྉʣ ͕ඞཁ
  3.  • CodeQL Ҏ֎ͷ੩తղੳπʔϧͰ΋ར༻Ͱ͖Δ • CI Ͱ SARIF ܗࣜͷϨϙʔτΛΞοϓϩʔυ͢Ε͹Α͍ •

    SARIFɿ Static Analysis Results Interchange Format ͷུ GitHub code scanning
  4.  { "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", "version": "2.1.0", "runs": [ { "originalUriBaseIds":

    { "%SRCROOT%": { "uri": "file:///home/runner/" } }, "results": [ { "level": "error", "locations": [ { "physicalLocation": { "artifactLocation": { "uri": “work/your-ropo/your-repo/app/src/main/java/com/example/myapp/android/MyApplicationTheme.kt”, "uriBaseId": "%SRCROOT%" }, "region": { "startColumn": 5, "startLine": 19 } } } ], "message": { "text": "Function name should start with a lowercase letter (except factory methods) and use camel case" }, "ruleId": "standard:function-naming" }, … ], "tool": { "driver": { "downloadUri": "https://github.com/pinterest/ktlint/releases/tag/1.0.1", "fullName": "ktlint", "informationUri": "https://github.com/pinterest/ktlint/", "language": "en", "name": "ktlint", "organization": "pinterest", "rules": [], "semanticVersion": "1.0.1", "version": "1.0.1" } } } ] } ktlint ͷ SARIF ϑΝΠϧͷྫ Schema ͷόʔδϣϯʢcode scanning ͸ 2.1.0 Λαϙʔτʣ ݕग़͞Εͨ໰୊ ࢖༻ͨ͠੩తղੳπʔϧͷ৘ใ πʔϧʹΑͬͯ͸ rules ཝʢͦΕҎ֎ͷ৔ॴͷ৔߹΋͋Δʣʹɺ֤ݕग़ϧʔϧ ͷิ଍৘ใ͕ॻ͔Ε͍ͯΔ
  5.  "results": [ { "level": "error", "locations": [ { "physicalLocation":

    { "artifactLocation": { "uri": “work/your-ropo/your-repo/app/src/main/java/com/example/myapp/android/MyApplicationTheme.kt”, "uriBaseId": "%SRCROOT%" }, "region": { "startColumn": 5, "startLine": 19 } } } ], "message": { "text": "Function name should start with a lowercase letter (except factory methods) and use camel case" }, "ruleId": "standard:function-naming" }, … ], ໰୊͕͋ΔϑΝΠϧͷύε ΤϥʔϨϕϧɻ͜͜Ͱ͸ͳ͘ rules ཝ౳ʹॻ͔Ε͍ͯΔ৔߹΋͋Δ ໰୊ͷίʔυͷҐஔɻπʔϧʹΑͬͯ͸։࢝Ґஔ͚ͩͰ ͳ͘ऴྃҐஔ΋ॻ͔Ε͍ͯΔ৔߹΋͋Δ ໰୊ͷ಺༰ͷςΩετ ݕग़ʹར༻ͨ͠ϧʔϧͷIDɻ͜ͷ ID ʹؔ͢Δิ଍৘ใ͕ rules ཝ౳ ʹॻ͔Ε͍ͯΔ৔߹͕͋Δ results ཝΛ֦େ
  6.  android { ... lint { sarifReport = true checkDependencies

    = true } } • SARIF ܗࣜͰϨϙʔτΛग़ྗ͢Δઃఆ • ϚϧνϞδϡʔϧߏ੒ͷ৔߹Ͱ΋ɺϧʔτͷϞδϡʔϧͰ checkDependencies = true Λࢦఆ͢Ε͹ɺαϒϞδϡʔϧࠐΈͷϨϙʔτ͕࡞੒͞ΕΔ Android Lint × GitHub code scanning app/build.gradle.kts
  7.  name: CI on: push: branches: [main] pull_request: branches: [main]

    jobs: analyze: runs-on: ubuntu-latest permissions: security-events: write actions: read contents: read steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: zulu java-version: 17 - run: ./gradlew app:lintDebug continue-on-error: true - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ./app/build/reports/lint-results-debug.sarif category: android-lint:debug Android Lint × GitHub code scanning github/codeql-action/upload-sarif action ͷ࣮ߦͰඞཁͳ permission code scanning ͕ར༻Ͱ͖ΔϦϙδτϦͰͳ͍৔߹͸͜ͷ step ͸ΤϥʔͱͳΓ·͢
  8.  - run: ./gradlew app:lintDebug continue-on-error: true Android Lint ×

    GitHub code scanning • ʢղੳॲཧ͕ਖ਼ৗʹऴΘͬͯ΋ʣ໰୊Λݕग़ͨ͠৔߹ʹऴྃίʔυ͕ 0 Ҏ֎ͱͳΔ੩తղੳ πʔϧͷ৔߹͸ continue-on-error: true Λࢦఆ • ϫʔΫϑϩʔ͕ fail εςʔλεͷ৔߹ɺcode scanning ͸ ղੳॲཧʹࣦഊ ͨ͠ͱΈͳ͢ • πʔϧଆͷઃఆͰɺͦ΋ͦ΋ҟৗऴྃ͠ͳ͍Α͏ʹͯ͠΋Α͍ • ྫ͑͹ Android Lint ͷ৔߹͸ abortOnError = false • ΋͘͠͸ ./gradlew app:lintDebug || true ͷΑ͏ʹͯ͠ҟৗऴྃΛѲΓ௵͢
  9.  Android Lint × GitHub code scanning - uses: github/codeql-action/upload-sarif@v3

    with: sarif_file: ./app/build/reports/lint-results-debug.sarif category: android-lint:debug • category ʹ͸೚ҙͷจࣈྻΛࢦఆՄೳ • লུ͢ΔͱʮϫʔΫϑϩʔϑΝΠϧ໊:δϣϒ໊ʯͱͳΔ • ʢ޷Έͷ໰୊Ͱ͸͋Δ͕ʣ೦ͷͨΊলུͤͣʹࢦఆ͓͍ͯͨ͠ํ͕ແ೉ͱࢥΘΕΔ • কདྷతʹϫʔΫϑϩʔΛ੔ཧͨ݁͠Ռɺδϣϒ໊͕มΘͬͯ͠·͏͜ͱ΋͋ΓಘΔ • ্هͷྫͰ͸πʔϧ໊ʹՃ͑ͯɺͲͷόϦΞϯτʹର͢Δղੳͳͷ͔Λ : Ҏ߱Ͱදݱ͍ͯ͠Δ • ͨͩԾʹ్தͰ category ͕มΘͬͯ͠·ͬͯ΋ɺͳΜͱͳ͘͸ཤྺͷඥ͚ͮ͸͞ΕΔ
  10.  val ktlintCheck by tasks.registering(JavaExec::class) { group = LifecycleBasePlugin.VERIFICATION_GROUP description

    = "Check Kotlin code style" classpath = ktlint mainClass.set("com.pinterest.ktlint.Main") args( "--color", "--reporter=plain", "--reporter=sarif,output=${buildDir}/reports/ktlint-results.sarif", "**/src/**/*.kt", "**.kts", "!**/build/**", ) // isIgnoreExitValue = true ҟৗऴྃͤ͞ͳ͍৔߹ } build.gradle.ktsʢϓϥάΠϯΛ࢖༻ͤͣʹ ktlint Λಋೖ͍ͯ͠Δ৔߹ʣ ktlint × GitHub code scanning
  11.  ktlint × GitHub code scanning name: CI on: push:

    branches: [main] pull_request: branches: [main] jobs: analyze: runs-on: ubuntu-latest permissions: security-events: write actions: read contents: read steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v3 with: distribution: zulu java-version: 17 - run: ./gradlew ktlintCheck continue-on-error: true - run: | cat './app/build/reports/ktlint-results.sarif' \ | jq '.runs[].results[].locations[].physicalLocation.artifactLocation.uri |= ltrimstr(“work/your-repo/your-repo/“)’ \ > '${{ runner.temp }}/ktlint-results.sarif' - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ runner.temp }}/ktlint-results.sarif category: ktlint
  12.  ktlint × GitHub code scanning - run: | cat

    './app/build/reports/ktlint-results.sarif' \ | jq '.runs[].results[].locations[].physicalLocation.artifactLocation.uri |= ltrimstr(“work/your-repo/your-repo/“)’ \ > '${{ runner.temp }}/ktlint-results.sarif' "artifactLocation": { "uri": “work/your-ropo/your-repo/app/src/main/java/com/example/myapp/android/MyApplicationTheme.kt”, "uriBaseId": "%SRCROOT%" } SARIF ϑΝΠϧͷՃ޻͕ඞཁ "artifactLocation": { "uri": “app/src/main/java/com/example/myapp/android/MyApplicationTheme.kt”, "uriBaseId": "%SRCROOT%" } uri ͔Β work/your-repo/your-rep/ Λআڈ
  13.  ktlint × GitHub code scanning file:///home/runner/work/your-ropo/your-repo/app/src/main/java/com/example/myapp/android/MyApplicationTheme.kt or app/src/main/java/com/example/myapp/android/MyApplicationTheme.kt GitHub

    code scanning Ͱ uri ͷύεΛਖ਼͘͠ೝࣝͤ͞Δʹ͸ɺ fi le:// ͔Β࢝·Δ CI ্ͷઈରύεɺ ΋͘͠͸ϦϙδτϦ௚ԼΛϧʔτͱ͢Δ૬ରύεͷͲͪΒͷܗࣜͰ͋Δඞཁ͕͋Δ SARIF ϑΝΠϧ಺ͷ SRCROOT Ͱ uri ͷϕʔεͷύε͕ఆٛ͞Ε͍ͯΔʢϕʔεͱ߹Θͤͯઈରύ εͱͳΔʣ৔߹͕͋Δ͕ɺcode scanning ͸ SRCROOT Λݟ͍ͯͳ͍
  14.  ktlint × GitHub code scanning - run: ./gradlew ktlintCheck

    --continue continue-on-error: true - run: | cat './app/build/reports/ktlint-results.sarif' \ | jq '.runs[].results[].locations[].physicalLocation.artifactLocation.uri |= ltrimstr(“work/your-repo/your-repo/")' \ > '${{ runner.temp }}/ktlint-results.sarif' - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ runner.temp }}/ktlint-results.sarif category: ktlint:app - run: | cat './shared/build/reports/ktlint-results.sarif' \ | jq '.runs[].results[].locations[].physicalLocation.artifactLocation.uri |= ltrimstr("work/your-repo/your-repo/")' \ > '${{ runner.temp }}/ktlint-results.sarif' - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ runner.temp }}/ktlint-results.sarif category: ktlint:shared 1ͭͷϞδϡʔϧͰҟৗऴ͕ྃ͋ͬͯ΋ܧଓ͢ΔΑ͏ʹ conitue Λࢦఆ ʢktlint ͷઃఆͰͦ΋ͦ΋ҟৗऴྃ͠ͳ͍Α͏ʹͯ͠΋Α͍ʣ ಉҰ job ͰಉҰπʔϧͷ݁ՌΛΞοϓϩʔυ͢Δ৔߹͸ category Λ ม͑Δඞཁ͕͋Δʢaction ͕ΤϥʔͱͳΔ ϚϧνϞδϡʔϧߏ੒ͷ৔߹
  15.  mobsfscan is a static analysis tool that can fi

    nd insecure code patterns in your Android and iOS source code. Supports Java, Kotlin, Android XML, Swift and Objective C Code. mobsfscan uses MobSF static analysis rules and is powered by semgrep and libsast pattern matcher. mobsfscan × GitHub code scanning README Ͱͷઆ໌
  16.  mobsfscan × GitHub code scanning name: CI on: push:

    branches: [main] pull_request: branches: [main] jobs: analyze: runs-on: ubuntu-latest permissions: security-events: write actions: read contents: read steps: - uses: actions/checkout@v4 - uses: MobSF/mobsfscan@main with: args: . --sarif --output results.sarif continue-on-error: true - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: results.sarif category: mobsfscan
  17. mobsfscan × GitHub code scanning  • ݕग़Ͱ͖Δ໰୊͕Ҏ֎ʹগͳ͍ʁ • େ͖ͳϓϩδΣΫτͰ͸ࢼ͍ͤͯͳ͍͕ɺࢼ͠ʹ

    google/iosched ͷΞ ϓϦΛର৅ʹݕࠪͯ͠΋ 9 ݅ͷݕग़ͩͬͨ • ൺֱͱͯ͠ɺQodana ʹΑΔݕग़͸ 2,800 ݅ • ΋͔ͯ͜͠͠ΕͰ΋े෼ͳݕࠪ͸͞Ε͍ͯΔͷ͔΋͠Εͳ͍͕ɺ಺༰ͷ ਫ਼ࠪ͸ඞཁͦ͏
  18. Qodana × GitHub code scanning  • JVMʢJava / KotlinʣɺAndroid

    ͸ Community ϓϥϯʢແྉʣͰ΋࢖͑Δ • ଞͷ༗ྉϓϥϯͱͷػೳࠩ͸গ͋͠Δ • Community ϓϥϯ૬౰ͷػೳʢڪΒ͘ʣΛར༻͢ΔݶΓͰ͸ɺ JetBrains ΞΧ΢ϯτͳ͠ʹ GitHub Actions ͷϫʔΫϑϩʔͰར༻Ͱ͖Δ • ϫʔΫϑϩʔͱμογϡϘʔυʢQodana Cloudɻར༻ʹ͸ JetBrains ΞΧ΢ϯτ͕ඞཁʣΛ࿈ܞ͢Δ৔߹͸ɺCloud ଆͰൃߦ͞ΕͨτʔΫϯ ΛϫʔΫϑϩʔ΁ઃఆ͢Δඞཁ͕͋Δ
  19. version: "1.0" linter: jetbrains/qodana-jvm-android:2023.3 profile: name: qodana.recommended projectJDK: 17 Qodana

    × GitHub code scanning  ϦϙδτϦ௚Լʹ qodana.yaml ϑΝΠϧΛ഑ஔ
  20. Qodana × GitHub code scanning  name: CI on: push:

    branches: [main] pull_request: branches: [main] jobs: analyze: runs-on: ubuntu-latest permissions: security-events: write actions: read contents: read steps: - uses: actions/checkout@v4 - uses: JetBrains/[email protected] with: post-pr-comment: false use-annotations: false pr-mode: false - run: | cat '${{ runner.temp }}/qodana/results/qodana.sarif.json' \ | jq 'del(.runs[].automationDetails)' \ > '${{ runner.temp }}/qodana.sarif' - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ runner.temp }}/qodana.sarif category: qodana:jvm-android Qodana ͷϓϧϦΫ࿈ܞͷػೳ͸શͯ off ʹʢมߋߦʹର͢Δ annotation ͕ code scanning ͷ΋ͷͱඃΔͷͰʣ
  21.  Qodana × GitHub code scanning SARIF ϑΝΠϧͷՃ޻͕ඞཁ - run:

    | cat '${{ runner.temp }}/qodana/results/qodana.sarif.json' \ | jq 'del(.runs[].automationDetails)' \ > '${{ runner.temp }}/qodana.sarif' - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ runner.temp }}/qodana.sarif category: qodana:jvm-android .runs[].automationDetails ཝΛ࡟আ
  22.  Qodana × GitHub code scanning ʢલϖʔδͷଓ͖ʣcategory ΁ࢦఆͨ͠จࣈྻΑΓ΋ SARIF ಺ͷ

    .runs[].automationDetails.id ͷ จࣈྻ͕༏ઌ͞Ε code scanning ΁౉͞ΕΔɻຊདྷ͸ͦΕͰ΋Α͍͕ݱঢ়ɺQodana ͕ੜ੒͢Δ SARIF ϑΝΠϧͰ͸ϓϧϦΫͱ push ΠϕϯτͰ id ͷ಺༰͕ҟͳΔҝɺcode scanning ͷը໘Ͱ ܯࠂ͕දࣔ͞Εͯ͠·͏ Αͬͯࣄલʹ .runs[].automationDetails ཝΛ࡟আ͠ɺϫʔΫϑϩʔͰࢦఆͨ͠ category Λద༻ͤ͞Δ
  23.  Qodana × GitHub code scanning - uses: JetBrains/[email protected] env:

    QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} with: post-pr-comment: false use-annotations: false pr-mode: false Qodana ͷμογϡϘʔυʢQodana Cloudʣͱ࿈ܞ͢Δ৔߹ Cloud ଆͰൃߦ͞ΕͨτʔΫϯΛઃఆ
  24.  Qodana × GitHub code scanning • Android Lint ͱॏෳ͢Δݕ͕ࠪଟ͍͔΋͠Εͳ͍

    • ಉ࣌ʹϨϙʔτ͢Δͱ։ൃऀ͕ࠞཚͯ͠͠·͏Մೳੑ • Qodana ͱ Android Lint ͷݕࠪͷΧόʔൣғΛͦΕͧΕ֬ೝͨ͠ํ͕Α ͍͔΋ • ৔߹ʹΑͬͯ͸ Qodana ΁ҰຊԽ͢Δʁ
  25.  steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - uses:

    JetBrains/[email protected] with: post-pr-comment: true use-annotations: true pr-mode: true - run: | cat '${{ runner.temp }}/qodana/results/qodana.sarif.json' \ | jq 'del(.runs[].automationDetails)' \ > '${{ runner.temp }}/qodana.sarif' - uses: actions/checkout@v4 - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{ runner.temp }}/qodana.sarif category: qodana:jvm-android σϑΥϧτ஋Ͳ͓ΓͳͷͰࢦఆͳ͠Ͱ΋Α͍ ʢuse-annotation Ҏ֎͸ push ΠϕϯτͰ͸ແࢹ͞ΕΔʣ Qodana × GitHub code scanningʢิ଍ʣ Ծʹ JetBrains/qodana-action ͷ pr-mode Λར༻͢Δ৔߹ɺϫʔΫεϖʔεͷ Git ͷঢ়ଶ͕ม Θͬͯ͠·͍ޙଓͷ github/codeql-action/upload-sarif ͕͏·͘ಈ͔ͳ͘ͳΔͷͰɺ࠶νΣοΫ Ξ΢τ౳Ͱ Git ͷঢ়ଶΛ໭͓ͯ͘͠ඞཁ͕͋Δ ԾʹϓϧϦΫͰ pr-mode Λར༻͢Δ৔߹ 0 ʹ͠ͳ͍ͱ pr-mode ͕ద༻͞Εͳ͍ ·ͨ post-pr-comment ͸ pull-requests: write permission ͕ɺ use-annotations ͸ checks: write permission ͕ඞཁ ͜͜Ͱ࠶νΣοΫΞ΢τ͕ඞཁʂ
  26.  Qodana × GitHub code scanningʢิ଍ʣ ʢલϖʔδͷଓ͖ʣQodana ʹ͸ GitHub Actions

    ͷ cache Λར༻ͨ͠Ϧιʔεͷ࠶ར༻ͷ࢓૊Έ ͕͋Δ͕ɺΩϟογϡ͕ແ͍ঢ়ଶͰ JetBrains/qodana-action Λ࢖༻͢Δͱɺͳ͔ͥݕग़݅਺͕ গͳ͘ͳΔݱ৅͕ΈΒΕͨɻকདྷతʹվળ͞ΕΔ͔΋͠Εͳ͍ɻ cache ͸σϑΥϧτͰ͸ϒϥϯνຖʹ࡞੒͞ΕΔɻmain ϒϥϯνͷΑ͏ͳ௕͘ར༻͞ΕΔϒϥϯ νͰ͸աڈͷ cache ͕͋Δҝ΄΅໰୊ͱ͸Βͳ͍͕ɺϓϧϦΫͷ৔߹͸ open ࣌͸ cache ͕ແ͍ ঢ়ଶͱͳͬͯ͠·͏ҝɺຊ action ͷ additional-cache-key ʹʮqodana-2023.3-ʯ౳ͷ cache Ωʔ Λࢦఆͯ͠ɺϚʔδઌͷϒϥϯν ·ͨ͸ σϑΥϧτϒϥϯνͷ cache Λ open ࣌ʹ΋ద༻͞ΕΔ Α͏ʹͨ͠ํ͕Α͍͔΋͠Εͳ͍ɻʢͨͩ cache ͷ෭࡞༻తͳ΋ͷ͸ؾʹͳΔͱ͜Ζ͕ͩɻʣ
  27. CodeQL × GitHub code scanning  name: CI on: push:

    branches: [main] pull_request: branches: [main] jobs: analyze: runs-on: ubuntu-latest permissions: security-events: write actions: read contents: read steps: - uses: actions/checkout@v4 - uses: github/codeql-action/init@v3 with: languages: java-kotlin - uses: actions/setup-java@v3 with: distribution: zulu java-version: 17 - run: ./gradlew assembleDebug - uses: github/codeql-action/analyze@v3 with: category: codeql:java-kotlin ͜ͷ action Ͱ SARIF ͷΞοϓϩʔυ·ͰߦΘΕΔ java-kotlin Λࢦఆ
  28. CodeQL × GitHub code scanning • ͦ΋ͦ΋ GitHub code scanning

    ͱ࿈ܞ͢Δ΋ͷͳͷͰ͢ΜͳΓಋೖͰ͖ Δʢ͸ͣʣ • ݕग़Ͱ͖Δ໰୊͕Ҏ֎ʹগͳ͍ʁ • େ͖ͳϓϩδΣΫτͰ͸ࢼ͍ͤͯͳ͍͕ɺࢼ͠ʹ google/iosched ͷΞ ϓϦΛର৅ʹݕࠪͯ͠΋ 1 ݅ͷݕग़ͩͬͨ • ൺֱͱͯ͠ɺQodana ʹΑΔݕग़͸ 2,800 ݅ • ݱ࣌఺Ͱ·ͩ ϕʔλ൛ ͔ͩΒ͔΋ʁ 
  29. GitHub code scanning Λ࢖Θͳ͍৔߹ • GitHub code scanning ͸ private

    ϦϙδτϦͰ͸ GitHub Advanced Security ͷϥΠηϯεʢ༗ྉʣ͕ඞཁ • ۀ຿ͷϓϩδΣΫτ͸େ֓ private ͳͷͰར༻͢Δʹ͸ෑډ͕͋Δ • ݱ࣌఺Ͱ͸ʢࢲͷ؍ଌൣғͰ͸ʣSARIF ϑΝΠϧ͔Βద੾ͳϨϙʔτΛ͠ ͯ͘ΕΔผͷαʔϏε΍πʔϧ౳͸ݟ͔ͭΒͳ͔ͬͨ • ͦ΋ͦ΋ SARIF ϑΝΠϧΛར༻͢Δඞཁ͕͋Δ͔ʁͱ͍͏͜ͱʹ͍ͭͯ ͸ɺ֤੩తղੳπʔϧΛ౷Ұతʹӡ༻͍ͨ͠ͱ͍͏χʔζʹର͢Δڞ௨ ϑΥʔϚοτͱͯ͠ɺ͜ΕΛར༻͢ΔҰఆͷҙٛ͸͋Δʢͱࢥ͏ʣ 
  30. GitHub code scanning Λ࢖Θͳ͍৔߹ • SARIF ͸ JSON ܗࣜͰ΋͋ͷͰɺ؆୯ʹσʔλΛύʔεͰ͖̎࣍ར༻͠΍ ͍͢

    • GitHub Actions ͷϫʔΫϑϩʔͰ͋Ε͹ jq ͕σϑΥϧτͰ࢖͑Δ • JavaScript Ͱ͋Ε͹ͦͷ·· JSON.parse() ͕Մೳ  .. ݱ࣌఺Ͱ͸ࣗલͰ SARIF ϑΝΠϧΛύʔεͯ͠ར༻͢ΔΑ͏ͳεΫϦϓτ Λ༻ҙ͢Δͷ͕ྑͦ͞͏
  31. GitHub code scanning Λ࢖Θͳ͍৔߹  ͜͜ͰɺCodeQL ʹ͍ͭͯ.. • GitHub code

    scanning ͕༗ޮͰͳ͍ϦϙδτϦͰ͸ github/codeql- action ܥͷҰ੾ͷ action ͕ΤϥʔͱͳΔ • ͜ΕΒͷ action Λར༻͠ͳ͘ͱ΋ɺCodeQL CLI Λར༻͢Ε͹ SARIF ϑΝΠϧͷग़ྗ·Ͱ͸ग़དྷͦ͏͕ͩɺֶज़ݚڀ౳ͷ໨తͰͳ͍ ৔߹͸ن໿ҧ൓ͱͳͬͯ͠·͏ • ͭ·ΓɺCodeQL ͸ GitHub code scanning ͱηοτͰར༻͢Δඞཁ ͕͋Δ Αͬͯ͜ΕҎ߱ͷ࿩͸ɺCodeQL Ҏ֎ͷ੩తղੳπʔϧͰͷ࿩ͱͳΓ·͢
  32.  - run: ./gradlew ktlintCheck continue-on-error: true - run: |

    cat './app/build/reports/ktlint-results.sarif' \ | jq '.runs[].results[].locations[].physicalLocation.artifactLocation.uri |= ltrimstr(“work/your-repo/your-repo/“)’ \ > '${{ runner.temp }}/ktlint-results.sarif' - run: | file='${{ runner.temp }}/ktlint-results.sarif' results="$(cat "$file" | jq -c '.runs[].results[] | { level, location: .locations[0].physicalLocation.artifactLocation.uri, line: .locations[0].physicalLocation.region.startLine, message: .message.text, ruleId }')" IFS=$'\n' for result in $results ; do level="$(echo "$result" | jq -r '.level')" location="$(echo "$result" | jq -r '.location')" line="$(echo "$result" | jq '.line')" message="$(echo "$result" | jq -r '.message')" ruleId="$(echo "$result" | jq -r '.ruleId')" case "$level" in 'error') message_level='error';; 'warning') message_level='warning';; 'note') message_level='notice';; *) # default message_level='warning' esac echo "::${message_level} file=${location},line=${line},title=${ruleId}::${message}" done ktlint ͷ SARIF ͷ಺༰Λ annotation ʹ͢Δྫ ※ ੩తղੳπʔϧʹΑͬͯ͸ level ͸ ruleId ΛΩʔͱͯ͠ rules ཝ౳͔Βऔಘ͢Δඞཁ͕͋Γ·͢ɻ·ͨΤϥʔͷৄࡉ಺ ༰΋ rules ཝ౳͔Βऔಘͨ͠ํ͕ΑΓΑ͍Ͱ͢
  33.  ϓϧϦΫͷ Files changed λϒͰͷදࣔ ktlint ͷ SARIF ͷ಺༰Λ annotation

    ʹ͢Δྫ ※ ຊདྷ͸։ൃऀ͕มߋͨ͠ߦͷΈʹ annotation ͢ΔΑ͏ͳ࣮૷Λͨ͠ํ͕Α͍Ͱ͢ ※ annotation ͷݸ਺ʹ͸੍ݶ͕͋Γ·͢ ※ ·ͨϨϏϡʔίϝϯτͱͯ͠ͷฦ৴΋Ͱ͖ͳ͍ͷͰɺannotation Ͱͳ͘ϓϧϦΫͷίϝϯτʹͨ͠ํ͕Α͍͔΋ Job Summaries Ͱͷදࣔ
  34.  - run: ./gradlew ktlintCheck continue-on-error: true - run: |

    cat './app/build/reports/ktlint-results.sarif' \ | jq '.runs[].results[].locations[].physicalLocation.artifactLocation.uri |= ltrimstr(“work/your-repo/your-repo/“)’ \ > '${{ runner.temp }}/ktlint-results.sarif' - run: | { file='${{ runner.temp }}/ktlint-results.sarif' results="$(cat "$file" | jq -c '.runs[].results[] | { level, location: .locations[0].physicalLocation.artifactLocation.uri, line: .locations[0].physicalLocation.region.startLine, message: .message.text, ruleId }')" IFS=$'\n' for result in $results ; do level="$(echo "$result" | jq -r '.level')" location="$(echo "$result" | jq -r '.location')" line="$(echo "$result" | jq '.line')" message="$(echo "$result" | jq -r '.message')" ruleId="$(echo "$result" | jq -r '.ruleId')" case "$level" in 'error') icon=':no_entry_sign:';; 'warning') icon=':warning:';; 'note') icon=':memo:';; *) # default icon=':warning:' esac location_url="https://github.com/${{ github.repository }}/blob/${{ github.sha }}/${location}#L${line}-${line}" echo "- ${icon} line ${line} in [${location}](${location_url})" echo " - **\`${ruleId}\`** ${message}" done } >> "$GITHUB_STEP_SUMMARY" ktlint ͷ SARIF ͷ಺༰Λ Job Summaries ΁ग़ྗ͢Δྫ ϚʔΫμ΢ϯܗࣜͰ Job Summaries ΁ग़ྗ
  35. • CodeQL Λআ͖ɺAndroid LintɺktlintɺmobsfscanɺQodana ͸ SARIF ܗࣜ Ҏ֎ʹ΋ HTML ܗࣜͰͷϨϙʔτग़ྗʹରԠ͍ͯ͠Δ

    • HTML Λ CI Ͱ GitHub Pages ΁σϓϩΠͯ͠Ӿཡ͢Δ • ීஈ Danger Λར༻͍ͯ͠Δ৔߹͸ danger-sarif ͱ͍͏ϓϥάΠϯ͕͋Δ • https://github.com/irgaly/danger-sarif • Qodana ͸ code scanning ͱ࿈ܞ͠ͳͯ͘΋͜Ε୯ମͰ݁ߏ͔ͭ͑Δ • Android Ͱ͋Ε͹ Community ϓϥϯʢແྉʣͰ࢖͑Δ • μογϡϘʔυʢQodana Cloudʣ࿈ܞ • ϓϧϦΫ࿈ܞʢannotation ΍αϚϦʔͷ౤ߘʣ  ͦͷଞͷબ୒ࢶ
  36. ͦͷ΄͔ࢀߟ৘ใ • detekt ΋ SARIF ͱ HTML ܗࣜͰͷϨϙʔτʹରԠ͍ͯ͠Δ • Dart

    Analyzerʢͱ Flutter AnalyzerʣͷϨϙʔτΛ SARIF ܗࣜ΁ม׵͢Δ GitHub custom action • https://github.com/marketplace/actions/dart-analyzer-sarif • JUnit ͷϨϙʔτΛ GitHub ͷ annotation ʹ͢Δ GitHub custom action • https://github.com/mikepenz/action-junit-report • ʢࠓճͷ SARIF ͷ࿩ͱ͸ؔ܎͋Γ·ͤΜ͕ʣ੩తղੳͱڞʹϓϧϦΫͷ CI ΁ಋ ೖ͢Δͱศརͩͱࢥ͍·͢