Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6fe136ae5a | |||
| 888834c8f0 | |||
| ae8f6d696e |
+2
-1
@@ -36,8 +36,9 @@ COPY package*.json ./
|
|||||||
# Install production dependencies only
|
# Install production dependencies only
|
||||||
RUN npm ci --only=production
|
RUN npm ci --only=production
|
||||||
|
|
||||||
# Copy prisma schema and migrations
|
# Copy prisma schema and migrations for runtime and hydration template
|
||||||
COPY prisma ./prisma/
|
COPY prisma ./prisma/
|
||||||
|
COPY prisma ./prisma_template/
|
||||||
|
|
||||||
# Copy built application from builder
|
# Copy built application from builder
|
||||||
COPY --from=builder /app/dist ./dist
|
COPY --from=builder /app/dist ./dist
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
# Auto-hydrate prisma directory when bind-mounted volume is empty
|
||||||
|
if [ ! -f "/app/prisma/schema.prisma" ]; then
|
||||||
|
echo "Mount is empty. Hydrating /app/prisma from /app/prisma_template..."
|
||||||
|
cp -R /app/prisma_template/. /app/prisma/
|
||||||
|
fi
|
||||||
|
|
||||||
# Run migrations
|
# Run migrations
|
||||||
npx prisma migrate deploy
|
npx prisma migrate deploy
|
||||||
|
|
||||||
|
|||||||
@@ -125,7 +125,47 @@ const respondWithValidationErrors = (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const validateSqliteHeader = (filePath: string): boolean => {
|
||||||
|
try {
|
||||||
|
const buffer = Buffer.alloc(16);
|
||||||
|
const fd = fs.openSync(filePath, "r");
|
||||||
|
const bytesRead = fs.readSync(fd, buffer, 0, 16, 0);
|
||||||
|
fs.closeSync(fd);
|
||||||
|
|
||||||
|
if (bytesRead < 16) {
|
||||||
|
console.warn("File too small to be a valid SQLite database");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SQLite format 3 header: "SQLite format 3\0" (16 bytes)
|
||||||
|
// Hex: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00
|
||||||
|
const expectedHeader = Buffer.from([
|
||||||
|
0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61,
|
||||||
|
0x74, 0x20, 0x33, 0x00,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const isValid = buffer.equals(expectedHeader);
|
||||||
|
if (!isValid) {
|
||||||
|
console.warn("Invalid SQLite file header detected", {
|
||||||
|
filePath,
|
||||||
|
header: buffer.toString("hex"),
|
||||||
|
expected: expectedHeader.toString("hex"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return isValid;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to validate SQLite header:", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const runIntegrityCheck = (filePath: string): boolean => {
|
const runIntegrityCheck = (filePath: string): boolean => {
|
||||||
|
// First validate the file header to prevent RCE attacks
|
||||||
|
if (!validateSqliteHeader(filePath)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let dbInstance: Database.Database | undefined;
|
let dbInstance: Database.Database | undefined;
|
||||||
try {
|
try {
|
||||||
dbInstance = new Database(filePath, {
|
dbInstance = new Database(filePath, {
|
||||||
|
|||||||
Reference in New Issue
Block a user