Proposed changes

this pr introduces an internal js parser:

based on dop251/goja and it uses jsluice as fallbak BishopFox/jsluice:

goja is pure go js parser independent of CGO, that’s why used it as default js parser.
the jsluice is behind the go build tags and can be & compiled by enabling the CGO_ENABLED=1

pkg/utils/jsparser/
extractor.go
extractor_goja.go
extractor_jsluice.go
matchers.go

the new flow is:

parser
-> pkg/utils/jsparser
-> goja backend when !cgo i.e. CGO_ENABLED=0
-> jsluice backend when cgo i.e. CGO_ENABLED=1

the parser layer now depends only on a generic API:

  • jsparser.Extract(...)
  • jsparser.IsPathCommonJSLibraryFile(...)
  • jsparser.Backend()

this removes parser coupling

the old build-specific parser files were removed and replaced with a single shared parser setup:

  • pkg/engine/parser/parser_options.go

parser selection is done using Go build tags:

  • extractor_jsluice.go//go:build cgo
  • extractor_goja.go//go:build !cgo

the default parser is goja, which removes the over head of CGO. maked the compilation easy on darwin arm64 devices

pure go build:

go build ./cmd/katana

uses:

  • goja/parser
  • no CGO dependency
  • cross-platform portable compilation

Proof

test:

test cases logs:
katana dev CGO_ENABLED=0 go test ./pkg/utils/jsparser -v
=== RUN TestExtractBasicPatterns
--- PASS: TestExtractBasicPatterns (0.00s)
=== RUN TestExtractCallPatterns
--- PASS: TestExtractCallPatterns (0.00s)
=== RUN TestExtractConcatenationAndIdentifiers
--- PASS: TestExtractConcatenationAndIdentifiers (0.00s)
=== RUN TestExtractTemplateLiteral
--- PASS: TestExtractTemplateLiteral (0.00s)
=== RUN TestIsPathCommonJSLibraryFile
=== RUN TestIsPathCommonJSLibraryFile/jquery
=== RUN TestIsPathCommonJSLibraryFile/react
=== RUN TestIsPathCommonJSLibraryFile/custom_app
--- PASS: TestIsPathCommonJSLibraryFile (0.00s)
--- PASS: TestIsPathCommonJSLibraryFile/jquery (0.00s)
--- PASS: TestIsPathCommonJSLibraryFile/react (0.00s)
--- PASS: TestIsPathCommonJSLibraryFile/custom_app (0.00s)
=== RUN TestIsLikelyEndpoint
=== RUN TestIsLikelyEndpoint/https://example.com/api/users
=== RUN TestIsLikelyEndpoint/wss://example.com/socket
=== RUN TestIsLikelyEndpoint//api/users
=== RUN TestIsLikelyEndpoint/./graphql
=== RUN TestIsLikelyEndpoint/../v1/login
=== RUN TestIsLikelyEndpoint/api/users
=== RUN TestIsLikelyEndpoint/rest/user.json
=== RUN TestIsLikelyEndpoint/graphql
=== RUN TestIsLikelyEndpoint/data:text/plain,hello
=== RUN TestIsLikelyEndpoint/javascript:void(0)
=== RUN TestIsLikelyEndpoint/#
=== RUN TestIsLikelyEndpoint/hello_world
--- PASS: TestIsLikelyEndpoint (0.00s)
--- PASS: TestIsLikelyEndpoint/https://example.com/api/users (0.00s)
--- PASS: TestIsLikelyEndpoint/wss://example.com/socket (0.00s)
--- PASS: TestIsLikelyEndpoint//api/users (0.00s)
--- PASS: TestIsLikelyEndpoint/./graphql (0.00s)
--- PASS: TestIsLikelyEndpoint/../v1/login (0.00s)
--- PASS: TestIsLikelyEndpoint/api/users (0.00s)
--- PASS: TestIsLikelyEndpoint/rest/user.json (0.00s)
katana dev CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o cgo-disabled-katana-darwin-arm64 ./cmd/katana
katana dev ls -lah | grep dar
.rwxr-xr-x 61M trash 11 Mar 18:58 cgo-disabled-katana-darwin-arm64
.rw-r--r-- 19k trash 11 Mar 18:25 output_standard.txt
katana dev CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 go build -o cgo-disabled-katana-darwin-arm64 ./cmd/katana
katana dev CGO_ENABLED=0 go test ./pkg/utils/jsparser -v
=== RUN TestExtractBasicPatterns
--- PASS: TestExtractBasicPatterns (0.00s)
=== RUN TestExtractCallPatterns
--- PASS: TestExtractCallPatterns (0.00s)
=== RUN TestExtractConcatenationAndIdentifiers
--- PASS: TestExtractConcatenationAndIdentifiers (0.00s)
=== RUN TestExtractTemplateLiteral
--- PASS: TestExtractTemplateLiteral (0.00s)
=== RUN TestIsPathCommonJSLibraryFile
=== RUN TestIsPathCommonJSLibraryFile/jquery
=== RUN TestIsPathCommonJSLibraryFile/react
=== RUN TestIsPathCommonJSLibraryFile/custom_app
--- PASS: TestIsPathCommonJSLibraryFile (0.00s)
--- PASS: TestIsPathCommonJSLibraryFile/jquery (0.00s)
--- PASS: TestIsPathCommonJSLibraryFile/react (0.00s)
--- PASS: TestIsPathCommonJSLibraryFile/custom_app (0.00s)
=== RUN TestIsLikelyEndpoint
=== RUN TestIsLikelyEndpoint/https://example.com/api/users
=== RUN TestIsLikelyEndpoint/wss://example.com/socket
=== RUN TestIsLikelyEndpoint//api/users
=== RUN TestIsLikelyEndpoint/./graphql
=== RUN TestIsLikelyEndpoint/../v1/login
=== RUN TestIsLikelyEndpoint/api/users
=== RUN TestIsLikelyEndpoint/rest/user.json
=== RUN TestIsLikelyEndpoint/graphql
=== RUN TestIsLikelyEndpoint/data:text/plain,hello
=== RUN TestIsLikelyEndpoint/javascript:void(0)
=== RUN TestIsLikelyEndpoint/#
=== RUN TestIsLikelyEndpoint/hello_world
--- PASS: TestIsLikelyEndpoint (0.00s)
--- PASS: TestIsLikelyEndpoint/https://example.com/api/users (0.00s)
--- PASS: TestIsLikelyEndpoint/wss://example.com/socket (0.00s)
--- PASS: TestIsLikelyEndpoint//api/users (0.00s)
--- PASS: TestIsLikelyEndpoint/./graphql (0.00s)
--- PASS: TestIsLikelyEndpoint/../v1/login (0.00s)
--- PASS: TestIsLikelyEndpoint/api/users (0.00s)
--- PASS: TestIsLikelyEndpoint/rest/user.json (0.00s)
--- PASS: TestIsLikelyEndpoint/graphql (0.00s)
--- PASS: TestIsLikelyEndpoint/data:text/plain,hello (0.00s)
--- PASS: TestIsLikelyEndpoint/javascript:void(0) (0.00s)
--- PASS: TestIsLikelyEndpoint/# (0.00s)
--- PASS: TestIsLikelyEndpoint/hello_world (0.00s)
=== RUN TestClassifyEndpoint
=== RUN TestClassifyEndpoint/https://example.com/api
=== RUN TestClassifyEndpoint/wss://example.com/socket
=== RUN TestClassifyEndpoint//api/users
=== RUN TestClassifyEndpoint/api/users
--- PASS: TestClassifyEndpoint (0.00s)
--- PASS: TestClassifyEndpoint/https://example.com/api (0.00s)
--- PASS: TestClassifyEndpoint/wss://example.com/socket (0.00s)
--- PASS: TestClassifyEndpoint//api/users (0.00s)
--- PASS: TestClassifyEndpoint/api/users (0.00s)
=== RUN TestDedupeEndpoints
--- PASS: TestDedupeEndpoints (0.00s)
PASS
ok github.com/projectdiscovery/katana/pkg/utils/jsparser (cached)
katana dev CGO_ENABLED=1 go test ./pkg/utils/jsparser -v
=== RUN TestExtractBasicPatterns
--- PASS: TestExtractBasicPatterns (0.00s)
=== RUN TestExtractCallPatterns
--- PASS: TestExtractCallPatterns (0.00s)
=== RUN TestExtractConcatenationAndIdentifiers
--- PASS: TestExtractConcatenationAndIdentifiers (0.00s)
=== RUN TestExtractTemplateLiteral
--- PASS: TestExtractTemplateLiteral (0.00s)
=== RUN TestIsPathCommonJSLibraryFile
=== RUN TestIsPathCommonJSLibraryFile/jquery
=== RUN TestIsPathCommonJSLibraryFile/react
=== RUN TestIsPathCommonJSLibraryFile/custom_app
--- PASS: TestIsPathCommonJSLibraryFile (0.00s)
--- PASS: TestIsPathCommonJSLibraryFile/jquery (0.00s)
--- PASS: TestIsPathCommonJSLibraryFile/react (0.00s)
--- PASS: TestIsPathCommonJSLibraryFile/custom_app (0.00s)
=== RUN TestIsLikelyEndpoint
=== RUN TestIsLikelyEndpoint/https://example.com/api/users
=== RUN TestIsLikelyEndpoint/wss://example.com/socket
=== RUN TestIsLikelyEndpoint//api/users
=== RUN TestIsLikelyEndpoint/./graphql
=== RUN TestIsLikelyEndpoint/../v1/login
=== RUN TestIsLikelyEndpoint/api/users
=== RUN TestIsLikelyEndpoint/rest/user.json
=== RUN TestIsLikelyEndpoint/graphql
=== RUN TestIsLikelyEndpoint/data:text/plain,hello
=== RUN TestIsLikelyEndpoint/javascript:void(0)
=== RUN TestIsLikelyEndpoint/#
=== RUN TestIsLikelyEndpoint/hello_world
--- PASS: TestIsLikelyEndpoint (0.00s)
--- PASS: TestIsLikelyEndpoint/https://example.com/api/users (0.00s)
--- PASS: TestIsLikelyEndpoint/wss://example.com/socket (0.00s)
--- PASS: TestIsLikelyEndpoint//api/users (0.00s)
--- PASS: TestIsLikelyEndpoint/./graphql (0.00s)
--- PASS: TestIsLikelyEndpoint/../v1/login (0.00s)
--- PASS: TestIsLikelyEndpoint/api/users (0.00s)
--- PASS: TestIsLikelyEndpoint/rest/user.json (0.00s)
--- PASS: TestIsLikelyEndpoint/graphql (0.00s)
--- PASS: TestIsLikelyEndpoint/data:text/plain,hello (0.00s)
--- PASS: TestIsLikelyEndpoint/javascript:void(0) (0.00s)
--- PASS: TestIsLikelyEndpoint/# (0.00s)
--- PASS: TestIsLikelyEndpoint/hello_world (0.00s)
=== RUN TestClassifyEndpoint
=== RUN TestClassifyEndpoint/https://example.com/api
=== RUN TestClassifyEndpoint/wss://example.com/socket
=== RUN TestClassifyEndpoint//api/users
=== RUN TestClassifyEndpoint/api/users
--- PASS: TestClassifyEndpoint (0.00s)
--- PASS: TestClassifyEndpoint/https://example.com/api (0.00s)
--- PASS: TestClassifyEndpoint/wss://example.com/socket (0.00s)
--- PASS: TestClassifyEndpoint//api/users (0.00s)
--- PASS: TestClassifyEndpoint/api/users (0.00s)
=== RUN TestDedupeEndpoints
--- PASS: TestDedupeEndpoints (0.00s)
PASS
ok github.com/projectdiscovery/katana/pkg/utils/jsparser (cached)

recording-2026-03-11-18-59-18.webm

recording-2026-03-11-19-09-29.webm

Checklist

  • Pull request is created against the dev branch
  • All checks passed (lint, unit/integration/regression tests etc.) with my changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

/claim #1367

Claim

Total prize pool $400
Total paid $0
Status Pending
Submitted March 11, 2026
Last updated March 11, 2026

Contributors

TR

tribhuwan

@tribhuwan-kumar

100%

Sponsors

PR

ProjectDiscovery

@projectdiscovery

$200
HE

Hermes1118

@dalledajay-gmail-com

$200