hardening: isolate third-party paths and clean external-build metadata (#311)

* hardening: isolate third-party paths and clean external-build metadata

* fix: restore external feedback flow and make privacy check portable
This commit is contained in:
KRATOS
2026-04-04 11:52:33 +05:30
committed by GitHub
parent cdbe016e6f
commit 27e6505bfd
18 changed files with 367 additions and 59 deletions

View File

@@ -0,0 +1,63 @@
import { afterEach, beforeEach, describe, expect, mock, test } from 'bun:test'
import axios from 'axios'
const originalEnv = { ...process.env }
async function importFreshModule() {
return import(`./utils.ts?ts=${Date.now()}-${Math.random()}`)
}
beforeEach(() => {
process.env = { ...originalEnv }
})
afterEach(() => {
process.env = { ...originalEnv }
})
describe('checkDomainBlocklist', () => {
test('returns allowed without API call in OpenAI mode', async () => {
process.env.CLAUDE_CODE_USE_OPENAI = '1'
const getSpy = mock(() =>
Promise.resolve({ status: 200, data: { can_fetch: true } }),
)
axios.get = getSpy as typeof axios.get
const { checkDomainBlocklist } = await importFreshModule()
const result = await checkDomainBlocklist('example.com')
expect(result.status).toBe('allowed')
expect(getSpy).not.toHaveBeenCalled()
})
test('returns allowed without API call in Gemini mode', async () => {
process.env.CLAUDE_CODE_USE_GEMINI = '1'
const getSpy = mock(() =>
Promise.resolve({ status: 200, data: { can_fetch: true } }),
)
axios.get = getSpy as typeof axios.get
const { checkDomainBlocklist } = await importFreshModule()
const result = await checkDomainBlocklist('example.com')
expect(result.status).toBe('allowed')
expect(getSpy).not.toHaveBeenCalled()
})
test('calls Anthropic domain check in first-party mode', async () => {
delete process.env.CLAUDE_CODE_USE_OPENAI
delete process.env.CLAUDE_CODE_USE_GEMINI
delete process.env.CLAUDE_CODE_USE_GITHUB
const getSpy = mock(() =>
Promise.resolve({ status: 200, data: { can_fetch: true } }),
)
axios.get = getSpy as typeof axios.get
const { checkDomainBlocklist } = await importFreshModule()
const result = await checkDomainBlocklist('example.com')
expect(result.status).toBe('allowed')
expect(getSpy).toHaveBeenCalledTimes(1)
})
})

View File

@@ -8,6 +8,7 @@ import { queryHaiku } from '../../services/api/claude.js'
import { AbortError } from '../../utils/errors.js'
import { getWebFetchUserAgent } from '../../utils/http.js'
import { logError } from '../../utils/log.js'
import { getAPIProvider } from '../../utils/model/providers.js'
import {
isBinaryContentType,
persistBinaryContent,
@@ -176,6 +177,11 @@ type DomainCheckResult =
export async function checkDomainBlocklist(
domain: string,
): Promise<DomainCheckResult> {
// Third-party providers should not consult Anthropic's domain policy.
if (getAPIProvider() !== 'firstParty') {
return { status: 'allowed' }
}
if (DOMAIN_CHECK_CACHE.has(domain)) {
return { status: 'allowed' }
}