mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
fix(agent-hooks): force C numeric locale on POSIX curl timeouts (#19600)
* fix(agent-hooks): force C numeric locale on POSIX curl timeouts curl parses --connect-timeout/--max-time with locale-sensitive strtod, so comma-decimal locales reject 0.5 and every hook silently falls into the restart spool. Fixes #19578 Co-authored-by: Cursor <cursoragent@cursor.com> * fix(agent-hooks): neutralize LC_ALL before setting LC_NUMERIC=C on POSIX curl Signed-off-by: siddiqui irshad <mohdirshad1306@gmail.com> * style(agent-hooks): format scoped curl commands * test(hooks): expect scoped curl locale in Muse install script --------- Signed-off-by: siddiqui irshad <mohdirshad1306@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Neil <neil@stably.ai>
This commit is contained in:
co-authored by
Cursor
Neil
parent
1e341b6edf
commit
5ce9d58b2d
@@ -1,11 +1,16 @@
|
||||
import type { AgentHookSource } from '../../shared/agent-hook-relay'
|
||||
import { ORCA_HOOK_RAW_JSON_TRANSPORT } from '../../shared/agent-hook-types'
|
||||
|
||||
// Older curl needs C numeric parsing; keep the parent script's UTF-8 locale unchanged.
|
||||
export function posixCurlCommand(curlCommand = 'curl'): string {
|
||||
return `LC_ALL= LC_NUMERIC=C ${curlCommand}`
|
||||
}
|
||||
|
||||
export function buildPosixAgentHookPostCommand(
|
||||
source: AgentHookSource,
|
||||
options: { curlCommand?: string; indent?: string } = {}
|
||||
): string[] {
|
||||
const curlCommand = options.curlCommand ?? 'curl'
|
||||
const curlCommand = posixCurlCommand(options.curlCommand ?? 'curl')
|
||||
const indent = options.indent ?? ' '
|
||||
return [
|
||||
`if [ "\${ORCA_AGENT_HOOK_TRANSPORT:-}" = "${ORCA_HOOK_RAW_JSON_TRANSPORT}" ] && command -v base64 >/dev/null 2>&1 && command -v tr >/dev/null 2>&1; then`,
|
||||
|
||||
@@ -901,6 +901,13 @@ describe('buildPosixAgentHookPostCommand', () => {
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
it('forces C numeric locale on every curl invocation so fractional timeouts parse', () => {
|
||||
const command = buildPosixAgentHookPostCommand('claude').join('\n')
|
||||
expect(command).not.toMatch(/\|\s+curl\b/)
|
||||
const custom = buildPosixAgentHookPostCommand('codex', { curlCommand: '"$curl_bin"' })
|
||||
expect(custom.join('\n')).toContain('| LC_ALL= LC_NUMERIC=C "$curl_bin" -sS')
|
||||
})
|
||||
})
|
||||
|
||||
describe('buildWindowsAgentHookCurlPostCommand', () => {
|
||||
|
||||
@@ -145,6 +145,33 @@ describe('managed hook script refresh', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it.skipIf(process.platform === 'win32')(
|
||||
'refreshes existing POSIX hook and statusline locale handling without a CLI config',
|
||||
async () => {
|
||||
const home = mkdtempSync(join(tmpdir(), 'orca-hook-locale-refresh-'))
|
||||
homedirMock.mockReturnValue(home)
|
||||
try {
|
||||
const hooksDir = join(home, '.orca', 'agent-hooks')
|
||||
mkdirSync(hooksDir, { recursive: true })
|
||||
for (const name of ['claude-hook.sh', 'claude-statusline.sh']) {
|
||||
writeFileSync(join(hooksDir, name), '#!/bin/sh\ncurl --connect-timeout 0.5\n')
|
||||
}
|
||||
await new ClaudeHookService().refreshManagedScripts()
|
||||
for (const name of ['claude-hook.sh', 'claude-statusline.sh']) {
|
||||
const script = readFileSync(join(hooksDir, name), 'utf8')
|
||||
expect(script).toContain('| LC_ALL= LC_NUMERIC=C curl -sS')
|
||||
expect(script).not.toMatch(/\|\s+curl\b/)
|
||||
expect(statSync(join(hooksDir, name)).mode & 0o777).toBe(0o755)
|
||||
}
|
||||
expect(existsSync(join(home, '.claude'))).toBe(false)
|
||||
expect(readdirSync(hooksDir).sort()).toEqual(['claude-hook.sh', 'claude-statusline.sh'])
|
||||
} finally {
|
||||
homedirMock.mockImplementation(() => process.env.HOME ?? tmpdir())
|
||||
rmSync(home, { recursive: true, force: true })
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
it('covers every shared launcher script with a refresher', async () => {
|
||||
const home = mkdtempSync(join(tmpdir(), 'orca-hook-refresh-coverage-'))
|
||||
homedirMock.mockReturnValue(home)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { spawn, spawnSync } from 'node:child_process'
|
||||
import { createServer, type Server, type Socket } from 'node:net'
|
||||
import { chmodSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import { chmodSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import type { SFTPWrapper } from 'ssh2'
|
||||
@@ -205,12 +205,33 @@ describe('managed agent hook timeouts', () => {
|
||||
(process.platform === 'win32' && command.includes('-EncodedCommand'))
|
||||
)
|
||||
expect(carriers).toBeGreaterThan(0)
|
||||
if (process.platform !== 'win32') {
|
||||
assertPosixCurlUsesCNumericLocale(
|
||||
readFileSync(join(homeDir, '.orca', 'agent-hooks', 'droid-hook.sh'), 'utf8'),
|
||||
'droid'
|
||||
)
|
||||
}
|
||||
} finally {
|
||||
homedirMock.mockImplementation(() => process.env.HOME ?? tmpdir())
|
||||
rmSync(homeDir, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
function assertPosixCurlUsesCNumericLocale(content: string, label: string): void {
|
||||
expect(content, `${label} wrapper missing curl transport`).toContain('curl')
|
||||
expect(content, `${label} wrapper missing --connect-timeout`).toContain('--connect-timeout')
|
||||
expect(content, `${label} wrapper missing --max-time`).toContain('--max-time')
|
||||
expect(content, `${label} wrapper missing C numeric locale for curl`).toMatch(
|
||||
/LC_ALL= LC_NUMERIC=C (?:curl|"\$curl_bin")/
|
||||
)
|
||||
expect(content, `${label} wrapper posts curl without C numeric locale`).not.toMatch(
|
||||
/\|\s+curl\b/
|
||||
)
|
||||
expect(content, `${label} wrapper posts curl_bin without C numeric locale`).not.toMatch(
|
||||
/\|\s+"\$curl_bin"/
|
||||
)
|
||||
}
|
||||
|
||||
it.skipIf(process.platform === 'win32')(
|
||||
'passes timeout budgets to curl from every generated POSIX wrapper',
|
||||
async () => {
|
||||
@@ -232,6 +253,7 @@ describe('managed agent hook timeouts', () => {
|
||||
if (!path.endsWith('.sh')) {
|
||||
continue
|
||||
}
|
||||
assertPosixCurlUsesCNumericLocale(content, `${agent} ${path}`)
|
||||
rmSync(capturePath, { force: true })
|
||||
const result = spawnSync(
|
||||
'/bin/sh',
|
||||
@@ -279,6 +301,76 @@ describe('managed agent hook timeouts', () => {
|
||||
}
|
||||
)
|
||||
|
||||
describe('comma-decimal curl locale', () => {
|
||||
let tempDir: string | null = null
|
||||
|
||||
afterEach(() => {
|
||||
if (tempDir) {
|
||||
rmSync(tempDir, { recursive: true, force: true })
|
||||
tempDir = null
|
||||
}
|
||||
})
|
||||
|
||||
it.skipIf(process.platform === 'win32')(
|
||||
'clears inherited LC_ALL and sets LC_NUMERIC only for curl',
|
||||
async () => {
|
||||
const { sftp, fs } = createFakeSftp()
|
||||
await new GeminiHookService().installRemote(sftp, REMOTE_HOME)
|
||||
const wrapperBody = fs.files.get(`${REMOTE_HOME}/.orca/agent-hooks/gemini-hook.sh`)!
|
||||
|
||||
tempDir = mkdtempSync(join(tmpdir(), 'orca-hook-lc-numeric-'))
|
||||
const binDir = join(tempDir, 'bin')
|
||||
mkdirSync(binDir)
|
||||
const observed = join(tempDir, 'lc-numeric')
|
||||
writeFileSync(
|
||||
join(binDir, 'curl'),
|
||||
`#!/bin/sh\nprintf '%s|%s' "$LC_ALL" "$LC_NUMERIC" > "${observed}"\nexit 0\n`
|
||||
)
|
||||
chmodSync(join(binDir, 'curl'), 0o755)
|
||||
const scriptPath = join(tempDir, 'gemini-hook.sh')
|
||||
writeFileSync(scriptPath, wrapperBody, 'utf8')
|
||||
chmodSync(scriptPath, 0o755)
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const child = spawn('sh', [scriptPath], {
|
||||
env: {
|
||||
...process.env,
|
||||
PATH: `${binDir}:${process.env.PATH ?? ''}`,
|
||||
LC_ALL: 'de_DE.UTF-8',
|
||||
LC_NUMERIC: 'de_DE.UTF-8',
|
||||
ORCA_AGENT_HOOK_ENDPOINT: '',
|
||||
ORCA_AGENT_HOOK_PORT: '9',
|
||||
ORCA_AGENT_HOOK_TOKEN: 'test-token',
|
||||
ORCA_PANE_KEY: 'pane-1',
|
||||
ORCA_TAB_ID: 'tab-1',
|
||||
ORCA_WORKTREE_ID: 'wt-1'
|
||||
},
|
||||
stdio: ['pipe', 'ignore', 'ignore']
|
||||
})
|
||||
const timeout = setTimeout(() => {
|
||||
child.kill('SIGKILL')
|
||||
reject(new Error('hook script exceeded test timeout'))
|
||||
}, 10_000)
|
||||
child.on('error', (error) => {
|
||||
clearTimeout(timeout)
|
||||
reject(error)
|
||||
})
|
||||
child.on('close', (status) => {
|
||||
clearTimeout(timeout)
|
||||
if (status === 0) {
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
reject(new Error(`hook script exited ${String(status)}`))
|
||||
})
|
||||
child.stdin.end('{"hook_event_name":"Stop"}')
|
||||
})
|
||||
|
||||
expect(readFileSync(observed, 'utf8')).toBe('|C')
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
describe('dead-endpoint transport budget', () => {
|
||||
let tempDir: string | null = null
|
||||
let server: Server | null = null
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { posixCurlCommand } from '../agent-hooks/hook-post-command'
|
||||
import {
|
||||
buildPosixHookPayloadCapture,
|
||||
POSIX_HOOK_JSON_STDIN,
|
||||
@@ -56,7 +57,7 @@ export function getManagedScript(
|
||||
' exit 0',
|
||||
'fi',
|
||||
// Keep large payloads off command lines to avoid EDR false positives.
|
||||
'printf \'%s\' "$payload" | curl -sS -X POST "http://127.0.0.1:${ORCA_AGENT_HOOK_PORT}/hook/antigravity" \\',
|
||||
`printf '%s' "$payload" | ${posixCurlCommand()} -sS -X POST "http://127.0.0.1:\${ORCA_AGENT_HOOK_PORT}/hook/antigravity" \\`,
|
||||
' --connect-timeout 0.5 --max-time 1.5 \\',
|
||||
' -H "Content-Type: application/x-www-form-urlencoded" \\',
|
||||
' -H "X-Orca-Agent-Hook-Token: ${ORCA_AGENT_HOOK_TOKEN}" \\',
|
||||
|
||||
@@ -113,7 +113,7 @@ describe('AntigravityHookService', () => {
|
||||
expect(script).toContain(`payload=$(${POSIX_HOOK_JSON_STDIN_READER})`)
|
||||
expect(script).toContain("payload='{}'")
|
||||
expect(script).not.toContain('if [ -z "$payload" ]; then\n exit 0\nfi')
|
||||
expect(script).toContain('printf \'%s\' "$payload" | curl')
|
||||
expect(script).toContain('printf \'%s\' "$payload" | LC_ALL= LC_NUMERIC=C curl')
|
||||
expect(script).toContain('--data-urlencode "payload@-"')
|
||||
expect(script).not.toContain('--data-urlencode "payload=${payload}"')
|
||||
}
|
||||
|
||||
@@ -724,7 +724,7 @@ describe('ClaudeHookService.installRemote', () => {
|
||||
expect(script!.indexOf('printf "{}\\n"')).toBe(
|
||||
script!.indexOf('#!/bin/sh') + '#!/bin/sh\n'.length
|
||||
)
|
||||
expect(script).toContain('printf \'%s\' "$payload" | curl')
|
||||
expect(script).toContain('printf \'%s\' "$payload" | LC_ALL= LC_NUMERIC=C curl')
|
||||
expect(script).toContain('-H "Content-Type: application/json"')
|
||||
expect(script).toContain('orca_hook_metadata=$(printf')
|
||||
expect(script).toContain('unset ORCA_AGENT_HOOK_TRANSPORT')
|
||||
|
||||
@@ -29,6 +29,8 @@ describe('getManagedStatusLineScript (posix)', () => {
|
||||
expect(endpointIndex).toBeLessThan(curlIndex)
|
||||
expect(script).toContain('/statusline/claude')
|
||||
expect(script).toContain('--data-urlencode "payload@-"')
|
||||
expect(script).toContain('| LC_ALL= LC_NUMERIC=C curl -sS')
|
||||
expect(script).not.toMatch(/\|\s+curl\b/)
|
||||
})
|
||||
|
||||
it('returns the posix script even on win32 when targeting a remote', () => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { posixCurlCommand } from '../agent-hooks/hook-post-command'
|
||||
import {
|
||||
buildWindowsHookStdinDrainEpilogue,
|
||||
WINDOWS_HOOK_STDIN_DRAIN_LABEL,
|
||||
@@ -161,7 +162,7 @@ export function getManagedStatusLineScript(target: 'local' | 'posix' = 'local'):
|
||||
'if [ -n "$orca_statusline_now" ]; then',
|
||||
' printf \'%s\' "$orca_statusline_now" >"$orca_statusline_stamp" 2>/dev/null || :',
|
||||
'fi',
|
||||
`printf '%s' "$payload" | curl -sS -X POST "http://127.0.0.1:\${ORCA_AGENT_HOOK_PORT}${CLAUDE_STATUSLINE_PATHNAME}" \\`,
|
||||
`printf '%s' "$payload" | ${posixCurlCommand()} -sS -X POST "http://127.0.0.1:\${ORCA_AGENT_HOOK_PORT}${CLAUDE_STATUSLINE_PATHNAME}" \\`,
|
||||
' --connect-timeout 0.5 --max-time 1.5 \\',
|
||||
' -H "Content-Type: application/x-www-form-urlencoded" \\',
|
||||
' -H "X-Orca-Agent-Hook-Token: ${ORCA_AGENT_HOOK_TOKEN}" \\',
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { posixCurlCommand } from '../agent-hooks/hook-post-command'
|
||||
import { buildWindowsAgentHookPostCommand } from '../agent-hooks/installer-utils'
|
||||
import {
|
||||
buildPosixHookPayloadCapture,
|
||||
@@ -122,7 +123,7 @@ export function buildCommandCodeManagedScript(
|
||||
' exit 0',
|
||||
'fi',
|
||||
// Bound stalled posts and pipe large payloads through stdin to avoid EDR command-line false positives.
|
||||
'printf \'%s\' "$payload" | curl -sS -X POST "http://127.0.0.1:${ORCA_AGENT_HOOK_PORT}/hook/command-code" \\',
|
||||
`printf '%s' "$payload" | ${posixCurlCommand()} -sS -X POST "http://127.0.0.1:\${ORCA_AGENT_HOOK_PORT}/hook/command-code" \\`,
|
||||
' --connect-timeout 0.5 --max-time 1.5 \\',
|
||||
' -H "Content-Type: application/x-www-form-urlencoded" \\',
|
||||
' -H "X-Orca-Agent-Hook-Token: ${ORCA_AGENT_HOOK_TOKEN}" \\',
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { posixCurlCommand } from '../agent-hooks/hook-post-command'
|
||||
import {
|
||||
buildWindowsAgentHookPostCommand,
|
||||
getSharedManagedScriptPath
|
||||
@@ -52,7 +53,7 @@ export function getManagedScript(target: 'local' | 'posix' = 'local'): string {
|
||||
' exit 0',
|
||||
'fi',
|
||||
// Keep large tool payloads off curl's command line to avoid EDR false positives.
|
||||
'printf \'%s\' "$payload" | curl -sS -X POST "http://127.0.0.1:${ORCA_AGENT_HOOK_PORT}/hook/copilot" \\',
|
||||
`printf '%s' "$payload" | ${posixCurlCommand()} -sS -X POST "http://127.0.0.1:\${ORCA_AGENT_HOOK_PORT}/hook/copilot" \\`,
|
||||
' --connect-timeout 0.5 --max-time 1.5 \\',
|
||||
' -H "Content-Type: application/x-www-form-urlencoded" \\',
|
||||
' -H "X-Orca-Agent-Hook-Token: ${ORCA_AGENT_HOOK_TOKEN}" \\',
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
buildWindowsHookPowerShellCommand,
|
||||
wrapWindowsPowerShellEncodedCommand
|
||||
} from '../agent-hooks/installer-utils'
|
||||
import { posixCurlCommand } from '../agent-hooks/hook-post-command'
|
||||
import {
|
||||
buildPosixHookPayloadCapture,
|
||||
buildPosixHookSpoolLines,
|
||||
@@ -83,7 +84,7 @@ export function getManagedScript(target: 'local' | 'posix' = 'local'): string {
|
||||
' exit 0',
|
||||
'fi',
|
||||
// Form encoding handles path-bearing IDs; stdin keeps large payloads off the command line.
|
||||
'printf \'%s\' "$payload" | curl -sS -X POST "http://127.0.0.1:${ORCA_AGENT_HOOK_PORT}/hook/cursor" \\',
|
||||
`printf '%s' "$payload" | ${posixCurlCommand()} -sS -X POST "http://127.0.0.1:\${ORCA_AGENT_HOOK_PORT}/hook/cursor" \\`,
|
||||
' --connect-timeout 0.5 --max-time 1.5 \\',
|
||||
' -H "Content-Type: application/x-www-form-urlencoded" \\',
|
||||
' -H "X-Orca-Agent-Hook-Token: ${ORCA_AGENT_HOOK_TOKEN}" \\',
|
||||
|
||||
@@ -135,7 +135,7 @@ describe('CursorHookService', () => {
|
||||
} else {
|
||||
// Stdin avoids oversized curl command lines that trigger EDR.
|
||||
expect(script).toContain(`payload=$(${POSIX_HOOK_STDIN_READER})`)
|
||||
expect(script).toContain('printf \'%s\' "$payload" | curl')
|
||||
expect(script).toContain('printf \'%s\' "$payload" | LC_ALL= LC_NUMERIC=C curl')
|
||||
expect(script).toContain('--data-urlencode "payload@-"')
|
||||
expect(script).not.toContain('--data-urlencode "payload=${payload}"')
|
||||
}
|
||||
|
||||
@@ -67,9 +67,11 @@ describe('DevinHookService', () => {
|
||||
const script = readFileSync(getDevinManagedScriptPath(), 'utf8')
|
||||
expect(script).toContain('/hook/devin')
|
||||
// stdin keeps large payloads off the command line to avoid EDR false positives.
|
||||
expect(script).toContain('printf \'%s\' "$payload" | curl')
|
||||
expect(script).toContain('--data-urlencode "payload@-"')
|
||||
expect(script).not.toContain('--data-urlencode "payload=${payload}"')
|
||||
if (process.platform !== 'win32') {
|
||||
expect(script).toContain('printf \'%s\' "$payload" | LC_ALL= LC_NUMERIC=C curl')
|
||||
}
|
||||
})
|
||||
|
||||
it('preserves unrelated keys in Devin config when installing hooks', () => {
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
buildWindowsHookEnvironmentGuardLines,
|
||||
buildWindowsHookStdinDrainEpilogue
|
||||
} from '../agent-hooks/hook-stdin-contract'
|
||||
import { posixCurlCommand } from '../agent-hooks/hook-post-command'
|
||||
import {
|
||||
applyDevinManagedHooks,
|
||||
DEVIN_EVENTS,
|
||||
@@ -68,7 +69,7 @@ function getManagedScript(target: 'local' | 'posix' = 'local'): string {
|
||||
'fi',
|
||||
// Form encoding handles filesystem paths containing quotes or newlines.
|
||||
// stdin keeps large payloads off the command line to avoid EDR false positives.
|
||||
'printf \'%s\' "$payload" | curl -sS -X POST "http://127.0.0.1:${ORCA_AGENT_HOOK_PORT}/hook/devin" \\',
|
||||
`printf '%s' "$payload" | ${posixCurlCommand()} -sS -X POST "http://127.0.0.1:\${ORCA_AGENT_HOOK_PORT}/hook/devin" \\`,
|
||||
' --connect-timeout 0.5 --max-time 1.5 \\',
|
||||
' -H "Content-Type: application/x-www-form-urlencoded" \\',
|
||||
' -H "X-Orca-Agent-Hook-Token: ${ORCA_AGENT_HOOK_TOKEN}" \\',
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
buildWindowsHookEnvironmentGuardLines,
|
||||
buildWindowsHookStdinDrainEpilogue
|
||||
} from '../agent-hooks/hook-stdin-contract'
|
||||
import { posixCurlCommand } from '../agent-hooks/hook-post-command'
|
||||
|
||||
// SessionStart clears prompt/tool caches on resume before the next user prompt.
|
||||
const DROID_EVENTS = [
|
||||
@@ -97,7 +98,7 @@ function getManagedScript(target: 'local' | 'posix' = 'local'): string {
|
||||
' exit 0',
|
||||
'fi',
|
||||
// Bound stalled posts and keep large payloads on stdin to avoid EDR command-line alerts.
|
||||
'printf \'%s\' "$payload" | curl -sS -X POST "http://127.0.0.1:${ORCA_AGENT_HOOK_PORT}/hook/droid" \\',
|
||||
`printf '%s' "$payload" | ${posixCurlCommand()} -sS -X POST "http://127.0.0.1:\${ORCA_AGENT_HOOK_PORT}/hook/droid" \\`,
|
||||
' --connect-timeout 0.5 --max-time 1.5 \\',
|
||||
' -H "Content-Type: application/x-www-form-urlencoded" \\',
|
||||
' -H "X-Orca-Agent-Hook-Token: ${ORCA_AGENT_HOOK_TOKEN}" \\',
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
buildWindowsHookEnvironmentGuardLines,
|
||||
buildWindowsHookStdinDrainEpilogue
|
||||
} from '../agent-hooks/hook-stdin-contract'
|
||||
import { posixCurlCommand } from '../agent-hooks/hook-post-command'
|
||||
|
||||
// Gemini has no permission-prompt hook, so approvals cannot produce an Orca waiting state.
|
||||
// Gemini uses BeforeTool; remove stale Claude-style PreToolUse registrations below.
|
||||
@@ -83,7 +84,7 @@ function getManagedScript(target: 'local' | 'posix' = 'local'): string {
|
||||
' exit 0',
|
||||
'fi',
|
||||
// Form encoding handles quotes/newlines in paths; stdin keeps large payloads off the command line.
|
||||
'printf \'%s\' "$payload" | curl -sS -X POST "http://127.0.0.1:${ORCA_AGENT_HOOK_PORT}/hook/gemini" \\',
|
||||
`printf '%s' "$payload" | ${posixCurlCommand()} -sS -X POST "http://127.0.0.1:\${ORCA_AGENT_HOOK_PORT}/hook/gemini" \\`,
|
||||
' --connect-timeout 0.5 --max-time 1.5 \\',
|
||||
' -H "Content-Type: application/x-www-form-urlencoded" \\',
|
||||
' -H "X-Orca-Agent-Hook-Token: ${ORCA_AGENT_HOOK_TOKEN}" \\',
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { posixCurlCommand } from '../agent-hooks/hook-post-command'
|
||||
import { getSharedManagedScriptPath, wrapPosixHookCommand } from '../agent-hooks/installer-utils'
|
||||
import { wrapWindowsBatchHookCommand } from '../agent-hooks/windows-direct-cmd-hook-command'
|
||||
import {
|
||||
@@ -45,7 +46,7 @@ export function getGrokManagedScript(target: 'local' | 'posix' = 'local'): strin
|
||||
`if [ -n "\${GROK_HOME:-}" ] && [ "\${#GROK_HOME}" -le ${GROK_HOME_ENVELOPE_MAX_LENGTH} ]; then`,
|
||||
' grok_home=$GROK_HOME',
|
||||
'fi',
|
||||
'printf \'%s\' "$payload" | curl -sS -X POST "http://127.0.0.1:${ORCA_AGENT_HOOK_PORT}/hook/grok" \\',
|
||||
`printf '%s' "$payload" | ${posixCurlCommand()} -sS -X POST "http://127.0.0.1:\${ORCA_AGENT_HOOK_PORT}/hook/grok" \\`,
|
||||
' --connect-timeout 0.5 --max-time 1.5 \\',
|
||||
' -H "Content-Type: application/x-www-form-urlencoded" \\',
|
||||
' -H "X-Orca-Agent-Hook-Token: ${ORCA_AGENT_HOOK_TOKEN}" \\',
|
||||
|
||||
@@ -294,7 +294,7 @@ describe('GrokHookService', () => {
|
||||
script.indexOf(`payload=$(${POSIX_HOOK_JSON_STDIN_READER})`)
|
||||
)
|
||||
expect(script).toContain(`payload=$(${POSIX_HOOK_JSON_STDIN_READER})`)
|
||||
expect(script).toContain('printf \'%s\' "$payload" | curl')
|
||||
expect(script).toContain('printf \'%s\' "$payload" | LC_ALL= LC_NUMERIC=C curl')
|
||||
expect(script).toContain('--data-urlencode "payload@-"')
|
||||
expect(script).toContain('${#GROK_HOME}" -le 4096')
|
||||
expect(script).toContain('--data-urlencode "grokHome=${grok_home}"')
|
||||
|
||||
@@ -128,7 +128,7 @@ describe('KimiHookService', () => {
|
||||
const script = readFileSync(scriptPath(), 'utf-8')
|
||||
expect(script).toContain('/hook/kimi')
|
||||
// Keep large payloads off curl's command line to avoid EDR false positives.
|
||||
expect(script).toContain('printf \'%s\' "$payload" | curl')
|
||||
expect(script).toContain('printf \'%s\' "$payload" | LC_ALL= LC_NUMERIC=C curl')
|
||||
expect(script).toContain('--data-urlencode "payload@-"')
|
||||
expect(script).not.toContain('--data-urlencode "payload=${payload}"')
|
||||
expect(config).toContain('agent-hooks/kimi-hook.sh')
|
||||
|
||||
@@ -35,6 +35,7 @@ import {
|
||||
buildWindowsHookEnvironmentGuardLines,
|
||||
buildWindowsHookStdinDrainEpilogue
|
||||
} from '../agent-hooks/hook-stdin-contract'
|
||||
import { posixCurlCommand } from '../agent-hooks/hook-post-command'
|
||||
import {
|
||||
applyManagedKimiHooks,
|
||||
KIMI_HOOK_EVENTS,
|
||||
@@ -98,7 +99,7 @@ function getManagedScript(target: 'local' | 'posix' = 'local'): string {
|
||||
' exit 0',
|
||||
'fi',
|
||||
// Form fields preserve arbitrary path text; stdin keeps large payloads off curl's command line for EDR.
|
||||
'printf \'%s\' "$payload" | curl -sS -X POST "http://127.0.0.1:${ORCA_AGENT_HOOK_PORT}/hook/kimi" \\',
|
||||
`printf '%s' "$payload" | ${posixCurlCommand()} -sS -X POST "http://127.0.0.1:\${ORCA_AGENT_HOOK_PORT}/hook/kimi" \\`,
|
||||
' --connect-timeout 0.5 --max-time 1.5 \\',
|
||||
' -H "Content-Type: application/x-www-form-urlencoded" \\',
|
||||
' -H "X-Orca-Agent-Hook-Token: ${ORCA_AGENT_HOOK_TOKEN}" \\',
|
||||
|
||||
@@ -76,7 +76,9 @@ describe('MuseHookService', () => {
|
||||
expect(script).toContain('/hook/muse')
|
||||
// Stdin payloads avoid oversized command-line EDR signals.
|
||||
expect(script).toContain(
|
||||
process.platform === 'win32' ? 'payload@-' : 'printf \'%s\' "$payload" | curl'
|
||||
process.platform === 'win32'
|
||||
? 'payload@-'
|
||||
: 'printf \'%s\' "$payload" | LC_ALL= LC_NUMERIC=C curl'
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user