Skip to content

Commit

Permalink
fix(security): sanitize path and prevent shell scripts (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
wellwelwel authored Feb 28, 2024
1 parent 014e27d commit 39f7d8c
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 35 deletions.
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
[ci-image]: https://img.shields.io/github/actions/workflow/status/wellwelwel/poku/ci.yml?event=push&style=flat&label=CI&branch=main
[ql-url]: https://github.com/wellwelwel/poku/actions/workflows/codeql.yml?query=branch%3Amain
[ql-image]: https://img.shields.io/github/actions/workflow/status/wellwelwel/poku/codeql.yml?event=push&style=flat&label=Code%20QL&branch=main
[license-url]: https://github.com/wellwelwel/poku/blob/main/LICENSE
[license-image]: https://img.shields.io/npm/l/poku.svg?maxAge=2592000&color=9c88ff

# Poku

Expand All @@ -23,6 +25,7 @@
[![TypeScript Version][typescript-version-image]][typescript-url]
[![GitHub Workflow Status (with event)][ci-image]][ci-url]
[![GitHub Workflow Status (with event)][ql-image]][ql-url]
[![License][license-image]][license-url]

Enjoying **Poku**? Consider giving him a star ⭐️

Expand Down Expand Up @@ -184,10 +187,22 @@ I'm continuously working to improve **Poku**. If you've got something interestin

## Acknowledgements

- [**Contributors**](https://github.com/wellwelwel/poku/graphs/contributors)
- [**Contributors**](https://github.com/wellwelwel/poku/graphs/contributors).

---

## Contributing

Please check the [_CONTRIBUTING.md_](./CONTRIBUTING.md) for instructions 🚀
Please check the [**CONTRIBUTING.md**](./CONTRIBUTING.md) for instructions 🚀

---

## License

Poku is under the [**MIT** License](./LICENSE).

---

## Security Policy

Please check the [**SECURITY.md**](./SECURITY.md) and the section [**Is Poku Safe?**](https://poku.dev/docs/security) from Documentation.
27 changes: 22 additions & 5 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Security Policy

## Is Poku Safe?

**Poku** is an open-source project, so you can see both the [Source Code on **GitHub** Repository](https://github.com/wellwelwel/poku) and the [Distribution Code on **NPM**](https://www.npmjs.com/package/poku?activeTab=code).

### Why does Poku use `child_process`?

Some test runners use **`eval`**, **Poku** prefers to use **`spawn`** to create a isolated process securely for each test file.

---

## Protective Measures

See the [**Protective Measures**](https://poku.dev/docs/security#protective-measures) in the documentation.

---

## Supported Versions

Currently, security updates will be applied to the following versions of **Poku**:
Expand All @@ -9,17 +25,18 @@ Currently, security updates will be applied to the following versions of **Poku*
| 1.x.x | :white_check_mark: |
| 0.x.x | :x: |

## Reporting a Vulnerability
---

> **Please, give Detailed Reports**
## Reporting a Vulnerability

- Please, give detailed reports
- Include steps to reproduce the vulnerability, and if possible, a patch or workaround.
- Include the specific version of **Poku** you are using.

Please report it privately: https://github.com/wellwelwel/poku/security/advisories.

---
- Once the issue has been resolved, you will be attributed a part of the report.

> If you wish it, once the issue has been resolved, you will be attributed a part of the report.
---

Let's keeping **Poku** safe 🩵
Let's keeping **Poku** safe 🐷
16 changes: 13 additions & 3 deletions src/modules/list-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ import fs from 'node:fs';
import path from 'node:path';
import type { Configs } from '../@types/list-files.js';

export const sanitizePath = (input: string, ensureTarget?: boolean): string => {
const sanitizedPath = input
.replace(/[/\\]+/g, path.sep) // adapting slashes according to OS
.replace(/(\.\.(\/|\\|$))+/g, '') // ensure the current path level
.replace(/[<>:|^?*]+/g, ''); // removing unusual path characters

// Preventing absolute path access
return ensureTarget ? sanitizedPath.replace(/^[/\\]/, './') : sanitizedPath;
};

export const escapeRegExp = (string: string) =>
string.replace(/[.*{}[\]\\]/g, '\\$&');

Expand All @@ -15,7 +25,7 @@ export const listFiles = (
files: string[] = [],
configs?: Configs
) => {
const currentFiles = fs.readdirSync(dirPath);
const currentFiles = fs.readdirSync(sanitizePath(dirPath));
const defaultRegExp = /\.(test|spec)\./i;
const filter: RegExp =
(envFilter
Expand All @@ -31,7 +41,7 @@ export const listFiles = (
: undefined;

for (const file of currentFiles) {
const fullPath = path.join(dirPath, file);
const fullPath = sanitizePath(path.join(dirPath, file));

if (/node_modules/.test(fullPath)) continue;
if (exclude && exclude.some((regex) => regex.test(fullPath))) continue;
Expand All @@ -45,4 +55,4 @@ export const listFiles = (
};

export const publicListFiles = (targetDir: string, configs?: Configs) =>
listFiles(targetDir, [], configs);
listFiles(sanitizePath(targetDir), [], configs);
1 change: 1 addition & 0 deletions src/services/run-test-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export const runTestFile = (

const child = spawn(runtime!, runtimeArguments, {
stdio: ['inherit', 'pipe', 'pipe'],
shell: false,
env: {
...process.env,
FILE: configs?.parallel ? fileRelative : '',
Expand Down
4 changes: 2 additions & 2 deletions src/services/run-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { EOL } from 'node:os';
import path from 'node:path';
import { runner } from '../helpers/runner.js';
import { indentation } from '../helpers/indentation.js';
import { listFiles } from '../modules/list-files.js';
import { listFiles, sanitizePath } from '../modules/list-files.js';
import { hr } from '../helpers/hr.js';
import { format } from '../helpers/format.js';
import { runTestFile } from './run-test-file.js';
Expand All @@ -20,7 +20,7 @@ export const runTests = async (
configs?: Configs
): Promise<boolean> => {
const cwd = process.cwd();
const testDir = path.join(cwd, dir);
const testDir = path.join(cwd, sanitizePath(dir));
const currentDir = path.relative(cwd, testDir);
const files = listFiles(testDir, undefined, configs);
const totalTests = files.length;
Expand Down
8 changes: 0 additions & 8 deletions website/docs/examples/back-to-the-roots/_category_.json

This file was deleted.

2 changes: 2 additions & 0 deletions website/docs/examples/beforeEach.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ node ./test/run.test.js

> Or `npx tsx ./test/run.test.ts` for **TypeScript**.
<hr />

:::tip
**Poku**'s `assert` will use the message exactly as it is when using `describe` or `it`. <br />
Your **Poku** is waiting for you 🐷✨
Expand Down
36 changes: 23 additions & 13 deletions website/docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -51,25 +51,23 @@ Enjoying **Poku**? Consider giving him a star ⭐️

## Why Poku?

Don't worry about `describe`, `it`, `beforeEach` and everything else 🚀

> You don't need to learn what you already know ✨
<div className='features black'>
<p>
<Success />
<span>Designed to be highly intuitive</span>
</p>
<p>
<Success />
<span>No constraints or rules, code in your own signature style</span>
<span>You don't need to learn what you already know ✨</span>
</p>
<p>
<Success />
<Link to='/'>Compare Poku with the Most Popular Test Runners</Link>
<span>
Don't worry about `describe`, `it`, `beforeEach` and everything else 🚀
</span>
</p>
</div>

<br />

- [**Compare Poku with the Most Popular Test Runners 🧪**](/docs/comparing)

<hr />

## **Install**
Expand Down Expand Up @@ -174,7 +172,7 @@ deno run npm:poku targetDir

## Documentation

> Initially, the [documentation](/docs/category/documentation) is based on **Node.js** usage, but you can use all the options normally for both **Bun** and **Deno**.
> Initially, the [**documentation**](/docs/category/documentation) and [**examples**](/docs/category/examples) are based on **Node.js** usage, but you can use all the options normally for both **Bun** and **Deno**.
<hr />

Expand All @@ -186,10 +184,22 @@ I'm continuously working to improve **Poku**. If you've got something interestin

## Acknowledgements

- [**Contributors**](https://github.com/wellwelwel/poku/graphs/contributors)
- [**Contributors**](https://github.com/wellwelwel/poku/graphs/contributors).

<hr />

## Contributing

Please check the [_CONTRIBUTING.md_](https://github.com/wellwelwel/poku/blob/main/CONTRIBUTING.md) for instructions 🚀
Please check the [**CONTRIBUTING.md**](https://github.com/wellwelwel/poku/blob/main/CONTRIBUTING.md) for instructions 🚀

<hr />

## License

Poku is under the [**MIT License**](https://github.com/wellwelwel/poku/blob/main/LICENSE).

<hr />

## Security Policy

Please check the [**SECURITY.md**](https://github.com/wellwelwel/poku/blob/main/SECURITY.md) and the section [**Is Poku Safe?**](/docs/security) from Documentation.
26 changes: 26 additions & 0 deletions website/docs/security.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Is Poku Safe?

**Poku** is an open-source project, so you can see both the [Source Code on **GitHub** Repository](https://github.com/wellwelwel/poku) and the [Distribution Code on **NPM**](https://www.npmjs.com/package/poku?activeTab=code).

## Why does Poku use `child_process`?

Some test runners use **`eval`**, **Poku** prefers to use **`spawn`** to create a isolated process securely for each test file.

## Protective Measures

- Blocks access above target directory by filtering `../` and `/` paths, for example:
- `/root` will be sanitized to `./root`
- `../../etc/secret` will be sanitized to `./etc/secret`
- Normalizes paths according to the OS, allowing all collaborators to use the same path, each using their own OS:
- `\` for **Windows**
- `/` for **Linux** and **macOS**
- Normalizes paths by filtering unusual path characters, for example:
- `<>:|^?*`
- Prevents shell scripts by setting `shell` to `false` in **`spawn`** options, ensuring that only secure arguments will be used.
- Every **RegExp** is prev-tested using the [**ReDoS Checker**](https://devina.io/redos-checker).

## Security Policy

:::info
See the [**Security Policy** on **GitHub** repository](https://github.com/wellwelwel/poku/blob/main/SECURITY.md).
:::
1 change: 1 addition & 0 deletions website/sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const sidebars: SidebarsConfig = {
'index',
'comparing',
'overview',
'security',
{
type: 'category',
label: 'Documentation',
Expand Down
3 changes: 1 addition & 2 deletions website/src/css/custom.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

[data-theme] {
blockquote {
font-size: 0.95rem;
font-size: 0.875rem;
}
}

Expand Down Expand Up @@ -131,7 +131,6 @@ html[data-theme='dark'] {
color: #b9bfdc;

blockquote {
font-size: 13px;
color: #8188ab;
}

Expand Down

0 comments on commit 39f7d8c

Please sign in to comment.