A minor issue and maybe a bigger one:
There’s a required nonce
param that’s not mentioned in the documentation:
def require_params
%i[public_key nonce scopes client_id application_name].each { |p| params.require(p) }
end
Now the trickier issue. Discourse calls the public_encrypt
method with no arguments:
That means the padding
argument defaults to PKCS1_PADDING
. From the Ruby documentation:
Encrypt
string
with the public key.padding
defaults toPKCS1_PADDING
, which is known to be insecure but is kept for backwards compatibility.
Unfortunately, Node v20.14.0 (the current LTS) returns an error if you attempt to call crypto.privateDecrypt
with RSA_PKCS1_PADDING
:
function decryptData(data: string, privateKey: string) {
const buffer = Buffer.from(data, "base64");
const decrypted = crypto.privateDecrypt(
{
key: privateKey,
padding: crypto.constants.RSA_PKCS1_PADDING,
},
buffer
);
return decrypted.toString("utf8");
}
TypeError: RSA_PKCS1_PADDING is no longer supported for private decryption, this can be reverted with --security-revert=CVE-2023-46809
A possible fix for Node apps is to run Node with the insecure flag:
node --security-revert=CVE-2023-46809
A fix on the Discourse end would be easy, but I suspect it would break a lot of existing integrations:
public_key = OpenSSL::PKey::RSA.new(params[:public_key])
@payload = Base64.encode64(public_key.public_encrypt(@payload, OpenSSL::PKey::RSA::PKCS1_OAEP_PADDING))