CVE-2022-31142: Observable Discrepancy (CWE-203)
value: @fastify/bearer-auth is a Fastify plugin to require bearer Authorization headers. @fastify/bearer-auth prior to versions 7.0.2 and 8.0.1 does not securely use crypto.timingSafeEqual. A malicious attacker could estimate the length of one valid bearer token. According to the corresponding RFC 6750, the bearer token has only base64 valid characters, reducing the range of characters for a brute force attack. Version 7.0.2 and 8.0.1 of @fastify/bearer-auth contain a patch. There are currently no known workarounds. The package fastify-bearer-auth, which covers versions 6.0.3 and prior, is also vulnerable starting at version 5.0.1. Users of fastify-bearer-auth should upgrade to a patched version of @fastify/bearer-auth.
CWE description: The product behaves differently or sends different responses under different circumstances in a way that is observable to an unauthorized actor, which exposes security-relevant information about the state of the product, such as whether a particular operation was successful or not.
CVSS v3 base score: 7.5
Published: 2022-07-14T19:15Z
Repository: https://github.com/fastify/fastify-bearer-auth
Language: JSON
Files changed: package.json, plugin.js
Commit date: 2020-05-28 16:01:22 +0200
Commit message: Use `crypto.timingSafeEqual()` instead of `secure-compare` module (#40)

* Use crypto.timingSafeEqual()

* Just try/catch Node core api
Diff: diff --git a/package.json b/package.json
index 4069836..b38c4e3 100644
--- a/package.json
+++ b/package.json
@@ -35,12 +35,11 @@
     "standard": "^14.0.2",
     "tap": "^12.6.5",
     "tsd": "^0.11.0"
   },
   "dependencies": {
-    "fastify-plugin": "^2.0.0",
-    "secure-compare": "^3.0.1"
+    "fastify-plugin": "^2.0.0"
   },
   "tsd": {
     "directory": "test",
     "compilerOptions": {
       "esModuleInterop": true
diff --git a/plugin.js b/plugin.js
index f5295dc..8221d0f 100644
--- a/plugin.js
+++ b/plugin.js
@@ -1,9 +1,9 @@
 'use strict'
 
+const crypto = require('crypto')
 const fp = require('fastify-plugin')
-const compare = require('secure-compare')
 
 function factory (options) {
   const defaultOptions = {
     keys: [],
     auth: undefined,
@@ -78,10 +78,20 @@ function factory (options) {
 
 function authenticate (keys, key) {
   return keys.findIndex((a) => compare(a, key)) !== -1
 }
 
+// perform constant-time comparison to prevent timing attacks
+function compare (a, b) {
+  try {
+    // may throw if they have different length, can't convert to Buffer, etc...
+    return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b))
+  } catch {
+    return false
+  }
+}
+
 function plugin (fastify, options, next) {
   fastify.addHook('onRequest', factory(options))
   next()
 }
 

Vulnerable code:     "fastify-plugin": "^2.0.0",
    "secure-compare": "^3.0.1"
const compare = require('secure-compare')
Fixed code:     "fastify-plugin": "^2.0.0"
const crypto = require('crypto')
// perform constant-time comparison to prevent timing attacks
function compare (a, b) {
  try {
    // may throw if they have different length, can't convert to Buffer, etc...
    return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b))
  } catch {
    return false
  }
}