@@ -3,7 +3,8 @@ import fs from "node:fs/promises";
33import path from "node:path" ;
44import { parseByteSize } from "../cli/parse-bytes.js" ;
55import type { CronConfig } from "../config/types.cron.js" ;
6- import { appendRegularFile , isPathInside , pathExists , root as fsRoot } from "../infra/fs-safe.js" ;
6+ import { assertNoSymlinkParents } from "../infra/fs-safe-advanced.js" ;
7+ import { isPathInside , pathExists , root as fsRoot } from "../infra/fs-safe.js" ;
78import { privateFileStore } from "../infra/private-file-store.js" ;
89import {
910 normalizeLowercaseStringOrEmpty ,
@@ -154,6 +155,24 @@ async function pruneIfNeeded(filePath: string, opts: { maxBytes: number; keepLin
154155 ) ;
155156}
156157
158+ async function appendRunLogLine ( filePath : string , content : string ) {
159+ const runDir = path . dirname ( filePath ) ;
160+ await assertNoSymlinkParents ( {
161+ rootDir : path . parse ( runDir ) . root ,
162+ targetPath : runDir ,
163+ allowMissing : false ,
164+ allowRootChildSymlink : true ,
165+ requireDirectories : true ,
166+ messagePrefix : "Refusing to append under" ,
167+ } ) ;
168+ await (
169+ await fsRoot ( runDir , { mode : 0o600 } )
170+ ) . append ( path . basename ( filePath ) , content , {
171+ mkdir : false ,
172+ mode : 0o600 ,
173+ } ) ;
174+ }
175+
157176export async function appendCronRunLog (
158177 filePath : string ,
159178 entry : CronRunLogEntry ,
@@ -167,11 +186,7 @@ export async function appendCronRunLog(
167186 const runDir = path . dirname ( resolved ) ;
168187 await fs . mkdir ( runDir , { recursive : true , mode : 0o700 } ) ;
169188 await fs . chmod ( runDir , 0o700 ) . catch ( ( ) => undefined ) ;
170- await appendRegularFile ( {
171- filePath : resolved ,
172- content : `${ JSON . stringify ( entry ) } \n` ,
173- rejectSymlinkParents : true ,
174- } ) ;
189+ await appendRunLogLine ( resolved , `${ JSON . stringify ( entry ) } \n` ) ;
175190 await setSecureFileMode ( resolved ) ;
176191 await pruneIfNeeded ( resolved , {
177192 maxBytes : opts ?. maxBytes ?? DEFAULT_CRON_RUN_LOG_MAX_BYTES ,
0 commit comments