Skip to content

security: fix CodeQL code-scanning alerts and patch vulnerable dependencies#2788

Draft
laileni-aws wants to merge 3 commits into
aws:mainfrom
laileni-aws:security/fix-dependabot-and-codeql-alerts
Draft

security: fix CodeQL code-scanning alerts and patch vulnerable dependencies#2788
laileni-aws wants to merge 3 commits into
aws:mainfrom
laileni-aws:security/fix-dependabot-and-codeql-alerts

Conversation

@laileni-aws

Copy link
Copy Markdown
Contributor

Security: fix CodeQL code-scanning alerts and patch vulnerable dependencies

Draft PR — opened as a draft for maintainer review. It touches CI workflow
permissions, two security-scan regexes, and the dependency lockfile, and I would
like owner eyes on the scope before it is marked ready. Nothing here changes
runtime behavior of the language servers.

This PR addresses the open GitHub Advanced Security findings for aws/language-servers:

  • Code scanning (CodeQL): all 10 open alerts are fixed.
  • Dependabot: the vulnerable transitive-dependency graph is reduced from
    86 → 56 npm audit findings (30 resolved), using a non-breaking,
    lockfile-only npm audit fix. The remaining findings are documented below with
    the reason each was not auto-fixed and a recommended follow-up.

All changes were verified with a full monorepo compile and the affected unit tests
(see Verification).


1. Code scanning (CodeQL) — 10 / 10 fixed

1a. actions/missing-workflow-permissions (medium) — 6 alerts

Three workflows did not set an explicit permissions block, leaving the
GITHUB_TOKEN at the repository/organization default (often read-write). These
workflows only check out code, build, run tests, and upload build artifacts, so a
top-level least-privilege block was added:

permissions:
    contents: read
File Alerts
.github/workflows/lsp-ci.yaml #5, #6, #7, #8
.github/workflows/npm-packaging.yaml #4
.github/workflows/create-agent-standalone.yml #1

This matches the existing convention already used in release-please.yaml and
create-agentic-github-prerelease.yml.

1b. js/redos — ReDoS (high) — 4 alerts

Two files contained regular expressions vulnerable to catastrophic backtracking.

server/.../securityScan/dependencyGraph/csharpDependencyGraph.ts (alerts #9, #10)
The C# namespace sub-pattern ([A-Z]\w*(.[A-Z]\w*)*) used an unescaped ..
Because . matches any character, it overlaps with the adjacent \w*, creating an
ambiguous nested quantifier that backtracks exponentially (e.g. on
using\tAaA0A0A0…). Escaping it to \.:

  • removes the ambiguity → linear matching, and
  • is more correct — C# namespace separators are literal dots.

Applied to importRegex (#9), importNamespaceRegex (#10), and the identical
searchRegEx in createNamespaceFilenameMapper (same root cause, not separately
flagged — fixed proactively to avoid a future alert).

server/.../supplementalContextUtil/unitTestIntentDetection.ts (alerts #11, #12)
The Java test-signature pattern's annotation loop
(?:\s*@\w+(?:\(.*?\))?\s*)* had both a leading and a trailing \s* inside a
*-quantified group (a whitespace-partition ambiguity), plus an unbounded .*?
inside the parentheses. Rewrote to:

(?:\s*@\w+(?:\([^)]*\))?)*

which drops the ambiguous trailing \s* (whitespace after an annotation is already
consumed by the following token) and bounds the parenthesis content with [^)]*.

Both js/redos files are exercised by existing unit tests; all still pass, and
the CodeQL attack strings now run in ≤ 1 ms at 5,000 repetitions (linear).


2. Dependabot — 30 advisories resolved (86 → 56)

Nearly all Dependabot alerts are transitive dependencies resolved in the single
root package-lock.json. The safest, most reviewable remediation is
npm audit fix without --force: it updates transitive dependencies to
patched versions within the semver ranges their parents already allow, editing
only the lockfile. package.json is unchanged.

npm audit before → after:

Severity Before After Fixed
Critical 11 7 4
High 16 4 12
Moderate 51 38 13
Low 8 7 1
Total 86 56 30

Representative packages fully remediated (patched in-range):
axios, hono, protobufjs, node-forge, ws, undici, form-data,
handlebars, fast-uri, fast-xml-builder, flatted, follow-redirects,
path-to-regexp, brace-expansion, picomatch, qs, postcss,
http-proxy-middleware, ip-address, launch-editor, websocket-driver,
shell-quote, basic-ftp, @babel/core, @hono/node-server, @protobufjs/utf8,
express, body-parser, express-rate-limit, @aws-sdk/xml-builder.


3. What was NOT fixed here, and why

I deliberately avoided two tempting-but-risky approaches:

  • npm audit fix --force — would apply breaking major upgrades to direct
    dependencies (build tooling, test frameworks), a high risk of breaking the build
    and tests for moderate/low findings.
  • Blanket overrides + full lockfile regeneration — I prototyped this. It
    does resolve two more findings, but only by re-resolving the entire tree
    (~8,500-line lockfile churn, unrelated version bumps, higher regression risk) for
    little gain. A surgical override instead mis-resolved (npm deduped the SDK's
    fast-xml-parser@4 onto an API-incompatible 5.x). For a security PR that
    maintainers must review, a tight, correct diff is worth far more than two extra
    fixes obtained noisily. See Recommended follow-ups.

The remaining 56 findings group into the following root causes:

A. First-party / internal packages (fix upstream, not here)

@amzn/amazon-q-developer-streaming-client, @amzn/codewhisperer,
@amzn/codewhisperer-runtime, @amzn/codewhisperer-streaming, @aws/lsp-core,
@aws/lsp-partiql, @aws/language-server-runtimes. The advisories live inside
these published Amazon artifacts; they must be remediated by releasing new versions
of those packages, which this repo then consumes.

B. AWS SDK cluster pinned by internal packages

The @amzn/* packages above pin @aws-sdk/core@3.731.0 and its siblings at
exact versions, freezing ~13 @aws-sdk/* packages at a pre-fix release
(3.529–3.893 advisory range). They cannot be moved from this repo without a
--force/override that would fight those exact pins. Fixing them properly means
bumping the internal @amzn/* packages (A) or a coordinated @aws-sdk upgrade.

C. fast-xml-parser (critical) — partially mitigated

The 5.x copy was patched to 5.10.1 by npm audit fix. The remaining critical
instance is 4.4.1, pulled exclusively by the exact-pinned
@aws-sdk/core@3.731.0 from (B). It is fixable via an overrides pin but only
cleanly with a lockfile regen — see Recommended follow-ups.

D. Dev / build / test tooling needing breaking major upgrades

Not shipped in the runtime bundles; upgrading risks breaking builds/tests, so
deferred for a maintainer decision: webpack-dev-server (→6) + sockjs,
crypto-browserify polyfill stack (browserify-sign, create-ecdh, elliptic),
@wdio/mocha-framework + mocha, xmlbuilder2 (→4, which pulls js-yaml),
sinon (→22), diff (→9), serialize-javascript (via wdio), esbuild,
yaml-language-server (and its lodash/yaml).

E. No upstream fix available

elliptic (no patched release), lodash (the advisory's "fixed" 4.17.23 is not
published), and the debug/spdx-licenses/bower-* chain below.

F. oss-attribution-generator (dev-only, unmaintained)

This attribution tool drags in a vulnerable, unmaintained chain
(bower-json, bower-license, npm-license, underscore, deep-extend,
spdx-licenses, old debug). It runs only at build time (license attribution) and
ships nothing at runtime. Recommend replacing it with a maintained alternative
(e.g. license-checker, already a dependency, or oss-attribution-builder).


Recommended follow-ups

For maintainers who want to push further (each requires a package-lock.json
regeneration, i.e. rm package-lock.json && npm install):

// package.json — targeted, per-major overrides (verified to resolve correctly)
"overrides": {
  "fast-xml-parser@^4": "^4.5.7", // forces the SDK's 4.4.1 → 4.5.7 (critical); leaves 5.x alone
  "yaml@^2": "^2.8.3"             // yaml-language-server's 2.2.2 → 2.9.x (moderate)
}

Bigger items that should be owner-driven: bump the internal @amzn/* packages (to
carry a patched @aws-sdk), upgrade webpack-dev-server to v6, and replace
oss-attribution-generator.


Verification

  • Build: npm run compile (full monorepo) — ✅ success, no type errors.
  • Tests: csharpDependencyGraph.test.ts + unitTestIntentDetection.test.ts
    — ✅ 56 passing, 0 failing (covers every regex changed here).
  • ReDoS: the exact CodeQL attack strings execute in ≤ 1 ms at 5,000
    repetitions
    against the patched regexes (linear), and valid-input correctness
    (namespace/import extraction, Java test-intent true/false) is unchanged.
  • Dependencies: npm audit 86 → 56; npm ci installs cleanly (0 invalid tree
    entries); package.json untouched.

Commits

  1. ci: restrict GITHUB_TOKEN permissions in CI workflows — §1a (6 alerts)
  2. fix: eliminate ReDoS in C# dependency-graph and Java test-intent regexes — §1b (4 alerts)
  3. fix: patch vulnerable transitive npm dependencies via npm audit fix — §2 (30 advisories)

Adds a top-level least-privilege `permissions: contents: read` block to
lsp-ci.yaml, npm-packaging.yaml and create-agent-standalone.yml.

These workflows only check out code, build, run tests and upload build
artifacts, so read-only access to repository contents is sufficient.

Resolves CodeQL `actions/missing-workflow-permissions` alerts #1, #4, #5,
#6, #7 and aws#8.
Fixes catastrophic-backtracking (ReDoS) regexes flagged by CodeQL js/redos.

csharpDependencyGraph.ts: the namespace-matching sub-pattern used an
unescaped `.` inside `([A-Z]\w*(.[A-Z]\w*)*)`, so `.` overlapped with
`\w` and produced ambiguous, exponential backtracking. Escaping it to
`\.` removes the ambiguity (linear time) and is also more correct, since
C# namespace separators are literal dots. Applied to importRegex (alert
aws#9), importNamespaceRegex (alert aws#10) and the identical searchRegEx in
createNamespaceFilenameMapper (same root cause, not separately flagged).

unitTestIntentDetection.ts: the Java signature pattern's annotation loop
`(?:\s*@\w+(?:\(.*?\))?\s*)*` had leading AND trailing `\s*` inside a
`*`-quantified group (whitespace-partition ambiguity) plus an unbounded
`.*?` in the parentheses. Rewrote to `(?:\s*@\w+(?:\([^)]*\))?)*`
(alerts aws#11, aws#12).

Verified: attack strings from the CodeQL reports complete in <=1ms at
5000 repetitions (linear), and the existing unit tests for both files
(56 cases) still pass.
Runs `npm audit fix` (non-breaking, lockfile-only) to update vulnerable
transitive dependencies to patched versions within the ranges already
allowed by their parents. No package.json changes; only package-lock.json.

Reduces `npm audit` from 86 to 56 vulnerabilities (30 resolved):
  critical 11 -> 7, high 16 -> 4, moderate 51 -> 38, low 8 -> 7.

Resolved advisories include axios, hono, protobufjs, node-forge, ws,
undici, form-data, handlebars, fast-uri, follow-redirects, path-to-regexp,
brace-expansion, picomatch, qs, postcss, http-proxy-middleware,
websocket-driver, shell-quote and others.

The remaining 56 require breaking major upgrades, have no upstream fix,
or live inside version-pinned internal packages; see the PR description
for the full breakdown and recommended follow-ups.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant