Skip to main content
All posts
DevSecOps・コード監査

自社コードの脆弱性監査で「攻撃者扱い」されないために:bf16.ai で構築するゼロ拒否 DevSecOps パイプライン

SQLi や SSRF の回帰テスト生成中に発生する content_filter 途中切断を解消。bf16.ai のゼロ保持(ZDR)2 段階構成で、セキュリティ修正の自動トリアージパイプラインを構築します。

TL;DR · AppSec エンジニアリング要点

  • 防御側のジレンマ:一般的な閉鎖型 API は自社リポジトリ向けの SQLi / SSRF 回帰テスト生成を攻撃コードと誤認し、正当なトリアージのストリームを content_filter で途中切断します。
  • bf16.ai の 2 段階トリアージ:Pass 1 で deepseek/deepseek-v4.1-flash-abliterated($0.30/$0.05/$1.20)が静的解析の誤検知を高速除外し、Pass 2 で zai-org/glm-5.3-abliterated($1.40/$0.30/$4.40)が厳密な JSON 回帰テストと修正パッチを生成します。
  • ゼロプロンプト保持(ZDR):プロプライエタリな差分を一切ディスク保存せず、料金も公式ベンダー API と同水準です。

1. なぜ出力セーフガードが防御的 SAST パイプラインを途中で切断するのか

Semgrep や CodeQL の生アラートの多くは到達不能な誤検知です。LLM で Source-to-Sink 到達性を判定し Vitest の再現テストとパラメータ化パッチを自動生成しようとしても、従来の API ではテストベクター内のエスケープ文字列に反応して 64 トークン目でストリームが強制切断され、CI が破損します:

[ci:sast-triage] Alert #418 -> semgrep.javascript.express.db.sequelize-raw-sql
[ci:sast-triage] Requesting source-to-sink reachability + Vitest regression test...
[upstream:frontier-api] HTTP 200 (stream truncated at token 64)
  finish_reason: "content_filter"
  error: "Output halted by automated cyber-risk safeguard: response appeared to construct a SQL injection proof-of-concept payload."
[ci:sast-triage] ERROR: Unexpected EOF in JSON stream. PR #892 security check marked INCONCLUSIVE.

2. bf16.ai による 2 パス構成(ゼロ保持 ZDR + 厳密 JSON スキーマ)

bf16.ai では 1M コンテキストの Abliterated モデルを 2 段階で使い分けられます:

  1. Pass 1 ノイズ除去(deepseek/deepseek-v4.1-flash-abliterated):Zod バリデータ等で保護済みの誤検知を高速に除外。
  2. Pass 2 再現テスト&パッチ生成(zai-org/glm-5.3-abliterated Flagship):strict: true の JSON スキーマで到達経路・Vitest コード・Unified Diff を欠損なく出力します。

DevSecOps 修復ループ:PR 差分を bf16.ai の ZDR エンドポイントで解析し、回帰テストと修正パッチを自動検証。

▲ DevSecOps 修復ループ:PR 差分を bf16.ai の ZDR エンドポイントで解析し、回帰テストと修正パッチを自動検証。

3. TypeScript トリアージ実装と GitHub Actions ワークフロー

直交重み Abliteration により JSON 文法状態機械が完全に維持されるため、複雑なエスケープを含むテストコードも初回から確実にパースできます:

import OpenAI from 'openai';

const bf16 = new OpenAI({
  baseURL: 'https://api.bf16.ai/v1',
  apiKey: process.env.BF16_SEC_AUDIT_KEY,
});

export async function auditDiffAndEmitPatch(gitDiff: string, routeContext: string) {
  // Pass 2 Deep Remediation on GLM-5.3 Flagship (Abliterated)
  const response = await bf16.chat.completions.create({
    model: 'zai-org/glm-5.3-abliterated',
    temperature: 0.1,
    response_format: {
      type: 'json_schema',
      json_schema: {
        name: 'sast_remediation_bundle',
        strict: true,
        schema: {
          type: 'object',
          additionalProperties: false,
          required: ['exploitable', 'sink_trace', 'vitest_regression_spec', 'unified_patch'],
          properties: {
            exploitable: { type: 'boolean' },
            sink_trace: { type: 'string' },
            vitest_regression_spec: { type: 'string' },
            unified_patch: { type: 'string' },
          },
        },
      },
    },
    messages: [
      {
        role: 'system',
        content:
          'You are an application security remediation engine auditing first-party repository code. ' +
          'Determine whether user-controlled input reaches the sink unparameterized. If exploitable, ' +
          'emit a local Vitest regression test and a minimal unified diff fixing the sink.',
      },
      { role: 'user', content: `## Route Context\n${routeContext}\n\n## PR Diff\n${gitDiff}` },
    ],
  });

  return JSON.parse(response.choices[0]?.message?.content ?? '{}');
}

GitHub Actions に組み込めば PR ごとに自動検証が回ります。bf16.ai/pricing の通り、月額固定費なしの完全従量課金で公式ベンダー標準価格と同等です:

# .github/workflows/bf16-sast-remediation.yml
name: PR Security Triage (bf16.ai ZDR)
on: [pull_request]

jobs:
  sast_verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Run Semgrep & Triage Reachable Sinks via bf16.ai
        env:
          BF16_SEC_AUDIT_KEY: ${{ secrets.BF16_SEC_AUDIT_KEY }}
        run: |
          semgrep scan --config auto --json > semgrep.json
          node scripts/sec-triage-bf16.mjs semgrep.json
          pnpm vitest run tests/security-regressions

4. パイプライン比較と PR 単価

Pass 1 を deepseek-v4.1-flash-abliterated、Pass 2 を zai-org/glm-5.3-abliterated に振り分ければ、大半のアラートにはフラッグシップの単価がかかりません。到達不能な検出は入力 $0.30 / 1M の段階で破棄され、到達可能と確認されたシンク(SQLi、SSRF、パストラバーサル、JWT の alg 混同、Webhook HMAC のタイミングバグ)だけが入力 $1.40 / 1M・出力 $4.40 / 1M で課金されます。PR あたりのコストとパッチ通過率は、いずれも自社リポジトリで計測してから判断してください:

SAST トリアージ構成各アラートの扱い
Semgrep 静的ルール単体到達可否にかかわらず、すべてのアラートが手動トリアージと手作業の修正待ちになる
Semgrep + 強フィルタ閉鎖型 APIcontent_filter でトリアージが途中で止まり、途切れた JSON と判定不能なチェックが残ることがある
Semgrep + bf16.ai (2 パス構成)到達可能なシンクには到達経路・Vitest 回帰テスト・パッチを生成。パッチはレビュー前に CI 通過が必須

5. 自動セキュリティ監査における 4 つの運用原則

  1. 自社所有または書面で許可されたリポジトリのみを対象とすること。
  2. 生成された回帰テストは使い捨てコンテナ(Testcontainers)内でのみ実行すること。
  3. パッチの自動マージは行わず、テスト通過後に人間が PR レビューで承認すること。
  4. CI 専用の sk-bf16-v1- キーを発行し日次予算上限を設定すること。