Skip to content

Commit fe1327b

Browse files
committed
Security hardening, Docker support, and test suite
- Fix SSRF: DNS resolution + private IP blocking (IPv4/IPv6/mapped/6to4/Teredo) with pinned HTTP agents - Fix path traversal: random filenames with extension allowlist - Add magic bytes validation (JPEG, PNG, GIF, BMP, WebP with sub-header check) - Add per-user rate limiting (5s cooldown) and global concurrency limit (10 max) - Add error sanitization via UserFacingError class, no internal details leaked - Fix ephemeral errors: validate before deferReply - Fix similarity threshold double-scaling, pass 0-100 directly - Fix ActivityType enum, remove unnecessary intents (MessageContent, GuildMessages) - Lazy AWS client init using default credential provider chain - Async file I/O throughout, per-request cleanup (race-safe) - Restrict attachment downloads to Discord CDN origin - Add Dockerfile: multi-stage, pinned digest, tini init, non-root, NODE_ENV=production - Add .dockerignore - Add 110 unit tests (bun test) covering SSRF, magic bytes, URL validation, IPv6 edge cases - Update deps: dotenv 16->17, undici override 6.24.1 (fixes 4 vulns) - Switch to bun lockfile, update engine to >=18.0.0 - Update README with Docker instructions, security docs, bun commands
1 parent b52d89e commit fe1327b

File tree

9 files changed

+1268
-370
lines changed

9 files changed

+1268
-370
lines changed

.dockerignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
node_modules
2+
temp
3+
tests
4+
.env
5+
.env.*
6+
.git
7+
.gitignore
8+
Dockerfile
9+
.dockerignore
10+
CLAUDE.md
11+
README.md
12+
CITATION.cff
13+
assets
14+
*.md
15+
*.log
16+
.DS_Store
17+
.vscode
18+
.idea
19+
.github

Dockerfile

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
FROM node:22-alpine@sha256:8094c002d08262dba12645a3b4a15cd6cd627d30bc782f53229a2ec13ee22a00 AS deps
2+
3+
WORKDIR /app
4+
COPY package.json ./
5+
RUN npm install --omit=dev --ignore-scripts
6+
7+
FROM node:22-alpine@sha256:8094c002d08262dba12645a3b4a15cd6cd627d30bc782f53229a2ec13ee22a00 AS runtime
8+
9+
RUN apk add --no-cache tini
10+
RUN addgroup -S bot && adduser -S bot -G bot
11+
12+
WORKDIR /app
13+
14+
ENV NODE_ENV=production
15+
16+
COPY --from=deps /app/node_modules ./node_modules
17+
COPY package.json index.js deploy-commands.js ./
18+
COPY commands/ commands/
19+
20+
RUN mkdir -p temp && chown bot:bot temp && chmod 700 temp
21+
22+
LABEL org.opencontainers.image.source="https://github.com/gl0bal01/discord-amazon-rekognition"
23+
LABEL org.opencontainers.image.description="Discord bot with AWS Rekognition integration"
24+
LABEL org.opencontainers.image.licenses="MIT"
25+
26+
USER bot
27+
28+
STOPSIGNAL SIGTERM
29+
ENTRYPOINT ["/sbin/tini", "--"]
30+
CMD ["node", "index.js"]

README.md

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<div align="center">
44

55
[![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit/)
6-
[![Node.js Version](https://img.shields.io/badge/node-%3E%3D16.9.0-brightgreen.svg)](https://nodejs.org/)
6+
[![Node.js Version](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)
77
[![Discord.js](https://img.shields.io/badge/discord.js-v14.16.3-blue.svg)](https://discord.js.org/)
88
[![AWS SDK](https://img.shields.io/badge/AWS_SDK-v3.667.0-orange.svg)](https://aws.amazon.com/sdk-for-javascript/)
99
[![DOI](https://zenodo.org/badge/1005680658.svg)](https://doi.org/10.5281/zenodo.15722656)
@@ -133,7 +133,8 @@ Compare faces between two images with similarity scoring.
133133

134134
## 📋 Prerequisites
135135

136-
- **Node.js** v16.9.0 or higher
136+
- **Node.js** v18.0.0 or higher (or **Bun** v1.0+)
137+
- **Docker** (optional, recommended for production)
137138
- **Discord Application** and bot token
138139
- **AWS Account** with Rekognition access
139140
- **AWS IAM User** with appropriate permissions
@@ -148,7 +149,7 @@ cd discord-amazon-rekognition
148149

149150
### 2. Install Dependencies
150151
```bash
151-
npm install
152+
bun install
152153
```
153154

154155
### 3. Set Up Environment Variables
@@ -236,22 +237,41 @@ Your bot needs these permissions:
236237
### 1. Deploy Commands
237238
```bash
238239
# Development (instant deployment to test server)
239-
npm run deploy
240+
bun run deploy
240241

241242
# Production (global deployment - takes up to 1 hour)
242-
npm run deploy:global
243+
bun run deploy:global
243244
```
244245

245246
### 2. Start the Bot
246247
```bash
247248
# Production
248-
npm start
249+
bun run start
249250

250251
# Development with auto-restart
251-
npm run dev
252+
bun run dev
252253
```
253254

254-
### 3. Verify Startup
255+
### 3. Docker (Recommended for Production)
256+
```bash
257+
# Build
258+
docker build -t rekognition-bot .
259+
260+
# Run
261+
docker run -d \
262+
--name rekognition-bot \
263+
--read-only \
264+
--tmpfs /app/temp:rw,noexec,nosuid,size=100m \
265+
--memory=512m \
266+
--cpus=1.0 \
267+
--pids-limit=50 \
268+
--security-opt=no-new-privileges:true \
269+
--env-file .env \
270+
--restart unless-stopped \
271+
rekognition-bot
272+
```
273+
274+
### 4. Verify Startup
255275
Look for these startup messages:
256276
```
257277
✅ Loaded command: rekognition
@@ -280,10 +300,14 @@ https://discord.com/api/oauth2/authorize?client_id=YOUR_CLIENT_ID&permissions=21
280300
discord-amazon-rekognition/
281301
├── commands/
282302
│ └── rekognition.js # Main Rekognition command
283-
├── temp/ # Temporary file storage
303+
├── tests/
304+
│ └── rekognition.test.js # Unit tests (bun test)
305+
├── temp/ # Temporary file storage (auto-created)
306+
├── .dockerignore # Docker build exclusions
284307
├── .env.example # Environment variables template
285308
├── .gitignore # Git ignore rules
286309
├── deploy-commands.js # Command deployment script
310+
├── Dockerfile # Multi-stage production container
287311
├── index.js # Main bot application
288312
├── LICENSE # MIT license
289313
├── package.json # Dependencies and scripts
@@ -338,7 +362,7 @@ discord-amazon-rekognition/
338362
| **Supported Formats** | JPEG, PNG |
339363
| **Max Image Size** | 5MB (JPEG), 8MB (PNG) |
340364
| **Accuracy Rate** | 95%+ for most features |
341-
| **Concurrent Users** | Unlimited |
365+
| **Concurrent Requests** | 10 (configurable) |
342366
| **Uptime** | 99.9% |
343367

344368

@@ -366,7 +390,7 @@ discord-amazon-rekognition/
366390

367391
#### ❌ Commands not appearing
368392
**Solution:**
369-
- Run `npm run deploy` to update commands
393+
- Run `bun run deploy` to update commands
370394
- Check `CLIENT_ID` is correct in `.env`
371395
- Wait up to 1 hour for global command deployment
372396

@@ -400,16 +424,24 @@ Monitor your usage at [AWS Billing Console](https://console.aws.amazon.com/billi
400424

401425
### Data Privacy
402426
- **No Image Storage**: Images are processed and immediately deleted
403-
- **Temporary Files**: Auto-cleanup after 60 seconds
427+
- **Temporary Files**: Auto-cleanup after 10 seconds per request
404428
- **AWS Security**: All data encrypted in transit and at rest
405429
- **No Logging**: Personal image data is never logged
406430

431+
### Security Hardening
432+
- **SSRF Protection**: DNS resolution + private IP blocking (IPv4, IPv6, IPv4-mapped IPv6, 6to4, Teredo) with pinned HTTP agents to prevent DNS rebinding
433+
- **Path Traversal Prevention**: Random filenames with extension allowlisting
434+
- **Magic Bytes Validation**: File signatures verified (JPEG, PNG, GIF, BMP, WebP)
435+
- **Rate Limiting**: Per-user cooldown + global concurrency limit
436+
- **Error Sanitization**: Internal errors never exposed to users
437+
- **Docker**: Runs as non-root, read-only filesystem, tini init, pinned base image
438+
407439
### Best Practices
408-
- Store AWS credentials securely
409-
- Use IAM roles with minimal permissions
410-
- Regularly rotate access keys
440+
- Use IAM roles (preferred) or static credentials with minimal permissions
441+
- Deploy with Docker using the recommended `docker run` flags
442+
- Regularly rotate access keys if using static credentials
411443
- Monitor AWS CloudTrail logs
412-
- Keep dependencies updated
444+
- Keep dependencies updated (`bun update`)
413445

414446
### Content Moderation
415447
The bot includes automatic content moderation features to detect:
@@ -439,12 +471,11 @@ const response = await client.send(command);
439471
```
440472

441473
### Testing
442-
Test with various image types:
443-
- Different resolutions
444-
- Various lighting conditions
445-
- Multiple faces
446-
- Text-heavy images
447-
- Different file formats
474+
```bash
475+
bun test
476+
```
477+
478+
110 unit tests covering SSRF protection, magic bytes validation, URL validation, extension sanitization, and IPv6 edge cases.
448479

449480

450481
## 🔗 Quick Links

0 commit comments

Comments
 (0)