thedotmack/claude-mem · error
Refusing CCS Align write outside the seat-owned ccs-align…
Error message
Refusing CCS Align write outside the seat-owned ccs-align root
What it means
assertSafeMiddleCachePath() is a path-containment guard for CCS Align middle-cache writes. It resolves the seat-owned root (ccsAlignViewerDir(dataRoot, viewerId)) and throws if the target file resolves outside that directory. The library refuses writes that could escape the per-seat ccs-align root, since landObservationsInMiddleCache must never touch files owned by other seats or system paths.
Solutions
- Build the target path with path.join(ccsAlignViewerDir(dataRoot, viewerId), relativeName) so it is anchored inside the seat root.
- Check the resolved path: ensure path.resolve(filePath).startsWith(path.resolve(ccsAlignViewerDir(dataRoot, viewerId)) + path.sep).
- Fix any traversal segments (../) or wrong viewerId in the path before calling landObservationsInMiddleCache.
Example fix
// before: unanchored path can escape the seat root const p = path.join(dataRoot, 'ccs-align', relativePath); // after: anchor inside the seat-owned viewer dir const p = path.join(ccsAlignViewerDir(dataRoot, viewerId), relativePath);
Defensive patterns
Strategy: validation
Validate before calling
import path from 'path';
function isInsideSeatRoot(dataRoot: string, viewerId: string, filePath: string): boolean {
const expectedRoot = path.resolve(ccsAlignViewerDir(dataRoot, viewerId));
const resolved = path.resolve(filePath);
return resolved === expectedRoot || resolved.startsWith(expectedRoot + path.sep);
} Try / catch
try {
landObservationsInMiddleCache(dataRoot, viewerId, filePath, observations);
} catch (err) {
if (err instanceof Error && err.message.includes('outside the seat-owned ccs-align root')) {
// rebuild path via ccsAlignViewerDir(dataRoot, viewerId) and retry once
} else throw err;
} Prevention
- Always derive cache paths from ccsAlignViewerDir(dataRoot, viewerId) instead of string concatenation.
- Sanitize user-supplied relative segments (reject '..').
- Keep viewerId consistent between path construction and write calls.
When it happens
Trigger: landObservationsInMiddleCache() calls assertSafeMiddleCachePath(dataRoot, viewerId, filePath) with a filePath that, after path.resolve(), does not start with the seat's ccs-align viewer dir (or equal it) — e.g. a path with ../ traversal, an absolute path into another directory, or a viewerId/filePath mismatch.
Common situations: Caller builds the cache path from untrusted or concatenated user input; viewerId changed between computing the path and writing; symlinks or relative paths cause resolution outside the root; a refactor moved files out of ccs-align/<viewerId>/ but the write path was not updated.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- Refusing awareness write outside agent memory/log
- Rejected path traversal attempt in watch.context.path
- INVALID_CORPUS_NAME
- Refusing awareness write to profile.md
- Refusing CCS Align write to profile.md
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/6531fc2ed088103f.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/integrations/CcsAlignMiddleCache.ts:283
excludedObsIds.add(mark.observationId);
for (const tid of mark.toolUseIds) {
excludedToolUseIds.add(tid);
}
}
return { excludedObsIds, excludedToolUseIds };
}
/**
* Refuse any write that escapes the seat-owned CCS Align root, targets
* `profile.md`, or lands inside an `agents/.../memory/log` tree (that is the
* #3931 pusher's seam, never Align's). Shape copied from
* `assertSafeAwarenessLogPath` (#3931).
*/
export function assertSafeMiddleCachePath(dataRoot: string, viewerId: string, filePath: string): void {
const expectedRoot = path.resolve(ccsAlignViewerDir(dataRoot, viewerId));
const resolved = path.resolve(filePath);
if (!resolved.startsWith(expectedRoot + path.sep) && resolved !== expectedRoot) {
throw new Error('Refusing CCS Align write outside the seat-owned ccs-align root');
}
if (path.basename(resolved) === 'profile.md') {
throw new Error('Refusing CCS Align write to profile.md');
}
if (/(^|[\\/])agents[\\/].*[\\/]memory[\\/]log([\\/]|$)/.test(resolved)) {
throw new Error('Refusing CCS Align write into agents/**/memory/log (that seam belongs to #3931)');
}
}
export function buildCcsAlignRecord(obs: CcsAlignObservationInput, now: Date = new Date()): CcsAlignMiddleRecord {
return {
v: RECORD_VERSION,
id: obs.id,
type: obs.type,
title: obs.title ?? null,
created_at: obs.created_at ?? null,
project: obs.project ?? null,
agent_id: obs.agent_id ?? null,View on GitHub (pinned to d8bc9755e7)