mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-15 10:59:32 +01:00
fix: keep credential files out of the file routes and Discord uploads (release review)
The Discord bot token was readable through the attachment routes, because discord.json was not on the sensitive list, and so were webhook.json, custom-model-hosts.json and the generated custom-model configs. Config backups were the wider gap: a dated copy of users.json or settings.json matched none of the name-anchored patterns. All are blocked now. `codeman notify --file` relied on folder confinement alone, which holds nothing back when a tab's folder is the home directory, and it would also post a workspace .env. It now applies the attachment blocklist to the real path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
126d967ba3
commit
4276b53a8f
7 files changed
+57
-6
No files matched your search
@@ -17,6 +17,7 @@ import type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
||||
import { ApiErrorCode, createErrorResponse, getErrorMessage, type ApiResponse } from '../../types.js';
|
||||
import { canAccessOwned, findSessionOrFail, getAuthUser, isAdmin, parseBody } from '../route-helpers.js';
|
||||
import type { SessionPort } from '../ports/session-port.js';
|
||||
import { isBlockedAttachmentPath, loadAttachmentGuardConfig } from '../../config/attachment-guard.js';
|
||||
import { isMultiUserMode } from '../../config/multiuser.js';
|
||||
import { describeUnknownPath, probePathKind } from '../../utils/bounded-path-probe.js';
|
||||
import { DiscordNotifySchema, DiscordUpdateSchema } from '../schemas.js';
|
||||
@@ -80,8 +81,10 @@ export function _resetNotifyBuckets(): void {
|
||||
|
||||
/**
|
||||
* A file a session may send: a regular file, at most MAX_FILE_BYTES, whose REAL path (symlinks
|
||||
* followed) lies inside the session's working folder. Anything else is refused, so a CLI cannot be
|
||||
* talked into posting ~/.codeman/discord.json or an ssh key. Returns the bytes, or the reason.
|
||||
* followed) lies inside the session's working folder and is not on the attachment blocklist. The
|
||||
* blocklist matters as much as the folder: with a home directory as the session folder, confinement
|
||||
* alone would let a CLI be talked into posting ~/.codeman/discord.json, an ssh key or a `.env`.
|
||||
* Returns the bytes, or the reason.
|
||||
*/
|
||||
async function fileProblem(
|
||||
workingDir: string,
|
||||
@@ -103,6 +106,9 @@ async function fileProblem(
|
||||
const rel = relative(root, real);
|
||||
if (rel === '' || rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel))
|
||||
return 'The file must be inside the session folder';
|
||||
if (isBlockedAttachmentPath(real, (await loadAttachmentGuardConfig()).blockedTrees)) {
|
||||
return 'That file cannot be sent: it can hold credentials';
|
||||
}
|
||||
const info = await stat(real);
|
||||
if (!info.isFile()) return 'Not a regular file';
|
||||
if (info.size > MAX_FILE_BYTES) return `The file is over ${MAX_FILE_BYTES / 1024 / 1024} MB`;
|
||||
|
||||
@@ -106,6 +106,17 @@ const SENSITIVE_PATTERNS: RegExp[] = [
|
||||
// agent wrote, keys and .env contents included; written 0600 and kept out of
|
||||
// /api/search for the same reason as intents.json.
|
||||
/\/\.codeman[^/]*\/edit-history\//,
|
||||
// Credentials kept outside settings.json: the Discord bot token, the webhook URL
|
||||
// (a bearer secret), the custom endpoints' API keys, and the generated per-session
|
||||
// configs, some of which carry that key inline.
|
||||
/\/\.codeman[^/]*\/discord\.json$/,
|
||||
/\/\.codeman[^/]*\/webhook\.json$/,
|
||||
/\/\.codeman[^/]*\/custom-model-hosts\.json$/,
|
||||
/\/\.codeman[^/]*\/custom-model-configs\//,
|
||||
// Config backups are dated COPIES of the files above (users.json and settings.json
|
||||
// included), which the name-anchored patterns do not match. A custom
|
||||
// `configBackupDir` is outside what a pattern here can name.
|
||||
/\/\.codeman[^/]*\/backups\//,
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user