Add SPA session validation and buglist, update migration docs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-12-03 21:28:08 +00:00
parent 9be3dfc14e
commit cff287e870
24169 changed files with 10223 additions and 7120 deletions

2
node_modules/node-forge/lib/aes.js generated vendored Normal file → Executable file
View File

@@ -325,7 +325,7 @@ var imix; // inverse mix-columns table
* The word [a0, a1, a2, a3] is a polynomial a3x^3 + a2x^2 + a1x + a0.
*
* Addition is performed by XOR'ing like powers of x. Multiplication
* is performed in two steps, the first is an algebriac expansion as
* is performed in two steps, the first is an algebraic expansion as
* you would do normally (where addition is XOR). But the result is
* a polynomial larger than 3 degrees and thus it cannot fit in a word. So
* next the result is modularly reduced by an AES-specific polynomial of

0
node_modules/node-forge/lib/aesCipherSuites.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/asn1-validator.js generated vendored Normal file → Executable file
View File

99
node_modules/node-forge/lib/asn1.js generated vendored Normal file → Executable file
View File

@@ -178,6 +178,11 @@ asn1.Type = {
BMPSTRING: 30
};
/**
* Sets the default maximum recursion depth when parsing ASN.1 structures.
*/
asn1.maxDepth = 256;
/**
* Creates a new asn1 object.
*
@@ -419,6 +424,8 @@ var _getValueLength = function(bytes, remaining) {
* erroneously decode values that happen to be valid ASN.1. This
* flag will be deprecated or removed as soon as schema support is
* available. (default: true)
* [maxDepth] override asn1.maxDepth recursion limit
* (default: asn1.maxDepth)
*
* @throws Will throw an error for various malformed input conditions.
*
@@ -448,6 +455,9 @@ asn1.fromDer = function(bytes, options) {
if(!('decodeBitStrings' in options)) {
options.decodeBitStrings = true;
}
if(!('maxDepth' in options)) {
options.maxDepth = asn1.maxDepth;
}
// wrap in buffer if needed
if(typeof bytes === 'string') {
@@ -476,6 +486,12 @@ asn1.fromDer = function(bytes, options) {
* @return the parsed asn1 object.
*/
function _fromDer(bytes, remaining, depth, options) {
// check depth limit
if(depth >= options.maxDepth) {
throw new Error('ASN.1 parsing error: Max depth exceeded.');
}
// temporary storage for consumption calculations
var start;
@@ -773,6 +789,10 @@ asn1.oidToDer = function(oid) {
last = true;
valueBytes = [];
value = parseInt(values[i], 10);
// TODO: Change bitwise logic to allow larger values.
if(value > 0xffffffff) {
throw new Error('OID value too large; max is 32-bits.');
}
do {
b = value & 0x7F;
value = value >>> 7;
@@ -818,8 +838,13 @@ asn1.derToOid = function(bytes) {
// the last byte for each value
var value = 0;
while(bytes.length() > 0) {
// error if 7b shift would exceed Number.MAX_SAFE_INTEGER
// (Number.MAX_SAFE_INTEGER / 128)
if(value > 0x3fffffffffff) {
throw new Error('OID value too large; max is 53-bits.');
}
b = bytes.getByte();
value = value << 7;
value = value * 128;
// not the last byte for the value
if(b & 0x80) {
value += b & 0x7F;
@@ -1165,22 +1190,65 @@ asn1.validate = function(obj, v, capture, errors) {
if(v.value && forge.util.isArray(v.value)) {
var j = 0;
for(var i = 0; rval && i < v.value.length; ++i) {
rval = v.value[i].optional || false;
if(obj.value[j]) {
rval = asn1.validate(obj.value[j], v.value[i], capture, errors);
if(rval) {
++j;
} else if(v.value[i].optional) {
var schemaItem = v.value[i];
rval = !!schemaItem.optional;
// current child in the object
var objChild = obj.value[j];
// if there is no child left to match
if(!objChild) {
// if optional, ok (rval already true), else fail below
if(!schemaItem.optional) {
rval = false;
if(errors) {
errors.push('[' + v.name + '] ' +
'Missing required element. Expected tag class "' +
schemaItem.tagClass + '", type "' + schemaItem.type + '"');
}
}
continue;
}
// If schema explicitly specifies tagClass/type, do a quick structural check
// to avoid unnecessary recursion/side-effects when tags clearly don't match.
var schemaHasTag = (typeof schemaItem.tagClass !== 'undefined' &&
typeof schemaItem.type !== 'undefined');
if(schemaHasTag &&
(objChild.tagClass !== schemaItem.tagClass || objChild.type !== schemaItem.type)) {
// Tags do not match.
if(schemaItem.optional) {
// Skip this schema element (don't consume objChild; don't call recursive validate).
rval = true;
continue;
} else {
// Required schema item mismatched - fail.
rval = false;
if(errors) {
errors.push('[' + v.name + '] ' +
'Tag mismatch. Expected (' +
schemaItem.tagClass + ',' + schemaItem.type + '), got (' +
objChild.tagClass + ',' + objChild.type + ')');
}
break;
}
}
if(!rval && errors) {
errors.push(
'[' + v.name + '] ' +
'Tag class "' + v.tagClass + '", type "' +
v.type + '" expected value length "' +
v.value.length + '", got "' +
obj.value.length + '"');
// Tags are compatible (or schema did not declare tags) - dive into recursive validate.
var childRval = asn1.validate(objChild, schemaItem, capture, errors);
if(childRval) {
// consume this child
++j;
rval = true;
} else if(schemaItem.optional) {
// validation failed but element is optional => skip schema item (don't consume child)
rval = true;
} else {
// required item failed
rval = false;
// errors should already be populated by recursive call; keep failing
break;
}
}
}
@@ -1226,7 +1294,8 @@ asn1.validate = function(obj, v, capture, errors) {
if(obj.type !== v.type) {
errors.push(
'[' + v.name + '] ' +
'Expected type "' + v.type + '", got "' + obj.type + '"');
'Expected type "' + v.type + '", got "' +
obj.type + '"');
}
}
return rval;

0
node_modules/node-forge/lib/baseN.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/cipher.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/cipherModes.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/des.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/ed25519.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/forge.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/form.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/hmac.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/http.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/index.all.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/index.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/jsbn.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/kem.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/log.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/md.all.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/md.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/md5.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/mgf.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/mgf1.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/oids.js generated vendored Normal file → Executable file
View File

2
node_modules/node-forge/lib/pbe.js generated vendored Normal file → Executable file
View File

@@ -672,7 +672,7 @@ pki.pbe.generatePkcs12Key = function(password, salt, id, iter, n, md) {
D.fillWithByte(id, v);
/* 2. Concatenate copies of the salt together to create a string S of length
v * ceil(s / v) bytes (the final copy of the salt may be trunacted
v * ceil(s / v) bytes (the final copy of the salt may be truncated
to create S).
Note that if the salt is the empty string, then so is S. */
var Slen = v * Math.ceil(s / v);

0
node_modules/node-forge/lib/pbkdf2.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/pem.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/pkcs1.js generated vendored Normal file → Executable file
View File

3
node_modules/node-forge/lib/pkcs12.js generated vendored Normal file → Executable file
View File

@@ -474,6 +474,9 @@ p12.pkcs12FromAsn1 = function(obj, strict, password) {
if(macValue.getBytes() !== capture.macDigest) {
throw new Error('PKCS#12 MAC could not be verified. Invalid password?');
}
} else if(Array.isArray(obj.value) && obj.value.length > 2) {
/* This is pfx data that should have mac and verify macDigest */
throw new Error('Invalid PKCS#12. macData field present but MAC was not validated.');
}
_decodeAuthenticatedSafe(pfx, data.value, strict, password);

0
node_modules/node-forge/lib/pkcs7.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/pkcs7asn1.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/pki.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/prime.js generated vendored Normal file → Executable file
View File

2
node_modules/node-forge/lib/prime.worker.js generated vendored Normal file → Executable file
View File

@@ -56,7 +56,7 @@ function findPrime(data) {
}
function isProbablePrime(n) {
// divide by low primes, ignore even checks, etc (n alread aligned properly)
// divide by low primes, ignore even checks, etc (n already aligned properly)
var i = 1;
while(i < LOW_PRIMES.length) {
var m = LOW_PRIMES[i];

0
node_modules/node-forge/lib/prng.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/pss.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/random.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/rc2.js generated vendored Normal file → Executable file
View File

12
node_modules/node-forge/lib/rsa.js generated vendored Normal file → Executable file
View File

@@ -282,7 +282,7 @@ var digestInfoValidator = {
constructed: false,
capture: 'algorithmIdentifier'
}, {
// NULL paramters
// NULL parameters
name: 'DigestInfo.DigestAlgorithm.parameters',
tagClass: asn1.Class.UNIVERSAL,
type: asn1.Type.NULL,
@@ -316,7 +316,7 @@ var digestInfoValidator = {
*
* @param md the message digest object with the hash to sign.
*
* @return the encoded message (ready for RSA encrytion)
* @return the encoded message (ready for RSA encryption)
*/
var emsaPkcs1v15encode = function(md) {
// get the oid for the algorithm
@@ -498,7 +498,7 @@ var _modPow = function(x, key, pub) {
*
* The parameter bt controls whether to put padding bytes before the
* message passed in. Set bt to either true or false to disable padding
* completely (in order to handle e.g. EMSA-PSS encoding seperately before),
* completely (in order to handle e.g. EMSA-PSS encoding separately before),
* signaling whether the encryption operation is a public key operation
* (i.e. encrypting data) or not, i.e. private key operation (data signing).
*
@@ -1173,7 +1173,7 @@ pki.setRsaPublicKey = pki.rsa.setPublicKey = function(n, e) {
}
// check hash algorithm identifier
// see PKCS1-v1-5DigestAlgorithms in RFC 8017
// FIXME: add support to vaidator for strict value choices
// FIXME: add support to validator for strict value choices
var oid = asn1.derToOid(capture.algorithmIdentifier);
if(!(oid === forge.oids.md2 ||
oid === forge.oids.md5 ||
@@ -1196,7 +1196,7 @@ pki.setRsaPublicKey = pki.rsa.setPublicKey = function(n, e) {
throw new Error(
'ASN.1 object does not contain a valid RSASSA-PKCS1-v1_5 ' +
'DigestInfo value. ' +
'Missing algorithm identifer NULL parameters.');
'Missing algorithm identifier NULL parameters.');
}
}
@@ -1637,7 +1637,7 @@ function _decodePkcs1_v1_5(em, key, pub, ml) {
1. The encryption block EB cannot be parsed unambiguously.
2. The padding string PS consists of fewer than eight octets
or is inconsisent with the block type BT.
or is inconsistent with the block type BT.
3. The decryption process is a public-key operation and the block
type BT is not 00 or 01, or the decryption process is a
private-key operation and the block type is not 02.

0
node_modules/node-forge/lib/sha1.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/sha256.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/sha512.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/socket.js generated vendored Normal file → Executable file
View File

0
node_modules/node-forge/lib/ssh.js generated vendored Normal file → Executable file
View File

4
node_modules/node-forge/lib/tls.js generated vendored Normal file → Executable file
View File

@@ -758,7 +758,7 @@ tls.handleUnexpected = function(c, record) {
*/
tls.handleHelloRequest = function(c, record, length) {
// ignore renegotiation requests from the server during a handshake, but
// if handshaking, send a warning alert that renegotation is denied
// if handshaking, send a warning alert that renegotiation is denied
if(!c.handshaking && c.handshakes > 0) {
// send alert warning
tls.queue(c, tls.createAlert(c, {
@@ -2258,7 +2258,7 @@ hsTable[tls.ConnectionEnd.client] = [
];
// map server current expect state and handshake type to function
// Note: CAD[CH] does not map to FB because renegotation is prohibited
// Note: CAD[CH] does not map to FB because renegotiation is prohibited
var H7 = tls.handleClientHello;
var H8 = tls.handleClientKeyExchange;
var H9 = tls.handleCertificateVerify;

0
node_modules/node-forge/lib/tlssocket.js generated vendored Normal file → Executable file
View File

6
node_modules/node-forge/lib/util.js generated vendored Normal file → Executable file
View File

@@ -677,7 +677,7 @@ util.ByteStringBuffer.prototype.clear = function() {
};
/**
* Shortens this buffer by triming bytes off of the end of this buffer.
* Shortens this buffer by trimming bytes off of the end of this buffer.
*
* @param count the number of bytes to trim off.
*
@@ -1343,7 +1343,7 @@ util.DataBuffer.prototype.clear = function() {
};
/**
* Shortens this buffer by triming bytes off of the end of this buffer.
* Shortens this buffer by trimming bytes off of the end of this buffer.
*
* @param count the number of bytes to trim off.
*
@@ -2316,7 +2316,7 @@ util.format = function(format) {
parts.push('<?>');
}
break;
// FIXME: do proper formating for numbers, etc
// FIXME: do proper formatting for numbers, etc
//case 'f':
//case 'd':
case '%':

2
node_modules/node-forge/lib/x509.js generated vendored Normal file → Executable file
View File

@@ -2289,7 +2289,7 @@ function _fillMissingExtensionFields(e, options) {
* Convert signature parameters object to ASN.1
*
* @param {String} oid Signature algorithm OID
* @param params The signature parametrs object
* @param params The signature parameters object
* @return ASN.1 object representing signature parameters
*/
function _signatureParametersToAsn1(oid, params) {

2
node_modules/node-forge/lib/xhr.js generated vendored Normal file → Executable file
View File

@@ -459,7 +459,7 @@ xhrApi.create = function(options) {
// set request method to given method
// set request URL
// set username, password
// set asychronous flag
// set asynchronous flag
_state.sendFlag = false;
xhr.responseText = '';
xhr.responseXML = null;