| CVE | Vulnerability name | Date | Responsible Security Disclosure by | Vulnerabilities |
|---|---|---|---|---|
|
-
|
PatternBleed |
2026-08-08 |
GitHub CodeQL (code scanning alert #431) and xet7 (fix)
![]() Automated code scanning flagged the identity (no-op) replacement. |
|
A test that checks every platform WeKan builds has a row in the Node.js source-resolver
mapping table (tests/releaseNodeSources.test.cjs) built one regular expression
per platform name:
// vulnerable — replace('-', '-') is a no-op, so nothing is escaped
const re = new RegExp(`^\s*${p.replace('-', '-')}\)\s+nodename=`, 'm');
p.replace('-', '-') replaces a hyphen with a hyphen, so it returns the string
unchanged. GitHub CodeQL reports this as js/identity-replacement: replacing a
value with itself is almost always a mistake. Its usual cause is a mistyped backslash escape
— '\"' in a string literal is simply '"', so
replace(/"/g, '\"') is an identity replacement where '\\"' was
meant.
What makes this one worth a name rather than a shrug is the position it sat in. It reads as
escape this value before interpolating it into a pattern, and it is the only thing
standing between a platform name and a new RegExp. The escaping was not merely
wrong, it was absent — while looking present. Nothing failed, because the platform names in
that list contain only hyphens and a hyphen needs no escaping outside a character class; a
name containing ., + or ( would have matched the wrong
row, or thrown. There was no runtime exposure: this is test-only code, and the values
are a hardcoded list, not user input.
Fix: escape the value for real, with the same helper the other guards in
tests/ use:
// fixed — a real escape of every regex metacharacter
const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const re = new RegExp(`^\s*${escapeRegExp(p)}\)\s+nodename=`, 'm');
This is the second js/identity-replacement finding in WeKan, after
IdentityBleed (alert #424) seventeen days earlier. Code
scanning finds these after a push, in a web interface, and reports them one at a time. So the
fix also adds tests/noIdentityReplacement.test.cjs, which scans WeKan's own
JavaScript for the shape and fails in the ordinary test run, in seconds.
Three details decide whether such a guard is worth having:
replace as values, not as source
text. '\"' is '"' — the whole point of CodeQL's own
example — so a text comparison would call them different and miss the very mistake the
guard exists for.replace('"', '\"') puts a double quote inside a single-quoted
literal: the first version of the pattern could not match CodeQL's example at all, which
was found by testing the pattern against that line rather than trusting it.Verified in both directions: the repository is clean under the guard, and the same scan run against the previous commit reports the offending line.