Summary
Neither extendViaContract nor extendViaFootprint puts a ceiling on what it will pay. Both take
minResourceFee from the simulation, hand the assembled transaction to sign, and submit. The
number is whatever the network says it will cost.
That is a real weakness rather than a theoretical one, because registration is permissionless.
Anyone can register a contract in the registry, and lkeep keep maintains every contract in it. A
contract written to be expensive to maintain gets maintained at whatever it costs, once per tick,
until the keeper's account is empty. The futility backoff added in src/keeper/futility.ts does not
help here: an expensive extension that genuinely moves TTL is productive by every measure the daemon
has, so the backoff never opens a window.
The mitigation documented in SECURITY.md today is "fund the keeper with only what you are willing
to lose in a day". That is advice, not a control.
Acceptance Criteria
Tech Stack
TypeScript 5.7 on Node 22+ (CI runs 22 and 24), ESM with moduleResolution: "NodeNext" — relative
imports need the .js extension. @stellar/stellar-sdk is pinned to an exact version; verify RPC
API shape against the installed copy, not against documentation. Tests are Vitest under test/ and
run without a network. npm run format:check, npm run lint, npm run build and npm test must
all be clean.
Summary
Neither
extendViaContractnorextendViaFootprintputs a ceiling on what it will pay. Both takeminResourceFeefrom the simulation, hand the assembled transaction tosign, and submit. Thenumber is whatever the network says it will cost.
That is a real weakness rather than a theoretical one, because registration is permissionless.
Anyone can register a contract in the registry, and
lkeep keepmaintains every contract in it. Acontract written to be expensive to maintain gets maintained at whatever it costs, once per tick,
until the keeper's account is empty. The futility backoff added in
src/keeper/futility.tsdoes nothelp here: an expensive extension that genuinely moves TTL is productive by every measure the daemon
has, so the backoff never opens a window.
The mitigation documented in SECURITY.md today is "fund the keeper with only what you are willing
to lose in a day". That is advice, not a control.
Acceptance Criteria
LK_MAX_FEEor similar — validated insrc/config.tsalongside theexisting integer fields, with a documented default.
exceeded. The refusal is logged with the contract, the simulated fee, and the ceiling.
runTickmoves on to the next contract, thesame way it handles a failed extension today.
signis called, not after submission.being described as unmitigated.
Tech Stack
TypeScript 5.7 on Node 22+ (CI runs 22 and 24), ESM with
moduleResolution: "NodeNext"— relativeimports need the
.jsextension.@stellar/stellar-sdkis pinned to an exact version; verify RPCAPI shape against the installed copy, not against documentation. Tests are Vitest under
test/andrun without a network.
npm run format:check,npm run lint,npm run buildandnpm testmustall be clean.