mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-19 01:46:15 +02:00
fix: retain Codex sandbox resources after npm platform installation
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
f17c8c3bbf
commit
6baec5181f
7 files changed
+179
-11
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
||||
import { mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'node:fs';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
@@ -55,12 +55,13 @@ test('verification never elevates PR-controlled provisioning or cleanup on the h
|
||||
});
|
||||
|
||||
test('the installed Codex probe exercises the public export and rejects incomplete or mismatched packages', () => {
|
||||
const root = mkdtempSync(join(tmpdir(), 'installed-codex-probe-'));
|
||||
const root = realpathSync(mkdtempSync(join(tmpdir(), 'installed-codex-probe-')));
|
||||
try {
|
||||
const consumer = join(root, 'consumer'); mkdirSync(consumer);
|
||||
const target = `${process.platform}-${process.arch}`;
|
||||
const platformPath = `node_modules/@openai/codex-${target}`;
|
||||
const platform = join(consumer, platformPath); mkdirSync(platform, { recursive: true });
|
||||
const nativeVendor = join(platform, 'vendor'); mkdirSync(nativeVendor);
|
||||
const manifest = { name: '@openai/codex', version: `0.160.0-${target}`, os: [process.platform], cpu: [process.arch] };
|
||||
writeFileSync(join(platform, 'package.json'), JSON.stringify(manifest));
|
||||
const entry = { name: manifest.name, version: manifest.version,
|
||||
@@ -71,6 +72,10 @@ test('the installed Codex probe exercises the public export and rejects incomple
|
||||
const vendor = join(server, 'dist/vendor/paperclip-runner'), drivers = join(vendor, 'drivers/acpx'); mkdirSync(drivers, { recursive: true });
|
||||
writeFileSync(join(server, 'package.json'), JSON.stringify({ name: '@paperclipai/server', type: 'module' }));
|
||||
const integrity = join(drivers, 'installation-integrity.js');
|
||||
const security = join(vendor, 'drivers/codex/codex-security-config.js'); mkdirSync(join(vendor, 'drivers/codex'));
|
||||
const securitySource = `export const codexExecutableReadOnlyRoots = () => [${JSON.stringify(nativeVendor)}];
|
||||
export const createIsolatedCodexAppServerArgs = (source, roots) => roots.map(root => JSON.stringify(root) + '=\"read\"');`;
|
||||
writeFileSync(security, securitySource);
|
||||
const moduleSource = `import assert from 'node:assert/strict'; import { writeFileSync } from 'node:fs';
|
||||
export function createAcpxPackageJsonResolver(root, manifest) { assert.equal(root, ${JSON.stringify(server)}); assert.equal(manifest, root + '/package.json'); return () => 'selected-authority'; }
|
||||
export async function verifyQualifiedAcpxInstallation(profile, resolver) { assert.deepEqual(profile, { agent: 'codex', model: 'gpt-5.4' }); assert.equal(resolver(), 'selected-authority');
|
||||
@@ -91,6 +96,7 @@ test('the installed Codex probe exercises the public export and rejects incomple
|
||||
assert.equal(JSON.parse(result.stdout).codexConsumerPlatform, target);
|
||||
assert.equal(JSON.parse(result.stdout).codexQualifiedInstallationVerified, true);
|
||||
assert.equal(JSON.parse(result.stdout).codexCommandLeaseVerified, true);
|
||||
assert.equal(JSON.parse(result.stdout).codexNativeSandboxResourcesVerified, true);
|
||||
assert.equal(readFileSync(join(server, 'lease-closed'), 'utf8'), 'ok');
|
||||
assert.equal(JSON.parse(result.stdout).providerCalls, 0);
|
||||
const legacyPath = 'node_modules/legacy-codex-adapter/node_modules/@openai/codex-' + target;
|
||||
@@ -116,6 +122,13 @@ test('the installed Codex probe exercises the public export and rejects incomple
|
||||
writeFileSync(index, "export const resolvePinnedCodexCommand = () => { throw new Error('Bundled Codex runtime version mismatch'); };");
|
||||
result = run(); assert.notEqual(result.status, 0); assert.match(result.stderr, /Bundled Codex runtime version mismatch/);
|
||||
writeFileSync(index, `export const resolvePinnedCodexCommand = () => ${JSON.stringify(command)};`);
|
||||
writeFileSync(security, securitySource.replace(JSON.stringify(nativeVendor), '"/missing-vendor-root"'));
|
||||
result = run(); assert.notEqual(result.status, 0); assert.match(result.stderr, /vendor directory must be readable/);
|
||||
writeFileSync(security, securitySource.replace(JSON.stringify(nativeVendor), `${JSON.stringify(nativeVendor)}, ${JSON.stringify(consumer)}`));
|
||||
result = run(); assert.notEqual(result.status, 0); assert.match(result.stderr, /must not grant enclosing npm/);
|
||||
writeFileSync(security, securitySource.replace("'=\"read\"'", "'=\"write\"'"));
|
||||
result = run(); assert.notEqual(result.status, 0); assert.match(result.stderr, /retain the selected native executable resources/);
|
||||
writeFileSync(security, securitySource);
|
||||
const emptySlot = join(server, 'node_modules/@openai/codex-' + target);
|
||||
mkdirSync(emptySlot, { recursive: true });
|
||||
result = run(); assert.equal(result.status, 0, result.stderr);
|
||||
|
||||
@@ -126,7 +126,18 @@ export function installedCodexProbeSource(indexPath, consumerRoot, expectedVersi
|
||||
const vendor = dirname(index);
|
||||
const integrityPath = join(vendor, 'drivers/acpx/installation-integrity.js');
|
||||
const profilesPath = join(vendor, 'drivers/acpx/qualified-profiles.js');
|
||||
assert.ok(contained(integrityPath) && contained(profilesPath), 'Codex integrity modules must come from the installed consumer');
|
||||
const securityPath = join(vendor, 'drivers/codex/codex-security-config.js');
|
||||
assert.ok(contained(integrityPath) && contained(profilesPath) && contained(securityPath), 'Codex verification modules must come from the installed consumer');
|
||||
const { codexExecutableReadOnlyRoots, createIsolatedCodexAppServerArgs } = await import(pathToFileURL(securityPath).href);
|
||||
const platformRoot = realpathSync(dirname(selectedPlatformManifest));
|
||||
const nativeVendor = realpathSync(join(platformRoot, 'vendor'));
|
||||
assert.ok(contained(nativeVendor) && nativeVendor.startsWith(platformRoot + sep), 'Codex vendor resources must remain inside their installed platform package');
|
||||
const sandboxSource = { HOME: '/private-provider-home', PATH: '/usr/local/bin:/usr/bin:/bin' };
|
||||
const readRoots = codexExecutableReadOnlyRoots(sandboxSource, command);
|
||||
assert.ok(readRoots.includes(nativeVendor), 'Selected native Codex vendor directory must be readable inside its sandbox');
|
||||
assert.ok(!readRoots.includes(platformRoot) && !readRoots.includes(root) && !readRoots.includes(sandboxSource.HOME), 'Codex sandbox must not grant enclosing npm or credential-home access');
|
||||
const sandboxArgs = createIsolatedCodexAppServerArgs(sandboxSource, readRoots).join('\\n');
|
||||
assert.ok(sandboxArgs.includes(JSON.stringify(nativeVendor) + '="read"'), 'Codex sandbox configuration must retain the selected native executable resources');
|
||||
const { createAcpxPackageJsonResolver, verifyQualifiedAcpxInstallation } = await import(pathToFileURL(integrityPath).href);
|
||||
const { resolveQualifiedAcpxProfile } = await import(pathToFileURL(profilesPath).href);
|
||||
const serverRoot = resolve(vendor, '../../..');
|
||||
@@ -136,7 +147,7 @@ export function installedCodexProbeSource(indexPath, consumerRoot, expectedVersi
|
||||
const lease = await installation.openCommand();
|
||||
await lease.close();
|
||||
console.log(JSON.stringify({ pinnedCodexCommandVerified: true, pinnedCodexVersion: ${JSON.stringify(expectedVersion)},
|
||||
...provenance, codexSelectedPlatformPath: selectedPlatform.path, codexSelectedPlatformVersion: selectedMetadata.version, codexQualifiedInstallationVerified: true, codexCommandLeaseVerified: true, providerCalls: 0 }));
|
||||
...provenance, codexSelectedPlatformPath: selectedPlatform.path, codexSelectedPlatformVersion: selectedMetadata.version, codexNativeSandboxResourcesVerified: true, codexQualifiedInstallationVerified: true, codexCommandLeaseVerified: true, providerCalls: 0 }));
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user