Skip to content

Commit ef6546c

Browse files
Escape HTML in messages and usernames
1 parent de68141 commit ef6546c

File tree

3 files changed

+18
-4
lines changed

3 files changed

+18
-4
lines changed

index.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
getRecentMessages,
66
type User,
77
} from "./src/db/database";
8-
import { LIMITS, validateInput } from "./src/constants";
8+
import { LIMITS, validateInput, escapeHtml } from "./src/constants";
99
import crypto from "crypto";
1010

1111
const port = process.env.PORT || 5177;
@@ -212,13 +212,15 @@ const server: any = Bun.serve({
212212
data.content,
213213
LIMITS.MESSAGE_MAX_LENGTH
214214
);
215-
const msg = await createMessage(user.id, validatedContent);
215+
// Escape HTML in the message
216+
const safeContent = escapeHtml(validatedContent);
217+
const msg = await createMessage(user.id, safeContent);
216218
server.publish(
217219
"chat",
218220
JSON.stringify({
219221
type: "message",
220222
username: user.username,
221-
content: validatedContent,
223+
content: safeContent,
222224
timestamp: new Date().toISOString(),
223225
})
224226
);

src/constants.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ export const LIMITS = {
44
MESSAGE_MAX_LENGTH: 2000,
55
} as const;
66

7+
export function escapeHtml(unsafe: string): string {
8+
return unsafe
9+
.replace(/&/g, "&")
10+
.replace(/</g, "&lt;")
11+
.replace(/>/g, "&gt;")
12+
.replace(/"/g, "&quot;")
13+
.replace(/'/g, "&#039;");
14+
}
15+
716
export function validateInput(input: string, maxLength: number): string {
817
if (!input || typeof input !== "string") {
918
throw new Error("Invalid input");

src/db/database.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Database } from "bun:sqlite";
22
import * as bcrypt from "bcryptjs";
3-
import { LIMITS, validateInput } from "../constants";
3+
import { LIMITS, validateInput, escapeHtml } from "../constants";
44

55
const DB_PATH = process.env.DB_PATH || `${process.cwd()}/chat.db`;
66
const SCHEMA_PATH =
@@ -40,6 +40,9 @@ export const createUser = async (
4040
username = validateInput(username, LIMITS.USERNAME_MAX_LENGTH);
4141
password = validateInput(password, LIMITS.PASSWORD_MAX_LENGTH);
4242

43+
// Escape HTML in username
44+
username = escapeHtml(username);
45+
4346
const hashedPassword = await bcrypt.hash(password, 10);
4447
try {
4548
const stmt = db.prepare(

0 commit comments

Comments
 (0)