-
Notifications
You must be signed in to change notification settings - Fork 37
Fix security vulnerabilities, bugs, and code quality issues #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # Required | ||
| OPENROUTER_API_KEY=your_openrouter_api_key_here | ||
|
|
||
| # Admin panel authentication (required for admin features) | ||
| ADMIN_SECRET=your_secure_admin_passcode_here | ||
|
|
||
| # Server | ||
| PORT=5109 | ||
| NODE_ENV=production | ||
|
|
||
| # Database | ||
| DATABASE_PATH=quipslop.sqlite | ||
|
|
||
| # Rate limiting (requests per minute) | ||
| WS_UPGRADE_LIMIT_PER_MIN=20 | ||
| HISTORY_LIMIT_PER_MIN=120 | ||
| ADMIN_LIMIT_PER_MIN=10 | ||
|
|
||
| # WebSocket limits | ||
| MAX_WS_GLOBAL=100000 | ||
| MAX_WS_PER_IP=8 | ||
|
|
||
| # History pagination | ||
| MAX_HISTORY_PAGE=100000 | ||
| MAX_HISTORY_LIMIT=50 | ||
| HISTORY_CACHE_TTL_MS=5000 | ||
| MAX_HISTORY_CACHE_KEYS=500 | ||
|
|
||
| # Streaming (optional, for scripts/stream-browser.ts) | ||
| TWITCH_STREAM_KEY=your_twitch_stream_key_here | ||
| STREAM_TARGET_SIZE=1920x1080 |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,6 +9,13 @@ RUN bun install --frozen-lockfile --production | |||||||||||||||||
| COPY . . | ||||||||||||||||||
|
|
||||||||||||||||||
| ENV NODE_ENV=production | ||||||||||||||||||
| EXPOSE ${PORT:-5109} | ||||||||||||||||||
| EXPOSE 5109 | ||||||||||||||||||
|
|
||||||||||||||||||
| # Run as non-root user | ||||||||||||||||||
| RUN addgroup --system --gid 1001 app && adduser --system --uid 1001 --ingroup app app | ||||||||||||||||||
| USER app | ||||||||||||||||||
|
Comment on lines
+14
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing All files under Add 🔒 Proposed fix-RUN addgroup --system --gid 1001 app && adduser --system --uid 1001 --ingroup app app
+RUN addgroup --system --gid 1001 app && \
+ adduser --system --uid 1001 --ingroup app app && \
+ chown -R app:app /app
USER appAlternatively, use +RUN addgroup --system --gid 1001 app && adduser --system --uid 1001 --ingroup app app
COPY package.json bun.lock ./
RUN bun install --frozen-lockfile --production
-COPY . .
+COPY --chown=app:app . .
+USER app📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ | ||||||||||||||||||
| CMD bun -e "fetch('http://localhost:' + (process.env.PORT || 5109) + '/healthz').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))" | ||||||||||||||||||
|
|
||||||||||||||||||
| CMD ["bun", "server.ts"] | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import { Database } from "bun:sqlite"; | ||
| const db = new Database("quipslop.sqlite"); | ||
| const dbPath = process.env.DATABASE_PATH ?? "quipslop.sqlite"; | ||
| const db = new Database(dbPath); | ||
| const rows = db.query("SELECT id, num FROM rounds ORDER BY id DESC LIMIT 20").all(); | ||
| console.log(rows); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -199,19 +199,19 @@ function ContestantCard({ | |
| vote{voteCount !== 1 ? "s" : ""} | ||
| </span> | ||
| <span className="vote-meta__dots"> | ||
| {voters.map((v, i) => { | ||
| {voters.map((v) => { | ||
| const logo = getLogo(v.voter.name); | ||
| return logo ? ( | ||
| <img | ||
| key={i} | ||
| key={v.voter.name} | ||
| src={logo} | ||
| alt={v.voter.name} | ||
| title={v.voter.name} | ||
| className="voter-dot" | ||
| /> | ||
| ) : ( | ||
| <span | ||
| key={i} | ||
| key={v.voter.name} | ||
| className="voter-dot voter-dot--letter" | ||
| style={{ color: getColor(v.voter.name) }} | ||
| title={v.voter.name} | ||
|
|
@@ -410,14 +410,20 @@ function App() { | |
| const wsUrl = `${wsProtocol}//${window.location.host}/ws`; | ||
| let ws: WebSocket; | ||
| let reconnectTimer: ReturnType<typeof setTimeout>; | ||
| let reconnectAttempt = 0; | ||
|
|
||
| let knownVersion: string | null = null; | ||
| function connect() { | ||
| ws = new WebSocket(wsUrl); | ||
| ws.onopen = () => setConnected(true); | ||
| ws.onopen = () => { | ||
| setConnected(true); | ||
| reconnectAttempt = 0; | ||
| }; | ||
| ws.onclose = () => { | ||
| setConnected(false); | ||
| reconnectTimer = setTimeout(connect, 2000); | ||
| const delay = Math.min(1000 * Math.pow(2, reconnectAttempt), 30000) + Math.random() * 1000; | ||
| reconnectAttempt++; | ||
| reconnectTimer = setTimeout(connect, delay); | ||
| }; | ||
|
Comment on lines
+418
to
427
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WebSocket cleanup leaves an uncancellable reconnect timer.
This is especially visible in React StrictMode (effects are mounted → cleaned up → re-mounted): the async Fix: null out 🔒 Proposed fix return () => {
clearTimeout(reconnectTimer);
+ ws.onclose = null; // prevent async onclose from scheduling a reconnect after cleanup
ws?.close();
};Also applies to: 443-446 🤖 Prompt for AI Agents |
||
| ws.onmessage = (e) => { | ||
| const msg: ServerMessage = JSON.parse(e.data); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟠 High
Dockerfile:15The
appuser won't have write permissions to/appsinceCOPYruns as root. SQLite database creation will fail. Consider addingRUN chown -R app:app /appbeforeUSER app.🚀 Reply "fix it for me" or copy this AI Prompt for your agent: