Skip to content

Commit

Permalink
fix: security issues
Browse files Browse the repository at this point in the history
  • Loading branch information
CompuIves committed Dec 12, 2023
1 parent 2442db8 commit 1501826
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 29 deletions.
33 changes: 33 additions & 0 deletions .codesandbox/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
// These tasks will run in order when initializing your CodeSandbox project.
"setupTasks": [
{
"name": "Install Dependencies",
"command": "pnpm install"
}
],

// These tasks can be run from CodeSandbox. Running one will open a log in the app.
"tasks": {
"dev": {
"name": "dev",
"command": "pnpm dev",
"runAtStart": true
},
"build": {
"name": "build",
"command": "pnpm build",
"runAtStart": false
},
"test": {
"name": "test",
"command": "pnpm test",
"runAtStart": false
},
"start": {
"name": "start",
"command": "pnpm start",
"runAtStart": false
}
}
}
22 changes: 22 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
{
"name": "Node.js & TypeScript",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye"

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install",

// Configure tool-specific properties.
// "customizations": {},

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
24 changes: 12 additions & 12 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const BUCKET_NAME = "prod-packager-packages.codesandbox.io";
let lastClean = Date.now();
const MAX_CLEAN_INTERVAL = 1000 * 60 * 60 * 1; // Every hour
function getFileFromS3(
keyPath: string
keyPath: string,
): Promise<aws.S3.GetObjectOutput | null> {
return new Promise((resolve, reject) => {
if (!BUCKET_NAME) {
Expand All @@ -40,15 +40,15 @@ function getFileFromS3(
}

resolve(packageData);
}
},
);
});
}

function saveFileToS3(
keyPath: string,
content: string,
contentType: string = "application/json"
contentType: string = "application/json",
): Promise<aws.S3.PutObjectOutput> {
return new Promise((resolve, reject) => {
if (!BUCKET_NAME) {
Expand All @@ -73,7 +73,7 @@ function saveFileToS3(
}

resolve(response);
}
},
);
});
}
Expand All @@ -84,7 +84,7 @@ function getBucketPath(dependency: string, version: string) {

async function getCache(
dependency: string,
version: string
version: string,
): Promise<{ body: string; ETag: string | undefined } | undefined> {
const bucketPath = getBucketPath(dependency, version);

Expand Down Expand Up @@ -114,7 +114,7 @@ queue.on("active", () => {
console.log(
`Working on item #${++count}. Size: ${queue.size} Pending: ${
queue.pending
}`
}`,
);
});

Expand All @@ -131,7 +131,7 @@ app.get("/_stats", async (_req, res) => {
try {
const dirs = await fs.promises.readdir(path.resolve("/tmp", "typings"));
const results = await Promise.all(
dirs.map((dir) => fs.promises.stat(path.resolve("/tmp", "typings", dir)))
dirs.map((dir) => fs.promises.stat(path.resolve("/tmp", "typings", dir))),
);

res.end(
Expand All @@ -152,7 +152,7 @@ app.get("/_stats", async (_req, res) => {

return 0;
}),
})
}),
);
} catch (e) {
res.end(JSON.stringify({ error: e.message }));
Expand All @@ -162,7 +162,7 @@ app.get("/_stats", async (_req, res) => {
app.get("/api/v8/:dependency", async (req, res) => {
try {
const depQuery = decodeURIComponent(
req.params.dependency.replace(/\.json$/, "")
req.params.dependency.replace(/\.json$/, ""),
);

res.setHeader("Content-Type", `application/json`);
Expand Down Expand Up @@ -208,13 +208,13 @@ app.get("/api/v8/:dependency", async (req, res) => {
} catch (e) {
console.log("Error", e.message);
res.statusCode = 422;
res.setHeader("Content-Type", `application/json`);
res.end(
JSON.stringify({
status: "error",
files: {},
error: e.message,
stack: e.stack,
})
}),
);
} finally {
if (
Expand All @@ -231,7 +231,7 @@ app.get("/api/v8/:dependency", async (req, res) => {
await cleanYarnCache();
console.log(
"Directories after cleanup",
await fs.promises.readdir(path.resolve("/tmp", "typings"))
await fs.promises.readdir(path.resolve("/tmp", "typings")),
);
} finally {
queue.concurrency = 4;
Expand Down
42 changes: 25 additions & 17 deletions src/typings.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { exec } from "child_process";
import * as fsPromises from "fs/promises";
import * as fs from "fs";
import * as path from "path";
import { parse } from "url";
Expand All @@ -22,9 +23,7 @@ export const cleanUpTime = 10 * 60 * 1000; // When 10 minutes old
export async function prepareTypingsFolder(folder: string) {
typingsFolder = folder;
// Delete any old packages due to restart of the process
if (!fs.existsSync(folder)) {
fs.mkdirSync(folder);
}
await fsPromises.mkdir(folder, { recursive: true });

try {
await rimraf(folder + "/*");
Expand Down Expand Up @@ -73,7 +72,7 @@ const TYPE_ONLY_DIRECTORIES = ["src"];

function isFileValid(path: string) {
const isTypeOnly = TYPE_ONLY_DIRECTORIES.some(
(dir) => path.indexOf("/" + dir + "/") > -1
(dir) => path.indexOf("/" + dir + "/") > -1,
);
const requiredEnding = isTypeOnly ? ".d.ts" : ".ts";

Expand Down Expand Up @@ -134,7 +133,7 @@ function cleanFiles(files: IFiles, rootPath: string) {
}

return paths.some(
(p) => p.startsWith(path.dirname(checkedPath)) && p.endsWith(".ts")
(p) => p.startsWith(path.dirname(checkedPath)) && p.endsWith(".ts"),
);
}

Expand All @@ -152,7 +151,7 @@ function cleanFiles(files: IFiles, rootPath: string) {

export function hasTypes(location: string) {
return recursive(location).then((paths) =>
paths.some((p) => p.endsWith(".d.ts"))
paths.some((p) => p.endsWith(".d.ts")),
);
}

Expand Down Expand Up @@ -183,15 +182,24 @@ export function cleanYarnCache() {
export async function extractFiles(
dependency: string,
version: string,
dependencyLocation: string
dependencyLocation: string,
): Promise<IFiles> {
console.log(`Installing ${dependency}@${version}, id: ${dependencyLocation}`);

const installQuery = version.startsWith("http")
? version
: `${dependency}@${version}`;
const dependencyFolder = path.join(typingsFolder, dependencyLocation);
await fsPromises.mkdir(dependencyFolder, { recursive: true });
await fsPromises.writeFile(
path.join(dependencyFolder, "package.json"),
JSON.stringify({
name: dependencyLocation,
version: "0.0.0",
dependencies: {
[dependency]: version,
},
}),
);
await execPromise(
`cd ${typingsFolder} && mkdir ${dependencyLocation} && cd ${dependencyLocation} && npm init -y && HOME=${typingsFolder}/${dependencyLocation} yarn add --ignore-engines --no-lockfile --non-interactive --no-progress --prod --cache-folder ./ ${installQuery}`
`cd ${typingsFolder} && mkdir ${dependencyLocation} && cd ${dependencyLocation} && npm init -y && HOME=${typingsFolder}/${dependencyLocation} yarn install --ignore-scripts --ignore-engines --no-lockfile --non-interactive --no-progress --prod --cache-folder`,
);

const dependencyPath = `${typingsFolder}/${dependencyLocation}/node_modules`;
Expand Down Expand Up @@ -223,7 +231,7 @@ interface IModuleResult {
}

export async function downloadDependencyTypings(
depQuery: string
depQuery: string,
): Promise<IModuleResult> {
const { dependency, version = "latest" } = getDependencyAndVersion(depQuery);

Expand All @@ -247,7 +255,7 @@ export async function downloadDependencyTypings(
module: files[n],
},
}),
{}
{},
);

return filesWithNoPrefix;
Expand Down Expand Up @@ -276,7 +284,7 @@ export async function downloadDependencyTypings(
"ERROR - Could not clean up " +
possiblyOldDependencyLocation +
", which has been there since " +
packageInstalls[possiblyOldDependencyLocation]
packageInstalls[possiblyOldDependencyLocation],
);
}
}
Expand Down Expand Up @@ -330,18 +338,18 @@ export default async (req: Request, res: Response) => {
status: "ok",
files: result.files,
droppedFileCount: result.droppedFileCount,
})
}),
);
} catch (e) {
console.log("Error", e.message);
res.statusCode = 422;
res.setHeader("Content-Type", `application/json`);
res.end(
JSON.stringify({
status: "error",
files: {},
error: e.message,
stack: e.stack,
})
}),
);
}
};

0 comments on commit 1501826

Please sign in to comment.