@juspay/neurolink 8.20.0 → 8.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [8.20.1](https://github.com/juspay/neurolink/compare/v8.20.0...v8.20.1) (2025-12-22)
2
+
3
+ ### Bug Fixes
4
+
5
+ - **(Validation):** implement secure base64 validation with fail-fast checks ([f1b9b9c](https://github.com/juspay/neurolink/commit/f1b9b9c105db38ce439a5e69ff343b77b12be174)), closes [#277](https://github.com/juspay/neurolink/issues/277)
6
+
1
7
  ## [8.20.0](https://github.com/juspay/neurolink/compare/v8.19.1...v8.20.0) (2025-12-22)
2
8
 
3
9
  ### Features
@@ -157,6 +157,7 @@ export declare const imageUtils: {
157
157
  createDataUri: (base64: string, mimeType?: string) => string;
158
158
  /**
159
159
  * Validate base64 string format
160
+ * Validates format BEFORE buffer allocation to prevent memory exhaustion
160
161
  */
161
162
  isValidBase64: (str: string) => boolean;
162
163
  /**
@@ -622,12 +622,40 @@ export const imageUtils = {
622
622
  },
623
623
  /**
624
624
  * Validate base64 string format
625
+ * Validates format BEFORE buffer allocation to prevent memory exhaustion
625
626
  */
626
627
  isValidBase64: (str) => {
627
628
  try {
628
629
  // Remove data URI prefix if present
629
630
  const cleanBase64 = str.includes(",") ? str.split(",")[1] : str;
630
- // Check if it's valid base64
631
+ // Empty string check
632
+ if (!cleanBase64 || cleanBase64.length === 0) {
633
+ return false;
634
+ }
635
+ // 1. Validate character set FIRST (A-Z, a-z, 0-9, +, /, =)
636
+ // This prevents memory allocation for invalid input like "hello world"
637
+ const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
638
+ if (!base64Regex.test(cleanBase64)) {
639
+ return false;
640
+ }
641
+ // 2. Check length is multiple of 4
642
+ if (cleanBase64.length % 4 !== 0) {
643
+ return false;
644
+ }
645
+ // 3. Validate padding position (max 2 equals at end only)
646
+ const paddingIndex = cleanBase64.indexOf("=");
647
+ if (paddingIndex !== -1) {
648
+ // Padding must be at the end
649
+ if (paddingIndex < cleanBase64.length - 2) {
650
+ return false;
651
+ }
652
+ // No characters after padding
653
+ const afterPadding = cleanBase64.slice(paddingIndex);
654
+ if (!/^=+$/.test(afterPadding)) {
655
+ return false;
656
+ }
657
+ }
658
+ // 4. ONLY NOW decode if format is valid
631
659
  const decoded = Buffer.from(cleanBase64, "base64");
632
660
  const reencoded = decoded.toString("base64");
633
661
  // Remove padding for comparison (base64 can have different padding)
@@ -157,6 +157,7 @@ export declare const imageUtils: {
157
157
  createDataUri: (base64: string, mimeType?: string) => string;
158
158
  /**
159
159
  * Validate base64 string format
160
+ * Validates format BEFORE buffer allocation to prevent memory exhaustion
160
161
  */
161
162
  isValidBase64: (str: string) => boolean;
162
163
  /**
@@ -622,12 +622,40 @@ export const imageUtils = {
622
622
  },
623
623
  /**
624
624
  * Validate base64 string format
625
+ * Validates format BEFORE buffer allocation to prevent memory exhaustion
625
626
  */
626
627
  isValidBase64: (str) => {
627
628
  try {
628
629
  // Remove data URI prefix if present
629
630
  const cleanBase64 = str.includes(",") ? str.split(",")[1] : str;
630
- // Check if it's valid base64
631
+ // Empty string check
632
+ if (!cleanBase64 || cleanBase64.length === 0) {
633
+ return false;
634
+ }
635
+ // 1. Validate character set FIRST (A-Z, a-z, 0-9, +, /, =)
636
+ // This prevents memory allocation for invalid input like "hello world"
637
+ const base64Regex = /^[A-Za-z0-9+/]*={0,2}$/;
638
+ if (!base64Regex.test(cleanBase64)) {
639
+ return false;
640
+ }
641
+ // 2. Check length is multiple of 4
642
+ if (cleanBase64.length % 4 !== 0) {
643
+ return false;
644
+ }
645
+ // 3. Validate padding position (max 2 equals at end only)
646
+ const paddingIndex = cleanBase64.indexOf("=");
647
+ if (paddingIndex !== -1) {
648
+ // Padding must be at the end
649
+ if (paddingIndex < cleanBase64.length - 2) {
650
+ return false;
651
+ }
652
+ // No characters after padding
653
+ const afterPadding = cleanBase64.slice(paddingIndex);
654
+ if (!/^=+$/.test(afterPadding)) {
655
+ return false;
656
+ }
657
+ }
658
+ // 4. ONLY NOW decode if format is valid
631
659
  const decoded = Buffer.from(cleanBase64, "base64");
632
660
  const reencoded = decoded.toString("base64");
633
661
  // Remove padding for comparison (base64 can have different padding)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "8.20.0",
3
+ "version": "8.20.1",
4
4
  "description": "Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and deploy AI applications with 9 major providers: OpenAI, Anthropic, Google AI, AWS Bedrock, Azure, Hugging Face, Ollama, and Mistral AI.",
5
5
  "author": {
6
6
  "name": "Juspay Technologies",