fix(augment): protect orphaned wrappers

This commit is contained in:
ZacharyZhang-NY committed 2026-07-20 09:37:10 -04:00
1 parent 323757e43d
commit 65b60b1eba
2 files changed
+40 -3

No files matched your search

+22 -3
View File
@@ -67,6 +67,11 @@ export interface PreparedManagedInstallation {
readonly transaction: PreparedManagedTransaction; readonly transaction: PreparedManagedTransaction;
} }
interface RuntimeArtifactLocation {
readonly filePath: string;
readonly label: string;
}
export type { RenameFile }; export type { RenameFile };
export function samePath(left: string, right: string): boolean { export function samePath(left: string, right: string): boolean {
@@ -145,6 +150,7 @@ function sameAgentId(left: unknown, right: string): boolean {
async function validateRuntimeIdentity( async function validateRuntimeIdentity(
paths: ManagedRuntimePaths, paths: ManagedRuntimePaths,
agentKey: string, agentKey: string,
additionalArtifacts: readonly RuntimeArtifactLocation[] = [],
): Promise<void> { ): Promise<void> {
if (!await inspectPhysicalDirectory(paths.runtimeRoot, 'Elydora runtime directory')) return; if (!await inspectPhysicalDirectory(paths.runtimeRoot, 'Elydora runtime directory')) return;
if (!await inspectPhysicalDirectory(paths.agentDirectory, 'Elydora agent runtime directory')) return; if (!await inspectPhysicalDirectory(paths.agentDirectory, 'Elydora agent runtime directory')) return;
@@ -156,6 +162,10 @@ async function validateRuntimeIdentity(
readPhysicalFile(path.join(paths.agentDirectory, 'chain-state.json'), 'Elydora chain state'), readPhysicalFile(path.join(paths.agentDirectory, 'chain-state.json'), 'Elydora chain state'),
readPhysicalFile(path.join(paths.agentDirectory, 'status-cache.json'), 'Elydora status cache'), readPhysicalFile(path.join(paths.agentDirectory, 'status-cache.json'), 'Elydora status cache'),
readPhysicalFile(path.join(paths.agentDirectory, 'error.log'), 'Elydora error log'), readPhysicalFile(path.join(paths.agentDirectory, 'error.log'), 'Elydora error log'),
...additionalArtifacts.map((artifact) => readPhysicalFile(
artifact.filePath,
artifact.label,
)),
]); ]);
if (!config) { if (!config) {
if (artifacts.some(Boolean)) { if (artifacts.some(Boolean)) {
@@ -233,6 +243,15 @@ export async function prepareManagedInstallation(
hookLocations: spec.hookSources, hookLocations: spec.hookSources,
config: spec.config, config: spec.config,
}, guardScript, auditScript); }, guardScript, auditScript);
const runtimeFiles = (spec.runtimeFiles ?? []).map((runtimeFile) => ({
runtimeFile,
filePath: runtimeFilePath(paths, runtimeFile.fileName),
}));
const runtimeArtifacts = runtimeFiles.map(({ runtimeFile, filePath }) => ({
filePath,
label: runtimeFile.label,
}));
await validateRuntimeIdentity(paths, spec.agentKey, runtimeArtifacts);
const changes = await Promise.all([ const changes = await Promise.all([
prepareManagedFileChange({ prepareManagedFileChange({
filePath: paths.guardPath, filePath: paths.guardPath,
@@ -260,8 +279,8 @@ export async function prepareManagedInstallation(
next: generateHookScript(spec.agentKey, spec.config.agentId, spec.auditOptions), next: generateHookScript(spec.agentKey, spec.config.agentId, spec.auditOptions),
mode: 0o700, mode: 0o700,
}), }),
...(spec.runtimeFiles ?? []).map((runtimeFile) => prepareManagedFileChange({ ...runtimeFiles.map(({ runtimeFile, filePath }) => prepareManagedFileChange({
filePath: runtimeFilePath(paths, runtimeFile.fileName), filePath,
label: runtimeFile.label, label: runtimeFile.label,
next: runtimeFile.source, next: runtimeFile.source,
mode: runtimeFile.mode, mode: runtimeFile.mode,
@@ -276,7 +295,7 @@ export async function prepareManagedInstallation(
verifyExpectedSource: true, verifyExpectedSource: true,
})), })),
]); ]);
await validateRuntimeIdentity(paths, spec.agentKey); await validateRuntimeIdentity(paths, spec.agentKey, runtimeArtifacts);
return { return {
paths, paths,
transaction: { transaction: {
+18
View File
@@ -197,6 +197,24 @@ test('Auggie rejects orphaned and mismatched runtime identities before writes',
} }
}); });
await t.test('orphaned wrapper', async () => {
const fixture = await createFixture();
try {
await mkdir(fixture.agentDir, { recursive: true });
await writeFile(fixture.guardWrapperPath, 'orphaned wrapper\n');
const result = await fixture.install();
assert.equal(result.code, 1);
assert.match(result.stderr, /identity cannot be verified/i);
assert.equal(
await readFile(fixture.guardWrapperPath, 'utf-8'),
'orphaned wrapper\n',
);
await assertMissing(fixture.settingsPath);
} finally {
await fixture.close();
}
});
await t.test('mismatched identity', async () => { await t.test('mismatched identity', async () => {
const fixture = await createFixture(); const fixture = await createFixture();
try { try {