@zaip-ai/cli 4.1.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +3 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/services/adapter-hook-sources.d.ts +1 -0
- package/dist/services/adapter-hook-sources.d.ts.map +1 -1
- package/dist/services/adapter-hook-sources.js +1 -0
- package/dist/services/adapter-hook-sources.js.map +1 -1
- package/dist/services/adapters.d.ts +2 -2
- package/dist/services/adapters.d.ts.map +1 -1
- package/dist/services/adapters.js +14 -73
- package/dist/services/adapters.js.map +1 -1
- package/dist/services/adapters.test.js +1 -0
- package/dist/services/adapters.test.js.map +1 -1
- package/dist/services/agent-adapters.d.ts.map +1 -1
- package/dist/services/agent-adapters.js +3 -7
- package/dist/services/agent-adapters.js.map +1 -1
- package/dist/services/agent-adapters.test.js +43 -11
- package/dist/services/agent-adapters.test.js.map +1 -1
- package/dist/services/codex-config-template.js +2 -2
- package/dist/services/codex-conversation-lifecycle-hook.d.ts.map +1 -1
- package/dist/services/codex-conversation-lifecycle-hook.js +38 -14
- package/dist/services/codex-conversation-lifecycle-hook.js.map +1 -1
- package/dist/services/codex-hook-activation.d.ts +4 -0
- package/dist/services/codex-hook-activation.d.ts.map +1 -0
- package/dist/services/codex-hook-activation.js +64 -0
- package/dist/services/codex-hook-activation.js.map +1 -0
- package/dist/services/codex-model-policy.d.ts +4 -0
- package/dist/services/codex-model-policy.d.ts.map +1 -0
- package/dist/services/codex-model-policy.js +24 -0
- package/dist/services/codex-model-policy.js.map +1 -0
- package/dist/services/codex-native-tool-authority-template.d.ts +2 -0
- package/dist/services/codex-native-tool-authority-template.d.ts.map +1 -0
- package/dist/services/codex-native-tool-authority-template.js +89 -0
- package/dist/services/codex-native-tool-authority-template.js.map +1 -0
- package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.js +68 -126
- package/dist/services/codex-pre-tool-hook-template.js.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.test.js +262 -1
- package/dist/services/codex-pre-tool-hook-template.test.js.map +1 -1
- package/dist/services/codex-pre-tool-support-template.d.ts +2 -0
- package/dist/services/codex-pre-tool-support-template.d.ts.map +1 -0
- package/dist/services/codex-pre-tool-support-template.js +401 -0
- package/dist/services/codex-pre-tool-support-template.js.map +1 -0
- package/dist/services/codex-subagent-hook-template.d.ts +1 -1
- package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
- package/dist/services/codex-subagent-hook-template.js +46 -10
- package/dist/services/codex-subagent-hook-template.js.map +1 -1
- package/dist/services/codex-validation-runtime-template.d.ts +3 -0
- package/dist/services/codex-validation-runtime-template.d.ts.map +1 -0
- package/dist/services/codex-validation-runtime-template.js +18 -0
- package/dist/services/codex-validation-runtime-template.js.map +1 -0
- package/dist/services/codex-windows-hook-command.d.ts.map +1 -1
- package/dist/services/codex-windows-hook-command.js +4 -2
- package/dist/services/codex-windows-hook-command.js.map +1 -1
- package/dist/services/codex-windows-hook-command.test.js +22 -0
- package/dist/services/codex-windows-hook-command.test.js.map +1 -1
- package/dist/services/developer-identity-fixture.d.ts +3 -0
- package/dist/services/developer-identity-fixture.d.ts.map +1 -0
- package/dist/services/developer-identity-fixture.js +17 -0
- package/dist/services/developer-identity-fixture.js.map +1 -0
- package/dist/services/global-codex-config-fixtures.d.ts +12 -0
- package/dist/services/global-codex-config-fixtures.d.ts.map +1 -0
- package/dist/services/global-codex-config-fixtures.js +38 -0
- package/dist/services/global-codex-config-fixtures.js.map +1 -0
- package/dist/services/global-codex-config-migration.test.d.ts +2 -0
- package/dist/services/global-codex-config-migration.test.d.ts.map +1 -0
- package/dist/services/global-codex-config-migration.test.js +301 -0
- package/dist/services/global-codex-config-migration.test.js.map +1 -0
- package/dist/services/global-codex-config-transaction.d.ts +15 -0
- package/dist/services/global-codex-config-transaction.d.ts.map +1 -0
- package/dist/services/global-codex-config-transaction.js +89 -0
- package/dist/services/global-codex-config-transaction.js.map +1 -0
- package/dist/services/global-codex-config-transaction.test.d.ts +2 -0
- package/dist/services/global-codex-config-transaction.test.d.ts.map +1 -0
- package/dist/services/global-codex-config-transaction.test.js +145 -0
- package/dist/services/global-codex-config-transaction.test.js.map +1 -0
- package/dist/services/global-codex-config.d.ts +10 -11
- package/dist/services/global-codex-config.d.ts.map +1 -1
- package/dist/services/global-codex-config.js +226 -108
- package/dist/services/global-codex-config.js.map +1 -1
- package/dist/services/global-codex-config.test.js +6 -6
- package/dist/services/global-codex-config.test.js.map +1 -1
- package/dist/services/hook-readiness.d.ts +7 -0
- package/dist/services/hook-readiness.d.ts.map +1 -0
- package/dist/services/hook-readiness.js +17 -0
- package/dist/services/hook-readiness.js.map +1 -0
- package/dist/services/logger.d.ts +2 -0
- package/dist/services/logger.d.ts.map +1 -1
- package/dist/services/logger.js +15 -1
- package/dist/services/logger.js.map +1 -1
- package/dist/services/logger.test.js +3 -0
- package/dist/services/logger.test.js.map +1 -1
- package/dist/services/managed-adapter.d.ts +6 -0
- package/dist/services/managed-adapter.d.ts.map +1 -0
- package/dist/services/managed-adapter.js +63 -0
- package/dist/services/managed-adapter.js.map +1 -0
- package/dist/services/runtime-template.test.js +3 -0
- package/dist/services/runtime-template.test.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/templates/.agents/README.md +8 -0
- package/templates/.agents/config/agents/discovery.json +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-brand-strategist.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-cloud-engineer.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-data-analyst.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-general-operations.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-governance-compliance.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-growth-strategist.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-marketing-analyst.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-refactoring-specialist.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-sales-specialist.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-task-executor.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-website-developer.toml +1 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-writer.toml +1 -2
- package/templates/.agents/dashboard/.zaip-managed.json +40 -32
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-DlN5EMmD.js → DashboardHelpDialog-CkQ_y8kg.js} +60 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{ProjectSettingsPage-BRdoeTWk.js → ProjectSettingsPage-doIMhei7.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-B_5u4Xnp.js → TraceabilityWorkspace-C_4ftjyB.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{index-C4rLXrz_.js → index-Rbmpz4UO.js} +2 -2
- package/templates/.agents/dashboard/apps/frontend/dist/index.html +1 -1
- package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
- package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
- package/templates/.agents/dashboard/modules/operations/package.json +1 -1
- package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
- package/templates/.agents/dashboard/packages/branding/package.json +1 -1
- package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
- package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +176 -176
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +135 -135
- package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/server.mjs +176 -176
- package/templates/.agents/dashboard/packages/local-runtime/src/server-operation-detail.test.ts +106 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +0 -13
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-counts-every-root-execution-day-returns.test.ts +17 -230
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-counts-fixture.test-support.ts +239 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.test.mjs +28 -8
- package/templates/.agents/dashboard/packages/ui/package.json +1 -1
- package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
- package/templates/.agents/design/.zaip-managed.json +3 -3
- package/templates/.agents/design/apps/catalog/package.json +1 -1
- package/templates/.agents/design/packages/local-runtime/package.json +1 -1
- package/templates/.agents/requirements/autonomous-assurance.md +1 -1
- package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
- package/templates/.agents/requirements/comparative-audit.md +1 -1
- package/templates/.agents/requirements/context-engine.md +1 -1
- package/templates/.agents/requirements/cost-observability.md +1 -1
- package/templates/.agents/requirements/dashboard-launch.md +1 -1
- package/templates/.agents/requirements/data-export.md +1 -1
- package/templates/.agents/requirements/design-system.md +1 -1
- package/templates/.agents/requirements/execution-engine.md +1 -1
- package/templates/.agents/requirements/kanban-dashboard.md +1 -1
- package/templates/.agents/requirements/model-orchestration.md +1 -1
- package/templates/.agents/requirements/public-distribution.md +1 -1
- package/templates/.agents/requirements/software-architecture.md +1 -1
- package/templates/.agents/requirements/strategic-improvements.md +1 -1
- package/templates/.agents/requirements/work-lifecycle.md +1 -1
- package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
- package/templates/.agents/rules/astra-diagnostic.md +1 -1
- package/templates/.agents/runtime/VERSION +1 -1
- package/templates/.agents/runtime/bin/zaip.mjs +769 -213
- package/templates/.agents/runtime/checksums.sha256 +5 -5
- package/templates/.agents/runtime/manifest.json +1 -1
- package/templates/.agents/runtime/provenance.json +4 -4
- package/templates/.agents/runtime/sbom.cdx.json +1 -1
- package/templates/.agents/skills/zaip-skill-execution/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-execution/references/correction-cycle.md +26 -0
- package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +2 -0
- package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +31 -1
- package/templates/.agents/skills/zaip-skill-setup/SKILL.md +26 -1
- package/templates/.agents/skills/zaip-skill-task/references/commit-policy.md +8 -1
- package/templates/.agents/zaip-aios/VERSION +1 -1
- package/templates/.agents/zaip-aios/guides/14-troubleshooting.md +52 -1
- package/templates/template-manifest.json +95 -87
|
@@ -5,9 +5,12 @@ import { lstat, readFile, realpath } from "node:fs/promises";
|
|
|
5
5
|
import { dirname, isAbsolute, relative, resolve } from "node:path";
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
7
|
import { promisify } from "node:util";
|
|
8
|
-
|
|
8
|
+
import { captureCliTurn, checkDestructivePatterns, gitInvocation, inside, isLiteralReadSequence, requiresShellMutationRun, reviewedContextReadPaths, reviewedReleasePaths, rewriteCliInput, selectHookExecutionWorkspace, shellSyntax, tokenizeLiteralCommand, validateInlineExecution } from "./zaip-pre-tool-support.mjs";
|
|
9
9
|
const execute = promisify(execFile);
|
|
10
|
-
const
|
|
10
|
+
const nativeAuthority = await import("./zaip-native-tool-authority.mjs").catch(() => null);
|
|
11
|
+
const activation = await import("./zaip-hook-activation.mjs").catch(() => null);
|
|
12
|
+
const installedRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
13
|
+
let repositoryRoot = installedRoot;
|
|
11
14
|
const deletionCommandPattern = /\b(?:Remove-Item|rm|rmdir|rd|del|erase)\b/i;
|
|
12
15
|
const allowedExplicitNetworkHosts = new Set([
|
|
13
16
|
"127.0.0.1", "api.github.com", "github.com", "localhost", "objects.githubusercontent.com", "::1",
|
|
@@ -66,7 +69,7 @@ const destructivePatterns = [
|
|
|
66
69
|
reason: "Remote, SSH, and credential configuration changes are blocked.",
|
|
67
70
|
},
|
|
68
71
|
{
|
|
69
|
-
pattern: /\bgh
|
|
72
|
+
pattern: /\bgh(?:\.exe)?\b[\s\S]*\s(?:--repo|-R)(?:=|\s|(?=[A-Za-z0-9]))/i,
|
|
70
73
|
reason: "GitHub CLI commands must target the current repository.",
|
|
71
74
|
},
|
|
72
75
|
{
|
|
@@ -94,13 +97,17 @@ const destructivePatterns = [
|
|
|
94
97
|
reason: "OS persistence and service changes are blocked.",
|
|
95
98
|
},
|
|
96
99
|
{
|
|
97
|
-
pattern: /\b(?:diskpart|bcdedit|fsutil|takeown|icacls|Set-Acl|chmod|chown)\b|(?:^|[\s
|
|
100
|
+
pattern: /\b(?:diskpart|bcdedit|fsutil|takeown|icacls|Set-Acl|chmod|chown)\b|(?:^|[;&|({\r\n])\s*(?:&\s*)?["']?format(?:\.(?:com|exe))?["']?(?=\s|$)|\bcipher\s+\/w\b/i,
|
|
98
101
|
reason: "Disk, boot, ownership, and access-control changes are blocked.",
|
|
99
102
|
},
|
|
100
103
|
{
|
|
101
104
|
pattern: /\b(?:runas|sudo|gsudo)\b|Start-Process[\s\S]*-Verb\s+RunAs|\bSet-ExecutionPolicy\b/i,
|
|
102
105
|
reason: "Privilege escalation and persistent execution-policy changes are blocked.",
|
|
103
106
|
},
|
|
107
|
+
{
|
|
108
|
+
pattern: /\b(?:Start-Process|saps)\b[^\r\n;|]*(?:[$(]|\b(?:-FilePath\s+)?['"]?git(?:\.exe)?['"]?(?:\s|$))/i,
|
|
109
|
+
reason: "Dynamic or indirect Git process launch is blocked; use a reviewed repository script.",
|
|
110
|
+
},
|
|
104
111
|
{
|
|
105
112
|
pattern: /\b(?:winget|choco|scoop)\s+(?:install|uninstall|upgrade)\b|\b(?:npm|pnpm|yarn)\s+(?:install|add|remove|uninstall)[\s\S]*(?:--global|-g)\b/i,
|
|
106
113
|
reason: "System-wide package changes are blocked.",
|
|
@@ -110,7 +117,7 @@ const destructivePatterns = [
|
|
|
110
117
|
reason: "Non-loopback listeners are blocked.",
|
|
111
118
|
},
|
|
112
119
|
{
|
|
113
|
-
pattern: /\bgh
|
|
120
|
+
pattern: /\bgh(?:\.exe)?\s+(?:pr\s+(?:create|merge|close|reopen)|issue\s+(?:create|close|reopen|delete)|release\s+(?:create|delete|upload)|repo\s+(?:create|delete|archive)|api\b[\s\S]*(?:(?:--method|-X)(?:=|\s*)(?:POST|PUT|PATCH|DELETE)\b|(?:--field|--raw-field|--input)(?:=|\s+)|(?:^|\s)-[fF](?:=|\s+)))/i,
|
|
114
121
|
reason: "Unreviewed GitHub mutations are blocked; use the bounded deploy workflow.",
|
|
115
122
|
},
|
|
116
123
|
{
|
|
@@ -120,23 +127,21 @@ const destructivePatterns = [
|
|
|
120
127
|
];
|
|
121
128
|
|
|
122
129
|
function deny(reason) {
|
|
130
|
+
activation?.recordActivation(repositoryRoot, event, "denied");
|
|
123
131
|
writeSync(
|
|
124
132
|
1,
|
|
125
133
|
JSON.stringify({
|
|
126
134
|
hookSpecificOutput: {
|
|
127
135
|
hookEventName: "PreToolUse",
|
|
128
136
|
permissionDecision: "deny",
|
|
129
|
-
permissionDecisionReason: "ZAIP safety policy: " + reason,
|
|
137
|
+
permissionDecisionReason: "ZAIP safety policy: " + reason + " [tool=" + String(event?.tool_name ?? "unknown").slice(0, 80) + "; session=" + String(event?.session_id ?? "missing").slice(0, 80) + "; turn=" + String(event?.turn_id ?? "missing").slice(0, 80) + "]",
|
|
130
138
|
},
|
|
131
139
|
}) + "\n",
|
|
132
140
|
);
|
|
133
141
|
process.exit(0);
|
|
134
142
|
}
|
|
135
143
|
|
|
136
|
-
|
|
137
|
-
const candidate = relative(repositoryRoot, resolve(path));
|
|
138
|
-
return candidate === "" || (!candidate.startsWith("..") && !isAbsolute(candidate));
|
|
139
|
-
}
|
|
144
|
+
const isWithinRepository = path => inside(path, repositoryRoot);
|
|
140
145
|
|
|
141
146
|
function repositoryPath(path) {
|
|
142
147
|
return relative(repositoryRoot, resolve(path)).replaceAll("\\", "/");
|
|
@@ -168,56 +173,52 @@ function explicitPathCandidates(command) {
|
|
|
168
173
|
}
|
|
169
174
|
return [...candidates].map(unquote).filter(Boolean);
|
|
170
175
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (homeReferencePattern.test(
|
|
176
|
+
function validateExplicitFilesystemReferences(command, cwd, reviewedPaths = []) {
|
|
177
|
+
const checked = reviewedPaths.reduce((text, path) => text.replaceAll(path, "REVIEWED_RELEASE_PATH"), command);
|
|
178
|
+
if (homeReferencePattern.test(checked)) {
|
|
174
179
|
deny("Direct user-profile path references are blocked; use repository-scoped paths.");
|
|
175
180
|
}
|
|
176
|
-
if (credentialReferencePattern.test(
|
|
181
|
+
if (credentialReferencePattern.test(checked) || sensitiveEnvironmentPattern.test(checked)) {
|
|
177
182
|
deny("Direct credential and secret access is blocked.");
|
|
178
183
|
}
|
|
179
|
-
if (/\b(?:Get-ChildItem|gci|dir)\s+Env:|\b(?:printenv|set)\s*$/i.test(
|
|
184
|
+
if (/\b(?:Get-ChildItem|gci|dir)\s+Env:|\b(?:printenv|set)\s*$/i.test(checked) || /GetEnvironmentVariables\s*\(/i.test(checked)) {
|
|
180
185
|
deny("Bulk environment enumeration is blocked.");
|
|
181
186
|
}
|
|
182
|
-
if (
|
|
187
|
+
if (/(?:^|[\s"'=(,]|-[A-Za-z][A-Za-z0-9_-]*:)(?:(?:\\\\){1,2}|\/\/)[^\\/\s"']+[\\/]/.test(checked)) {
|
|
183
188
|
deny("UNC and network filesystem paths are blocked.");
|
|
184
189
|
}
|
|
185
|
-
|
|
190
|
+
const osPathCommand = checked.replace(/^(node\s+\.agents[\\/]runtime[\\/]bin[\\/]zaip\.mjs\s+subagent\s+capture-terminal\b[^;&|\x60\r\n]*?)--agent-id\s+\/root\/[a-z][a-z0-9_]*_zaip_agent(?:_[a-z0-9]+)?(?=\s|$)(?=[^;&|\x60\r\n]*$)/, "$1--agent-id zaip-agent");
|
|
191
|
+
if (/(?:^|[\s"'=])\/(?:etc|home|Users|root|var|opt|private|mnt|proc|sys|dev|tmp)(?:[\/\s"']|$)/i.test(osPathCommand)) {
|
|
186
192
|
deny("Explicit operating-system paths outside the repository are blocked.");
|
|
187
193
|
}
|
|
188
|
-
|
|
194
|
+
if (process.platform === "win32" && /(?:^|[\s"'=(,])\\(?!\\)[^\s\\/"'<>|;]+(?:\\[^\s"'<>|;]+|\.[A-Za-z0-9]{1,10})/.test(checked)) {
|
|
195
|
+
deny("Drive-rooted filesystem paths outside the repository are blocked.");
|
|
196
|
+
}
|
|
197
|
+
for (const candidate of explicitPathCandidates(checked)) {
|
|
189
198
|
if (process.platform !== "win32" && /^[A-Za-z]:[\\/]/.test(candidate)) deny("Explicit filesystem path escapes the repository boundary.");
|
|
190
199
|
const absolute = resolve(cwd, candidate);
|
|
191
200
|
if (!isWithinRepository(absolute)) {
|
|
192
|
-
deny("Explicit filesystem path escapes the repository boundary.");
|
|
201
|
+
deny("Explicit filesystem path escapes the repository boundary. Validated workspace: " + repositoryRoot + "; tool: " + event.tool_name + "; workdir override: " + (typeof event.tool_input?.workdir === "string"));
|
|
193
202
|
}
|
|
194
203
|
}
|
|
195
204
|
}
|
|
196
|
-
|
|
197
|
-
function validateInlineExecution(command) {
|
|
198
|
-
const inlinePatterns = [
|
|
199
|
-
/\b(?:node|deno)\s+(?:-e|--eval)\b/i,
|
|
200
|
-
/\b(?:python(?:3)?|ruby|perl|php)\s+(?:-c|-e)\b/i,
|
|
201
|
-
/\bdeno\s+eval\b/i,
|
|
202
|
-
/\b(?:powershell|pwsh)(?:\.exe)?\b[\s\S]*\s-(?:Command|EncodedCommand|enc)\b/i,
|
|
203
|
-
/\bcmd(?:\.exe)?\s+\/c\b/i,
|
|
204
|
-
/\|\s*(?:node|deno|python(?:3)?|ruby|perl|php|powershell|pwsh|cmd)\b/i,
|
|
205
|
-
/\b(?:Invoke-Expression|iex)\b/i,
|
|
206
|
-
];
|
|
207
|
-
if (inlinePatterns.some((pattern) => pattern.test(command))) {
|
|
208
|
-
deny("Inline or piped interpreter execution is blocked; use a reviewed repository script.");
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
205
|
async function validateGitPublication(command) {
|
|
206
|
+
if (/(?:^|[;&|\r\n])\s*(?:(?:&\s*)?(?:['"]git(?:\.exe)?['"]|\(\s*['"]git(?:\.exe)?['"]\s*\))|(?:env|command)\s+git(?:\.exe)?\b)/i.test(command) ||
|
|
207
|
+
/&\s*\(\s*Get-Command\s+git(?:\.exe)?\b/i.test(command) ||
|
|
208
|
+
/(?:^|[\s;&|])&\s*\$[A-Za-z_]/i.test(command) || /\b(?:Set-Alias|New-Alias)\b[^\r\n;]*\bgit\b/i.test(command)) {
|
|
209
|
+
deny("Indirect Git execution is blocked; use a single literal command.");
|
|
210
|
+
}
|
|
211
|
+
if (/\(\s*git(?:\.exe)?\b/i.test(command)) {
|
|
212
|
+
deny("Nested Git execution is blocked; use a single literal command.");
|
|
213
|
+
}
|
|
213
214
|
const tokens = tokenizeLiteralCommand(command);
|
|
214
215
|
if (tokens === null) {
|
|
215
|
-
if (/(?:^|[
|
|
216
|
+
if (/(?:^|[;&|\r\n(])\s*git(?:\.exe)?\b/i.test(command)) {
|
|
216
217
|
deny("Git commands must be a single literal command; separate commands before requesting execution.");
|
|
217
218
|
}
|
|
218
219
|
return;
|
|
219
220
|
}
|
|
220
|
-
const invocation = gitInvocation(tokens);
|
|
221
|
+
const invocation = gitInvocation(tokens, deny);
|
|
221
222
|
if (invocation === null) return;
|
|
222
223
|
const { subcommand, arguments: arguments_ } = invocation;
|
|
223
224
|
if (subcommand === "commit" && arguments_.some((value) => /^(?:--amend|--no-verify|-n)/i.test(value))) {
|
|
@@ -331,39 +332,6 @@ function isSafeBranchName(branch) {
|
|
|
331
332
|
return typeof branch === "string" && branch.length <= 255 && /^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(branch) && !branch.includes("..") && !branch.includes("//") && !branch.includes("@{") && !branch.endsWith(".") && !branch.endsWith("/") && !branch.split("/").some((segment) => segment.startsWith(".") || segment.endsWith(".lock"));
|
|
332
333
|
}
|
|
333
334
|
|
|
334
|
-
function gitInvocation(tokens) {
|
|
335
|
-
if (tokens === null || !/^(?:git|git\.exe)$/i.test(tokens[0] ?? "")) return null;
|
|
336
|
-
let index = 1;
|
|
337
|
-
while (index < tokens.length && tokens[index].startsWith("-")) {
|
|
338
|
-
const rawOption = tokens[index];
|
|
339
|
-
const option = rawOption.toLowerCase();
|
|
340
|
-
if (option === "--version" || option === "--help") return null;
|
|
341
|
-
if (option === "--no-pager" || option === "--literal-pathspecs") {
|
|
342
|
-
index += 1;
|
|
343
|
-
continue;
|
|
344
|
-
}
|
|
345
|
-
if (
|
|
346
|
-
rawOption === "-c" ||
|
|
347
|
-
rawOption.startsWith("-c") ||
|
|
348
|
-
option.startsWith("--config") ||
|
|
349
|
-
option === "--git-dir" ||
|
|
350
|
-
option === "--work-tree" ||
|
|
351
|
-
option === "--namespace"
|
|
352
|
-
) {
|
|
353
|
-
deny("Git global configuration and repository-routing overrides are blocked.");
|
|
354
|
-
}
|
|
355
|
-
if (rawOption === "-C" || rawOption.startsWith("-C")) {
|
|
356
|
-
const directory = rawOption === "-C" ? tokens[index + 1] : rawOption.slice(2);
|
|
357
|
-
if (directory !== ".") deny("Git working-directory overrides outside the repository root are blocked.");
|
|
358
|
-
index += rawOption === "-C" ? 2 : 1;
|
|
359
|
-
continue;
|
|
360
|
-
}
|
|
361
|
-
deny("Unknown Git global option is blocked.");
|
|
362
|
-
}
|
|
363
|
-
const subcommand = tokens[index]?.toLowerCase();
|
|
364
|
-
return subcommand === undefined ? null : { subcommand, arguments: tokens.slice(index + 1) };
|
|
365
|
-
}
|
|
366
|
-
|
|
367
335
|
function validateExplicitNetwork(command) {
|
|
368
336
|
if (/(?:^|[;&|]\s*)\b(?:ssh|scp|sftp|rsync|ftp|telnet|nc|ncat)\b/i.test(command)) {
|
|
369
337
|
deny("Direct remote-shell and file-transfer clients are blocked.");
|
|
@@ -546,43 +514,6 @@ async function validateCloudRunner(command) {
|
|
|
546
514
|
return true;
|
|
547
515
|
}
|
|
548
516
|
|
|
549
|
-
function tokenizeLiteralCommand(command) {
|
|
550
|
-
if (
|
|
551
|
-
command.includes("\r") ||
|
|
552
|
-
command.includes("\n") ||
|
|
553
|
-
command.includes(";") ||
|
|
554
|
-
command.includes("|") ||
|
|
555
|
-
command.includes("&") ||
|
|
556
|
-
command.includes(String.fromCharCode(96))
|
|
557
|
-
) return null;
|
|
558
|
-
|
|
559
|
-
const tokens = [];
|
|
560
|
-
let token = "";
|
|
561
|
-
let quote = null;
|
|
562
|
-
let started = false;
|
|
563
|
-
for (const character of command) {
|
|
564
|
-
if (quote !== null) {
|
|
565
|
-
if (character === quote) quote = null;
|
|
566
|
-
else token += character;
|
|
567
|
-
} else if (character === "'" || character === '"') {
|
|
568
|
-
quote = character;
|
|
569
|
-
started = true;
|
|
570
|
-
} else if (/\s/.test(character)) {
|
|
571
|
-
if (started) {
|
|
572
|
-
tokens.push(token);
|
|
573
|
-
token = "";
|
|
574
|
-
started = false;
|
|
575
|
-
}
|
|
576
|
-
} else {
|
|
577
|
-
token += character;
|
|
578
|
-
started = true;
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
if (quote !== null) return null;
|
|
582
|
-
if (started) tokens.push(token);
|
|
583
|
-
return tokens;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
517
|
function deletionTargets(command) {
|
|
587
518
|
const tokens = tokenizeLiteralCommand(command);
|
|
588
519
|
if (tokens === null || tokens.length < 2) return null;
|
|
@@ -652,7 +583,7 @@ async function validateShellDeletion(command, cwd) {
|
|
|
652
583
|
for (const target of targets) await validateDeletionPath(target, cwd);
|
|
653
584
|
}
|
|
654
585
|
|
|
655
|
-
function validatePatch(command) {
|
|
586
|
+
async function validatePatch(command) {
|
|
656
587
|
const headers = [...command.matchAll(/^\*\*\* (Add|Update|Delete) File:\s*(.+)$|^\*\*\* Move to:\s*(.+)$/gm)];
|
|
657
588
|
const lifecycleRecordTouched = headers.some((match) => {
|
|
658
589
|
const candidate = (match[2] ?? match[3]).trim().replace(/^["']|["']$/g, "");
|
|
@@ -665,28 +596,27 @@ function validatePatch(command) {
|
|
|
665
596
|
const candidate = (match[2] ?? match[3]).trim().replace(/^["']|["']$/g, "");
|
|
666
597
|
const absolute = resolve(repositoryRoot, candidate);
|
|
667
598
|
if (!isWithinRepository(absolute)) deny("Patch path escapes the repository boundary.");
|
|
599
|
+
if (!await nativeAuthority?.isSafePatchPath(absolute, repositoryRoot)) deny("Patch path traverses a link or could not be safely verified.");
|
|
668
600
|
if (repositoryPath(absolute) === "") deny("Patching the repository root is blocked.");
|
|
669
601
|
if (isGitPath(absolute)) {
|
|
670
602
|
deny("Direct edits to protected Git control files are blocked.");
|
|
671
603
|
}
|
|
672
604
|
}
|
|
673
605
|
}
|
|
674
|
-
|
|
675
|
-
const lifecycleExemptPathPattern = /^(?:\.agents\/records|\.local)\//;
|
|
676
|
-
const shellMutationPattern = /\b(?:Set-Content|Add-Content|Out-File|New-Item|Copy-Item|Move-Item|Remove-Item|git\s+apply|npm\s+version|pnpm\s+version)\b/i;
|
|
677
|
-
|
|
606
|
+
const lifecycleExemptPathPattern = /^\.local\/(?!(?:codex-hook-|codex-telemetry-spool\/|runs\/))/;
|
|
678
607
|
function patchPaths(command) {
|
|
679
608
|
return [...command.matchAll(/^\*\*\* (?:Add|Update|Delete) File:\s*(.+)$|^\*\*\* Move to:\s*(.+)$/gm)].map(
|
|
680
609
|
(match) => repositoryPath(resolve(repositoryRoot, (match[1] ?? match[2]).trim().replace(/^["']|["']$/g, ""))),
|
|
681
610
|
);
|
|
682
611
|
}
|
|
683
612
|
|
|
684
|
-
function requiresOrchestratorRun(event, command) {
|
|
613
|
+
async function requiresOrchestratorRun(event, command) {
|
|
685
614
|
if (event.tool_name === "apply_patch") {
|
|
686
615
|
const paths = patchPaths(command);
|
|
687
616
|
return paths.length === 0 || paths.some((path) => !lifecycleExemptPathPattern.test(path));
|
|
688
617
|
}
|
|
689
618
|
if (event.tool_name === "Edit" || event.tool_name === "Write") {
|
|
619
|
+
if (!await nativeAuthority?.isSafePatchPath(resolve(event.cwd ?? repositoryRoot, command), repositoryRoot)) deny("File write path traverses a link or could not be safely verified.");
|
|
690
620
|
return !lifecycleExemptPathPattern.test(repositoryPath(resolve(event.cwd ?? repositoryRoot, command)));
|
|
691
621
|
}
|
|
692
622
|
// Only single literal writes claim exemptions; compound commands remain gated.
|
|
@@ -701,23 +631,25 @@ function requiresOrchestratorRun(event, command) {
|
|
|
701
631
|
}
|
|
702
632
|
if (valid && options.has("-literalpath") && options.has("-value")) {
|
|
703
633
|
const path = repositoryPath(resolve(event.cwd ?? repositoryRoot, options.get("-literalpath")));
|
|
634
|
+
if (!await nativeAuthority?.isSafePatchPath(resolve(repositoryRoot, path), repositoryRoot)) deny("Shell write path traverses a link or could not be safely verified.");
|
|
704
635
|
if (lifecycleExemptPathPattern.test(path)) return false;
|
|
705
636
|
}
|
|
706
637
|
}
|
|
707
|
-
return
|
|
638
|
+
return requiresShellMutationRun(command, tokens, event.cwd ?? repositoryRoot, repositoryRoot);
|
|
708
639
|
}
|
|
709
640
|
|
|
710
641
|
async function boundedCanonicalText(path, maximumBytes) {
|
|
711
642
|
const info = await lstat(path);
|
|
712
643
|
if (!info.isFile() || info.isSymbolicLink() || info.size > maximumBytes) throw new Error("Unsafe Run lookup file");
|
|
713
644
|
const physical = await realpath(path);
|
|
714
|
-
|
|
645
|
+
const identity = value => process.platform === "win32" ? value.toLowerCase() : value;
|
|
646
|
+
if (!isWithinRepository(physical) || identity(physical) !== identity(resolve(path))) throw new Error("Run lookup must not follow links");
|
|
715
647
|
return readFile(path, "utf8");
|
|
716
648
|
}
|
|
717
649
|
|
|
718
650
|
async function hasCurrentTaskOrchestratorRun(event) {
|
|
719
|
-
const threadId = event.session_id
|
|
720
|
-
const turnId = event.turn_id
|
|
651
|
+
const threadId = event.session_id;
|
|
652
|
+
const turnId = event.turn_id;
|
|
721
653
|
if (typeof threadId !== "string" || typeof turnId !== "string" || !threadId || !turnId) return false;
|
|
722
654
|
if ((event.session_id && process.env.CODEX_THREAD_ID && event.session_id !== process.env.CODEX_THREAD_ID) ||
|
|
723
655
|
(event.turn_id && process.env.CODEX_TURN_ID && event.turn_id !== process.env.CODEX_TURN_ID)) return false;
|
|
@@ -726,7 +658,7 @@ async function hasCurrentTaskOrchestratorRun(event) {
|
|
|
726
658
|
const digest = createHash("sha256").update(JSON.stringify(["codex", threadId, turnId, null, null])).digest("hex");
|
|
727
659
|
const correlation = JSON.parse(await boundedCanonicalText(resolve(repositoryRoot, ".local/codex-telemetry-spool/v1/correlations", digest + ".json"), 65536));
|
|
728
660
|
const id = correlation.run_id;
|
|
729
|
-
const dated = typeof id === "string" ? /^RUN-(\d{4})-(\d{2})-(\d{2})-[A-Z0-9-]+-[A-Z0-9]{
|
|
661
|
+
const dated = typeof id === "string" ? /^RUN-(\d{4})-(\d{2})-(\d{2})-[A-Z0-9-]+-[A-Z0-9]{2,16}$/.exec(id) : null;
|
|
730
662
|
if (!dated || correlation.schema_version !== 1 || correlation.thread_id !== threadId || correlation.turn_id !== turnId || correlation.agent_path !== null) return false;
|
|
731
663
|
const candidates = [
|
|
732
664
|
".agents/records/runs/" + dated[1] + "/" + dated[2] + "/" + id + ".jsonl",
|
|
@@ -766,11 +698,13 @@ try {
|
|
|
766
698
|
deny("Malformed hook input was rejected.");
|
|
767
699
|
}
|
|
768
700
|
|
|
769
|
-
|
|
701
|
+
const toolInput = event?.tool_input;
|
|
702
|
+
try { const scope = await selectHookExecutionWorkspace(installedRoot, event); repositoryRoot = scope.repositoryRoot; event = { ...event, cwd: scope.cwd }; }
|
|
703
|
+
catch (error) { deny(error.message); }
|
|
704
|
+
if (!isWithinRepository(event.cwd)) {
|
|
770
705
|
deny("Tool execution outside the ZAIP-AIOS repository is blocked.");
|
|
771
706
|
}
|
|
772
707
|
|
|
773
|
-
const toolInput = event?.tool_input;
|
|
774
708
|
const commandFromCmd = toolInput?.cmd;
|
|
775
709
|
const commandFromCommand = toolInput?.command;
|
|
776
710
|
if (typeof commandFromCmd === "string" && typeof commandFromCommand === "string" && commandFromCmd !== commandFromCommand) {
|
|
@@ -779,22 +713,30 @@ if (typeof commandFromCmd === "string" && typeof commandFromCommand === "string"
|
|
|
779
713
|
const command = typeof commandFromCmd === "string" ? commandFromCmd : commandFromCommand;
|
|
780
714
|
if (typeof command !== "string") deny("A matched tool call without a command was rejected.");
|
|
781
715
|
|
|
782
|
-
if (requiresOrchestratorRun(event, command) && !(await hasCurrentTaskOrchestratorRun(event))
|
|
716
|
+
if (await requiresOrchestratorRun(event, command) && !(await hasCurrentTaskOrchestratorRun(event)) &&
|
|
717
|
+
!(await nativeAuthority?.hasNativeDelegatedPatch(event, repositoryRoot, boundedCanonicalText))) {
|
|
783
718
|
deny("Persistent mutation requires the exact active Task Run and its verified thread/turn correlation. Capture or reconcile this turn before retrying; no global Task fallback is allowed.");
|
|
784
719
|
}
|
|
785
720
|
|
|
786
|
-
if (event.tool_name === "apply_patch") validatePatch(command);
|
|
721
|
+
if (event.tool_name === "apply_patch") await validatePatch(command);
|
|
787
722
|
else {
|
|
788
|
-
|
|
789
|
-
|
|
723
|
+
const reviewedPaths = [
|
|
724
|
+
...await reviewedReleasePaths(command, event.cwd, repositoryRoot, credentialReferencePattern, deny),
|
|
725
|
+
...await reviewedContextReadPaths(command, credentialReferencePattern), ...await (nativeAuthority?.reviewedValidationRuntimePaths?.(command, tokenizeLiteralCommand) ?? []),
|
|
726
|
+
];
|
|
727
|
+
validateExplicitFilesystemReferences(command, event.cwd, reviewedPaths);
|
|
728
|
+
validateInlineExecution(command, deny);
|
|
729
|
+
if (!isLiteralReadSequence(command)) {
|
|
790
730
|
await validateGitPublication(command);
|
|
791
731
|
await validateCloudRunner(command);
|
|
792
732
|
validateDirectCloudProviderMutation(command);
|
|
793
733
|
validateExplicitNetwork(command);
|
|
794
734
|
await validateShellDeletion(command, event.cwd);
|
|
795
|
-
|
|
796
|
-
if (entry.pattern.test(command)) deny(entry.reason);
|
|
735
|
+
checkDestructivePatterns(command, destructivePatterns, deny);
|
|
797
736
|
}
|
|
737
|
+
try { const updated = await captureCliTurn(repositoryRoot, event, command); if (updated) writeSync(1, JSON.stringify(rewriteCliInput(toolInput, updated, commandFromCmd)) + "\n"); }
|
|
738
|
+
catch (error) { deny(error.message); }
|
|
798
739
|
}
|
|
740
|
+
activation?.recordActivation(repositoryRoot, event, "allowed");
|
|
799
741
|
`;
|
|
800
742
|
//# sourceMappingURL=codex-pre-tool-hook-template.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex-pre-tool-hook-template.js","sourceRoot":"","sources":["../../src/services/codex-pre-tool-hook-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"codex-pre-tool-hook-template.js","sourceRoot":"","sources":["../../src/services/codex-pre-tool-hook-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAouB5C,CAAC"}
|