main
tag: launch-2026-06-01
tag: magicmirror-v0.1.1
tag: magicmirror-v0.3.0
tag: mnw-cli-v0.1.2
tag: mnw-cli-v0.1.3
tag: mnw-cli-v0.1.4
tag: pom-v0.4.1
tag: pom-v0.4.2
tag: pom-v0.4.3
tag: pom-v0.4.4
tag: pom-v0.4.5
tag: wam-v0.3.0
tag: wam-v0.3.1
Files
Commits
Tags
Notes
Issues
server: minor audit polish (5 fixes from Ultra Fuzz Run #1)
- validate.rs: render "Must be at least 2 characters" for 1-char
slugs across project/collection/blog endpoints; empty stays blank
- promo_codes.rs:291: document why the final param_idx increment is
elided (unused_assignments) so the next added field knows to restore
- main.rs: explicit .with_http_only(true) on SessionManagerLayer
- versions.rs: LEAST(SUM, i64::MAX)::BIGINT clamp before cast to guard
against pathological row counts overflowing the i64
- billing.rs: tip-refund lookup now logs an explicit error line via
inspect_err before propagating
Co-Authored-By
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 files changed,
+48 insertions,
-8 deletions
113
113
114
114
let session_layer = SessionManagerLayer::new(session_store)
115
115
.with_secure(secure_cookies)
116
+
.with_http_only(true)
116
117
.with_same_site(SameSite::Lax) // Lax allows session on top-level navigations (OAuth redirects)
117
118
.with_expiry(Expiry::OnInactivity(CookieDuration::days(
118
119
constants::SESSION_EXPIRY_DAYS,
288
288
}
289
289
if max_uses.is_some() {
290
290
sets.push(format!("max_uses = ${param_idx}"));
291
-
// param_idx += 1;
291
+
// Final SET clause; param_idx is never read after this point, so the
292
+
// increment is elided to avoid an unused_assignments warning. Restore
293
+
// it if a new optional field is added below.
292
294
}
293
295
294
296
if sets.is_empty() {
317
317
/// Sum all version file sizes for a given item (for storage decrement on item delete).
318
318
#[tracing::instrument(skip_all)]
319
319
pub async fn sum_file_sizes_for_item(pool: &PgPool, item_id: super::ItemId) -> Result<i64> {
320
+
// SUM over many bigints widens to NUMERIC in Postgres; cap at i64::MAX
321
+
// before casting back to BIGINT so a pathological row count can't overflow
322
+
// the i64 the rest of the codebase passes around.
320
323
let total: i64 = sqlx::query_scalar(
321
-
"SELECT COALESCE(SUM(file_size_bytes)::BIGINT, 0) FROM versions WHERE item_id = $1 AND file_size_bytes IS NOT NULL",
324
+
"SELECT COALESCE(LEAST(SUM(file_size_bytes), 9223372036854775807)::BIGINT, 0) FROM versions WHERE item_id = $1 AND file_size_bytes IS NOT NULL",
322
325
)
323
326
.bind(item_id)
324
327
.fetch_one(pool)
70
70
auth: AuthUser,
71
71
axum::Form(form): axum::Form<SlugForm>,
72
72
) -> impl IntoResponse {
73
-
if form.slug.len() < 2 {
73
+
if form.slug.is_empty() {
74
74
return Html(String::new());
75
75
}
76
+
if form.slug.len() < 2 {
77
+
return Html(
78
+
SaveStatusTemplate {
79
+
success: false,
80
+
message: "Must be at least 2 characters".to_string(),
81
+
}
82
+
.render_string(),
83
+
);
84
+
}
76
85
77
86
let slug = match Slug::new(&form.slug) {
78
87
Ok(s) => s,
119
128
auth: AuthUser,
120
129
axum::Form(form): axum::Form<SlugForm>,
121
130
) -> impl IntoResponse {
122
-
if form.slug.len() < 2 {
131
+
if form.slug.is_empty() {
123
132
return Html(String::new());
124
133
}
134
+
if form.slug.len() < 2 {
135
+
return Html(
136
+
SaveStatusTemplate {
137
+
success: false,
138
+
message: "Must be at least 2 characters".to_string(),
139
+
}
140
+
.render_string(),
141
+
);
142
+
}
125
143
126
144
let slug = match Slug::new(&form.slug) {
127
145
Ok(s) => s,
152
170
auth: AuthUser,
153
171
axum::Form(form): axum::Form<BlogSlugForm>,
154
172
) -> impl IntoResponse {
155
-
if form.slug.len() < 2 {
173
+
if form.slug.is_empty() {
156
174
return Html(String::new());
157
175
}
176
+
if form.slug.len() < 2 {
177
+
return Html(
178
+
SaveStatusTemplate {
179
+
success: false,
180
+
message: "Must be at least 2 characters".to_string(),
181
+
}
182
+
.render_string(),
183
+
);
184
+
}
158
185
159
186
let slug = match Slug::new(&form.slug) {
160
187
Ok(s) => s,
344
344
);
345
345
} else {
346
346
// No transaction found — check if this was a tip refund
347
-
if db::tips::refund_tip_by_payment_intent(&state.db, payment_intent_id)
347
+
let tip_refunded = db::tips::refund_tip_by_payment_intent(&state.db, payment_intent_id)
348
348
.await
349
-
.context("refund tip")?
350
-
{
349
+
.inspect_err(|e| {
350
+
tracing::error!(
351
+
payment_intent_id = %payment_intent_id,
352
+
error = ?e,
353
+
"tip refund lookup failed"
354
+
);
355
+
})
356
+
.context("refund tip")?;
357
+
if tip_refunded {
351
358
tracing::info!(payment_intent_id = %payment_intent_id, "tip refund processed");
352
359
} else {
353
360
// No matching transaction or tip — the payment webhook likely hasn't