cloudflare / cloudflare/webcm-docs

Chained build-pipeline DoS: trim ReDoS (CVE-2020-7753) + unpinned CI image/action

Open
#27 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
9
Forks
4
PR merge metrics
No merged PRs in 30d

Description

Two medium-severity issues that chain into a reliable **build-pipeline DoS**:

1. `trim@0.0.1` (locked in `package-lock.json`) is vulnerable to ReDoS (CVE-2020-7753), reachable via `remark-parse` during `docusaurus build`.
2. The CI workflow that runs the build uses an **unpinned container image** and **unpinned action**, so the build environment is neither reproducible nor auditable while this is happening.

Either alone is a Medium. Together, a single crafted markdown file can hang every build (PR + daily cron), burning CI minutes on an environment you can't pin down.

## Issue 1 — ReDoS in `trim@0.0.1`

**Location:** `package-lock.json` → `node_modules/trim` (`0.0.1`), pulled in via `remark-parse@8.0.3`.

**Vulnerable code** (`trim@0.0.1/index.js`):

```js
return str.replace(/^\s*|\s*$/g, '');
```

**Reachability (verified against `remark-parse@8.0.3` source):** markdown content flows into `trim()` in `lib/tokenize/blockquote.js:87`, `paragraph.js:78`, and `list.js:261` — all of which `require('trim')`.

**PoC (measured locally, Node 22):** input `'x' + ' '.repeat(n) + 'y'`

| n | time |
|---|---|
| 1,000 | 1.0 ms |
| 4,000 | 15.8 ms |
| 8,000 | 62.8 ms |
| 16,000 | 250.8 ms |
| 32,000 | ~1 s |

Input 2x → time 4x (quadratic confirmed; ~1 MB input ≈ 15+ min single-thread hang). The fixed `trim@0.0.3` handles 512k chars in ~0.2 ms (uses native `str.trim()`), confirming the regex as the sink.

## Issue 2 — Unpinned CI components

**Location:** `.github/workflows/semgrep.yml:22,24`

```yaml
container:
image: returntocorp/semgrep # no tag/digest → :latest
steps:
- uses: actions/checkout@v3 # mutable tag, no SHA pin
```

No `permissions:` block either, so `GITHUB_TOKEN` gets default broad scopes. Any compromise/swap of the tag or image executes code in the same pipeline that builds this site.

## Chained scenario

1. Attacker opens a PR adding a docs `.md` file containing a whitespace bomb (~1 MB of spaces inside a blockquote/list, shaped to defeat both regex branches).
2. CI (and the daily `cron: '0 0 * * *'` schedule) runs the build → `remark-parse` → `trim()` → quadratic hang → job timeout, wasted runner minutes, repeated daily.
3. Because the container image and checkout action float, maintainers can't reproduce or audit the exact build environment while triaging the hang.

Note: this is **build-time only** — site visitors can't trigger it; it needs a merged/commitable markdown file. That's why each part is Medium, not High.

## Suggested fix

```jsonc
// package.json
"overrides": { "trim": "^0.0.3" }
```

```yaml
# .github/workflows/semgrep.yml
permissions:
contents: read
container:
image: returntocorp/semgrep:
steps:
- uses: actions/checkout@ # e.g. v4.1.7 SHA
```

Plus `.DS_Store` cleanup (it's tracked under `src/`) and adding `.DS_Store` to `.gitignore` — minor, happy to split into a separate PR.

## References

- CVE-2020-7753 (`trim` < 0.0.3, ReDoS)
- `remark-parse@8.0.3` → `trim@0.0.1` dependency chain in `package-lock.json`

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.