Skip to content

Commit 2e4ddeb

Browse files
script3rclaudehappy-otter
committed
Add JavaScript and TypeScript language support
- Add tree-sitter-javascript and tree-sitter-typescript parsers - Support file extensions: .js, .mjs, .cjs, .jsx, .ts, .mts, .cts, .tsx - Add patterns for Node.js crypto module (createHash, createCipheriv, etc.) - Add patterns for Web Crypto API (crypto.subtle.*) - Add patterns for crypto-js library (CryptoJS.AES, CryptoJS.SHA256, etc.) - Fix panic in import_like_nodes when checking require() calls - Add test fixtures for all three JS/TS crypto libraries Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
1 parent 5c0e253 commit 2e4ddeb

15 files changed

Lines changed: 1150 additions & 3 deletions

File tree

Cargo.lock

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@ tree-sitter-swift = { version = "0.7", optional = true }
3636
tree-sitter-php = { version = "0.24", optional = true }
3737
tree-sitter-objc = { version = "3.0", optional = true }
3838
tree-sitter-rust = { version = "0.23", optional = true }
39+
tree-sitter-javascript = { version = "0.25", optional = true }
40+
tree-sitter-typescript = { version = "0.23", optional = true }
3941

4042
[features]
41-
default = ["lang-c", "lang-cpp", "lang-java", "lang-python", "lang-go", "lang-swift", "lang-php", "lang-objc", "lang-rust"]
43+
default = ["lang-c", "lang-cpp", "lang-java", "lang-python", "lang-go", "lang-swift", "lang-php", "lang-objc", "lang-rust", "lang-javascript", "lang-typescript"]
4244
lang-c = ["tree-sitter-c"]
4345
lang-cpp = ["tree-sitter-cpp"]
4446
lang-java = ["tree-sitter-java"]
@@ -48,6 +50,8 @@ lang-swift = ["tree-sitter-swift"]
4850
lang-php = ["tree-sitter-php"]
4951
lang-objc = ["tree-sitter-objc"]
5052
lang-rust = ["tree-sitter-rust"]
53+
lang-javascript = ["tree-sitter-javascript"]
54+
lang-typescript = ["tree-sitter-typescript"]
5155

5256
[dev-dependencies]
5357
assert_cmd = "2.0"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{"assetType":"library","identifier":"crypto-js","path":"fixtures/javascript/crypto_js/src/test.js","evidence":{"line":2,"column":18}}
2+
{"assetType":"algorithm","identifier":"SHA-256","path":"fixtures/javascript/crypto_js/src/test.js","evidence":{"line":17,"column":12},"metadata":{"primitive":"hash"}}
3+
{"assetType":"algorithm","identifier":"SHA-256","path":"fixtures/javascript/crypto_js/src/test.js","evidence":{"line":32,"column":12},"metadata":{"primitive":"hash"}}
4+
{"assetType":"algorithm","identifier":"AES","path":"fixtures/javascript/crypto_js/src/test.js","evidence":{"line":6,"column":12},"metadata":{"primitive":"symmetric"}}
5+
{"assetType":"algorithm","identifier":"AES","path":"fixtures/javascript/crypto_js/src/test.js","evidence":{"line":11,"column":19},"metadata":{"primitive":"symmetric"}}
6+
{"assetType":"algorithm","identifier":"SHA-3","path":"fixtures/javascript/crypto_js/src/test.js","evidence":{"line":55,"column":12},"metadata":{"primitive":"hash"}}
7+
{"assetType":"algorithm","identifier":"PBKDF2","path":"fixtures/javascript/crypto_js/src/test.js","evidence":{"line":42,"column":12},"metadata":{"primitive":"kdf","iterations":100000}}
8+
{"assetType":"algorithm","identifier":"3DES","path":"fixtures/javascript/crypto_js/src/test.js","evidence":{"line":50,"column":12},"metadata":{"primitive":"symmetric"}}
9+
{"assetType":"algorithm","identifier":"MD5","path":"fixtures/javascript/crypto_js/src/test.js","evidence":{"line":27,"column":12},"metadata":{"primitive":"hash"}}
10+
{"assetType":"algorithm","identifier":"SHA-512","path":"fixtures/javascript/crypto_js/src/test.js","evidence":{"line":22,"column":12},"metadata":{"primitive":"hash"}}
11+
{"assetType":"algorithm","identifier":"SHA-512","path":"fixtures/javascript/crypto_js/src/test.js","evidence":{"line":37,"column":12},"metadata":{"primitive":"hash"}}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// crypto-js library usage examples
2+
const CryptoJS = require('crypto-js');
3+
4+
// AES encryption
5+
function encryptAes(plaintext, key) {
6+
return CryptoJS.AES.encrypt(plaintext, key).toString();
7+
}
8+
9+
// AES decryption
10+
function decryptAes(ciphertext, key) {
11+
const bytes = CryptoJS.AES.decrypt(ciphertext, key);
12+
return bytes.toString(CryptoJS.enc.Utf8);
13+
}
14+
15+
// SHA-256 hashing
16+
function hashSha256(data) {
17+
return CryptoJS.SHA256(data).toString();
18+
}
19+
20+
// SHA-512 hashing
21+
function hashSha512(data) {
22+
return CryptoJS.SHA512(data).toString();
23+
}
24+
25+
// MD5 hashing (not recommended for security)
26+
function hashMd5(data) {
27+
return CryptoJS.MD5(data).toString();
28+
}
29+
30+
// HMAC-SHA256
31+
function hmacSha256(data, key) {
32+
return CryptoJS.HmacSHA256(data, key).toString();
33+
}
34+
35+
// HMAC-SHA512
36+
function hmacSha512(data, key) {
37+
return CryptoJS.HmacSHA512(data, key).toString();
38+
}
39+
40+
// PBKDF2 key derivation
41+
function deriveKey(password, salt) {
42+
return CryptoJS.PBKDF2(password, salt, {
43+
keySize: 256 / 32,
44+
iterations: 100000
45+
}).toString();
46+
}
47+
48+
// Triple DES encryption (legacy)
49+
function encryptTripleDes(plaintext, key) {
50+
return CryptoJS.TripleDES.encrypt(plaintext, key).toString();
51+
}
52+
53+
// SHA-3 hashing
54+
function hashSha3(data) {
55+
return CryptoJS.SHA3(data).toString();
56+
}
57+
58+
module.exports = {
59+
encryptAes,
60+
decryptAes,
61+
hashSha256,
62+
hashSha512,
63+
hashMd5,
64+
hmacSha256,
65+
hmacSha512,
66+
deriveKey,
67+
encryptTripleDes,
68+
hashSha3
69+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{"assetType":"library","identifier":"Node.js crypto","path":"fixtures/javascript/node_crypto/src/test.js","evidence":{"line":2,"column":16}}
2+
{"assetType":"algorithm","identifier":"SHA-256","path":"fixtures/javascript/node_crypto/src/test.js","evidence":{"line":6,"column":25},"metadata":{"primitive":"hash"}}
3+
{"assetType":"algorithm","identifier":"SHA-256","path":"fixtures/javascript/node_crypto/src/test.js","evidence":{"line":13,"column":25},"metadata":{"primitive":"hash"}}
4+
{"assetType":"algorithm","identifier":"scrypt","path":"fixtures/javascript/node_crypto/src/test.js","evidence":{"line":64,"column":19},"metadata":{"primitive":"kdf"}}
5+
{"assetType":"algorithm","identifier":"AES-GCM","path":"fixtures/javascript/node_crypto/src/test.js","evidence":{"line":21,"column":27},"metadata":{"primitive":"symmetric","keySize":256}}
6+
{"assetType":"algorithm","identifier":"AES-GCM","path":"fixtures/javascript/node_crypto/src/test.js","evidence":{"line":30,"column":29},"metadata":{"primitive":"symmetric","keySize":256}}
7+
{"assetType":"algorithm","identifier":"RSA","path":"fixtures/javascript/node_crypto/src/test.js","evidence":{"line":40,"column":16},"metadata":{"keySize":4096,"primitive":"asymmetric"}}
8+
{"assetType":"algorithm","identifier":"PBKDF2","path":"fixtures/javascript/node_crypto/src/test.js","evidence":{"line":59,"column":19},"metadata":{"iterations":100000,"primitive":"kdf"}}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Node.js crypto module usage examples
2+
const crypto = require('crypto');
3+
4+
// SHA-256 hashing
5+
function hashData(data) {
6+
const hash = crypto.createHash('sha256');
7+
hash.update(data);
8+
return hash.digest('hex');
9+
}
10+
11+
// HMAC-SHA256
12+
function hmacSign(data, key) {
13+
const hmac = crypto.createHmac('sha256', key);
14+
hmac.update(data);
15+
return hmac.digest('hex');
16+
}
17+
18+
// AES-256-GCM encryption
19+
function encryptAesGcm(plaintext, key) {
20+
const iv = crypto.randomBytes(12);
21+
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
22+
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
23+
encrypted += cipher.final('hex');
24+
const authTag = cipher.getAuthTag();
25+
return { encrypted, iv, authTag };
26+
}
27+
28+
// AES-256-GCM decryption
29+
function decryptAesGcm(encrypted, key, iv, authTag) {
30+
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
31+
decipher.setAuthTag(authTag);
32+
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
33+
decrypted += decipher.final('utf8');
34+
return decrypted;
35+
}
36+
37+
// RSA key pair generation
38+
async function generateRsaKeyPair() {
39+
return new Promise((resolve, reject) => {
40+
crypto.generateKeyPair('rsa', {
41+
modulusLength: 4096,
42+
publicKeyEncoding: {
43+
type: 'spki',
44+
format: 'pem'
45+
},
46+
privateKeyEncoding: {
47+
type: 'pkcs8',
48+
format: 'pem'
49+
}
50+
}, (err, publicKey, privateKey) => {
51+
if (err) reject(err);
52+
else resolve({ publicKey, privateKey });
53+
});
54+
});
55+
}
56+
57+
// PBKDF2 key derivation
58+
function deriveKey(password, salt) {
59+
return crypto.pbkdf2Sync(password, salt, 100000, 32, 'sha256');
60+
}
61+
62+
// scrypt key derivation
63+
function deriveKeyScrypt(password, salt) {
64+
return crypto.scryptSync(password, salt, 32);
65+
}
66+
67+
module.exports = {
68+
hashData,
69+
hmacSign,
70+
encryptAesGcm,
71+
decryptAesGcm,
72+
generateRsaKeyPair,
73+
deriveKey,
74+
deriveKeyScrypt
75+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{"assetType":"library","identifier":"Web Crypto API","path":"fixtures/javascript/webcrypto/src/test.js","evidence":{"line":1,"column":1}}
2+
{"assetType":"algorithm","identifier":"PBKDF2","path":"fixtures/javascript/webcrypto/src/test.js","evidence":{"line":86,"column":13},"metadata":{"iterations":100000,"primitive":"kdf"}}
3+
{"assetType":"algorithm","identifier":"AES-GCM","path":"fixtures/javascript/webcrypto/src/test.js","evidence":{"line":4,"column":11},"metadata":{"keySize":256,"primitive":"symmetric"}}
4+
{"assetType":"algorithm","identifier":"AES-GCM","path":"fixtures/javascript/webcrypto/src/test.js","evidence":{"line":92,"column":11},"metadata":{"keySize":256,"primitive":"symmetric"}}
5+
{"assetType":"algorithm","identifier":"ECDSA","path":"fixtures/javascript/webcrypto/src/test.js","evidence":{"line":45,"column":11},"metadata":{"primitive":"signature","curve":"P-384"}}
6+
{"assetType":"algorithm","identifier":"SHA-384","path":"fixtures/javascript/webcrypto/src/test.js","evidence":{"line":54,"column":26},"metadata":{"primitive":"hash"}}
7+
{"assetType":"algorithm","identifier":"SHA-384","path":"fixtures/javascript/webcrypto/src/test.js","evidence":{"line":63,"column":26},"metadata":{"primitive":"hash"}}
8+
{"assetType":"algorithm","identifier":"RSA-OAEP","path":"fixtures/javascript/webcrypto/src/test.js","evidence":{"line":33,"column":13},"metadata":{"keySize":4096,"primitive":"asymmetric"}}
9+
{"assetType":"algorithm","identifier":"SHA-256","path":"fixtures/javascript/webcrypto/src/test.js","evidence":{"line":36,"column":13},"metadata":{"primitive":"hash"}}
10+
{"assetType":"algorithm","identifier":"SHA-256","path":"fixtures/javascript/webcrypto/src/test.js","evidence":{"line":72,"column":32},"metadata":{"primitive":"hash"}}
11+
{"assetType":"algorithm","identifier":"SHA-256","path":"fixtures/javascript/webcrypto/src/test.js","evidence":{"line":89,"column":13},"metadata":{"primitive":"hash"}}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// Web Crypto API usage examples
2+
async function generateAesKey() {
3+
return await crypto.subtle.generateKey(
4+
{ name: 'AES-GCM', length: 256 },
5+
true,
6+
['encrypt', 'decrypt']
7+
);
8+
}
9+
10+
async function encryptData(key, data) {
11+
const iv = crypto.getRandomValues(new Uint8Array(12));
12+
const encoded = new TextEncoder().encode(data);
13+
const ciphertext = await crypto.subtle.encrypt(
14+
{ name: 'AES-GCM', iv },
15+
key,
16+
encoded
17+
);
18+
return { ciphertext, iv };
19+
}
20+
21+
async function decryptData(key, ciphertext, iv) {
22+
const decrypted = await crypto.subtle.decrypt(
23+
{ name: 'AES-GCM', iv },
24+
key,
25+
ciphertext
26+
);
27+
return new TextDecoder().decode(decrypted);
28+
}
29+
30+
async function generateRsaKeyPair() {
31+
return await crypto.subtle.generateKey(
32+
{
33+
name: 'RSA-OAEP',
34+
modulusLength: 4096,
35+
publicExponent: new Uint8Array([1, 0, 1]),
36+
hash: 'SHA-256'
37+
},
38+
true,
39+
['encrypt', 'decrypt']
40+
);
41+
}
42+
43+
async function generateEcdsaKeyPair() {
44+
return await crypto.subtle.generateKey(
45+
{ name: 'ECDSA', namedCurve: 'P-384' },
46+
true,
47+
['sign', 'verify']
48+
);
49+
}
50+
51+
async function signData(privateKey, data) {
52+
const encoded = new TextEncoder().encode(data);
53+
return await crypto.subtle.sign(
54+
{ name: 'ECDSA', hash: 'SHA-384' },
55+
privateKey,
56+
encoded
57+
);
58+
}
59+
60+
async function verifySignature(publicKey, signature, data) {
61+
const encoded = new TextEncoder().encode(data);
62+
return await crypto.subtle.verify(
63+
{ name: 'ECDSA', hash: 'SHA-384' },
64+
publicKey,
65+
signature,
66+
encoded
67+
);
68+
}
69+
70+
async function hashSha256(data) {
71+
const encoded = new TextEncoder().encode(data);
72+
return await crypto.subtle.digest('SHA-256', encoded);
73+
}
74+
75+
async function deriveKeyPbkdf2(password, salt) {
76+
const encoded = new TextEncoder().encode(password);
77+
const keyMaterial = await crypto.subtle.importKey(
78+
'raw',
79+
encoded,
80+
'PBKDF2',
81+
false,
82+
['deriveBits', 'deriveKey']
83+
);
84+
return await crypto.subtle.deriveKey(
85+
{
86+
name: 'PBKDF2',
87+
salt,
88+
iterations: 100000,
89+
hash: 'SHA-256'
90+
},
91+
keyMaterial,
92+
{ name: 'AES-GCM', length: 256 },
93+
true,
94+
['encrypt', 'decrypt']
95+
);
96+
}
97+
98+
export {
99+
generateAesKey,
100+
encryptData,
101+
decryptData,
102+
generateRsaKeyPair,
103+
generateEcdsaKeyPair,
104+
signData,
105+
verifySignature,
106+
hashSha256,
107+
deriveKeyPbkdf2
108+
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{"assetType":"library","identifier":"Node.js crypto","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":2,"column":1}}
2+
{"assetType":"algorithm","identifier":"SHA-256","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":17,"column":25},"metadata":{"primitive":"hash"}}
3+
{"assetType":"algorithm","identifier":"SHA-256","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":31,"column":25},"metadata":{"primitive":"hash"}}
4+
{"assetType":"algorithm","identifier":"scrypt","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":108,"column":19},"metadata":{"primitive":"kdf"}}
5+
{"assetType":"algorithm","identifier":"SHA-512","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":24,"column":25},"metadata":{"primitive":"hash"}}
6+
{"assetType":"algorithm","identifier":"AES-GCM","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":39,"column":27},"metadata":{"primitive":"symmetric","keySize":256}}
7+
{"assetType":"algorithm","identifier":"AES-GCM","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":53,"column":29},"metadata":{"primitive":"symmetric","keySize":256}}
8+
{"assetType":"algorithm","identifier":"ChaCha20-Poly1305","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":122,"column":27},"metadata":{"primitive":"symmetric"}}
9+
{"assetType":"algorithm","identifier":"ECDSA","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":93,"column":46},"metadata":{"curve":"P-384","primitive":"signature"}}
10+
{"assetType":"algorithm","identifier":"RSA","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":80,"column":16},"metadata":{"primitive":"asymmetric","keySize":4096}}
11+
{"assetType":"algorithm","identifier":"HKDF","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":117,"column":19},"metadata":{"primitive":"kdf"}}
12+
{"assetType":"algorithm","identifier":"Ed25519","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":70,"column":46},"metadata":{"primitive":"signature"}}
13+
{"assetType":"algorithm","identifier":"PBKDF2","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":103,"column":19},"metadata":{"primitive":"kdf","iterations":100000}}
14+
{"assetType":"algorithm","identifier":"AES-CBC","path":"fixtures/typescript/node_crypto/src/test.ts","evidence":{"line":62,"column":27},"metadata":{"primitive":"symmetric","keySize":256}}

0 commit comments

Comments
 (0)