Skip to content

Commit 4a8a76b

Browse files
Shawclaude
andcommitted
fix(discord): close reply-reference double-fetch + injection vector
Post-merge of #7821: - formatInboundEnvelope used `knownReplyContext ?? (await getDiscordReplyContext(message))`, which re-fetched whenever the caller passed an explicit `null` (already established no reply context). Switch to undefined-check so null is honored. - Raw Discord message text was concatenated into the envelope unsanitized, letting a user-crafted `[platform_reply_reference]...[/platform_reply_reference]` block be parsed by core as a trusted reply reference. Run rawContent through sanitizeReplyReferenceText so the markers cannot be smuggled in. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2 parents 7742088 + ae7b68d commit 4a8a76b

4 files changed

Lines changed: 51 additions & 12 deletions

File tree

packages/cloud-shared/src/lib/services/eliza-app/provisioning.test.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,31 @@ mock.module("../../../db/repositories/credit-transactions", () => ({
1818
},
1919
}));
2020

21+
class InsufficientCreditsError extends Error {
22+
constructor(
23+
public readonly required: number,
24+
public readonly available: number,
25+
public readonly reason?: string,
26+
) {
27+
super(
28+
`Insufficient credits. Required: $${required.toFixed(4)}, Available: $${available.toFixed(4)}`,
29+
);
30+
this.name = "InsufficientCreditsError";
31+
}
32+
}
33+
34+
class CreditsService {}
35+
2136
mock.module("../credits", () => ({
2237
creditsService: {
2338
addCredits,
2439
},
40+
CreditsService,
41+
InsufficientCreditsError,
42+
COST_BUFFER: 1.5,
43+
MIN_RESERVATION: 0.000001,
44+
EPSILON: 0.0000001,
45+
DEFAULT_OUTPUT_TOKENS: 500,
2546
}));
2647

2748
mock.module("../eliza-sandbox", () => ({

packages/core/src/services/message.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,13 +1713,9 @@ function parsePlatformReplyReferenceBlock(
17131713
): PlatformReplyReference | null {
17141714
if (!text) return null;
17151715
const lines = text.replace(/\r\n/g, "\n").split("\n");
1716-
let start = -1;
1717-
for (let index = lines.length - 1; index >= 0; index--) {
1718-
if (lines[index]?.trim() === PLATFORM_REPLY_REFERENCE_START) {
1719-
start = index;
1720-
break;
1721-
}
1722-
}
1716+
const start = lines.findLastIndex(
1717+
(line) => line.trim() === PLATFORM_REPLY_REFERENCE_START,
1718+
);
17231719
if (start === -1) return null;
17241720
const end = lines.findIndex(
17251721
(line, index) =>

packages/native/ios-deps/llama.cpp/build-ios.sh

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ build_slice() {
214214
mkdir -p "$build_dir/ggml/src/ggml-metal/autogenerated"
215215

216216
local xcode_jobs="${MILADY_LLAMA_XCODE_JOBS:-1}"
217+
local xcode_timeout="${MILADY_LLAMA_XCODE_TIMEOUT_SECONDS:-300}"
217218
# `cmake --build` adds `-parallelizeTargets` for Xcode projects. llama.cpp's
218219
# generated iOS project can race inside Xcode's shared build database even
219220
# with `-jobs 1`, so invoke xcodebuild directly and serialize target builds.
@@ -223,7 +224,24 @@ build_slice() {
223224
-target llama-common \
224225
-configuration Release \
225226
-jobs "$xcode_jobs" \
226-
-hideShellScriptEnvironment
227+
-hideShellScriptEnvironment &
228+
local xcode_pid=$!
229+
local elapsed=0
230+
while kill -0 "$xcode_pid" 2>/dev/null; do
231+
if (( elapsed >= xcode_timeout )); then
232+
err "xcodebuild timed out after ${xcode_timeout}s for slice $slice"
233+
kill "$xcode_pid" 2>/dev/null || true
234+
wait "$xcode_pid" 2>/dev/null || true
235+
popd >/dev/null
236+
return 1
237+
fi
238+
sleep 1
239+
elapsed=$((elapsed + 1))
240+
done
241+
if ! wait "$xcode_pid"; then
242+
popd >/dev/null
243+
return 1
244+
fi
227245
popd >/dev/null
228246

229247
# Locate produced .a files and fold them into a single libllama.a so
@@ -236,7 +254,8 @@ build_slice() {
236254
done < <(find "$search_root" \( -name "libllama.a" -o -name "libggml*.a" -o -name "libcommon.a" \) -print0)
237255

238256
if [[ ${#archives[@]} -eq 0 ]]; then
239-
die "no .a files produced in $build_dir — build likely failed"
257+
err "no .a files produced in $build_dir — build likely failed"
258+
return 1
240259
fi
241260

242261
# Compile the LlamaShim.c as well, into its own .a, and add to the bundle.
@@ -306,7 +325,8 @@ build_xcframework() {
306325
args+=(-library "$DIST_DIR/ios-arm64-simulator/libllama.a" -headers "$DIST_DIR/ios-arm64-simulator/Headers")
307326
fi
308327
if [[ ${#args[@]} -eq 0 ]]; then
309-
die "no slices to assemble into xcframework"
328+
err "no slices to assemble into xcframework"
329+
return 1
310330
fi
311331

312332
log "Assembling $out"

plugins/plugin-discord/inbound-envelope.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,9 @@ export async function formatInboundEnvelope(
170170

171171
let replyContextText = "";
172172
const refContext =
173-
knownReplyContext ?? (await getDiscordReplyContext(message));
173+
knownReplyContext === undefined
174+
? await getDiscordReplyContext(message)
175+
: knownReplyContext;
174176
if (refContext) {
175177
const truncated = truncateText(
176178
refContext.content,
@@ -193,7 +195,7 @@ export async function formatInboundEnvelope(
193195

194196
const header = `[Discord ${channelLabel}] @${senderName} (${timestamp})`;
195197
return {
196-
formattedContent: `${header}: ${rawContent}${replyContextText}`,
198+
formattedContent: `${header}: ${sanitizeReplyReferenceText(rawContent)}${replyContextText}`,
197199
chatType,
198200
};
199201
}

0 commit comments

Comments
 (0)