code-review-tools.md (25175B)
1 --- 2 title: "Source Code Review / SAST Tools" 3 section: "Network Services" 4 sectionSlug: "network-services-pentesting" 5 sourcePath: "src/network-services-pentesting/pentesting-web/code-review-tools.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/code-review-tools.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Source Code Review / SAST Tools 14 15 ## Guidance and tool lists 16 17 - [**https://owasp.org/www-community/Source_Code_Analysis_Tools**](https://owasp.org/www-community/Source_Code_Analysis_Tools) 18 - [**https://github.com/analysis-tools-dev/static-analysis**](https://github.com/analysis-tools-dev/static-analysis) 19 20 ## C/C++ Manual Review Gotchas 21 22 When reviewing **C/C++** manually, look for APIs and patterns that appear safe in isolation but become exploitable when their outputs are reused later in the control flow.<sup>[[1]](#references)[[2]](#references)</sup> 23 24 ### Non-reentrant libc return buffers breaking security checks 25 26 Some legacy networking/string helpers return pointers to **static internal storage**. A classic example is `inet_ntoa()`: storing the returned pointer and calling the function again usually means the second call overwrites the same buffer. 27 28 ```c 29 char *user_ip = inet_ntoa(addr_from_user); 30 char *allowed_ip = inet_ntoa(addr_from_policy); 31 32 if (strcmp(user_ip, allowed_ip) != 0) { 33 return DENY; 34 } 35 ``` 36 37 This kind of code can silently collapse an **allowlist / equality check** because both pointers may reference the same final string. During review, treat these APIs as suspicious whenever the returned pointer is: 38 39 - stored for later comparison 40 - reused across branches 41 - relied on for policy decisions such as SSRF prevention or host allowlists 42 43 Prefer APIs that write into a caller-provided buffer (`inet_ntop`, `snprintf`, explicit copies with fixed bounds). 44 45 ### Validated input reused later in `system()` / shell-outs 46 47 A frequent review failure is validating input with a parser and later reusing the **original raw string** in a shell command: 48 49 ```c 50 if (!inet_aton(ip_addr, &parsed)) { 51 return 1; 52 } 53 54 snprintf(cmd, sizeof(cmd), "ping '%s'", ip_addr); 55 system(cmd); 56 ``` 57 58 Parsing the data does **not** make the original string safe. If execution reaches `system()`, `popen()`, `execl("/bin/sh", ...)`, or similar shell-backed helpers, metacharacters in the original input can still become **command injection / RCE**. 59 60 During review, check for this sequence: 61 62 1. Input is parsed or normalized into a structured object. 63 2. A security decision is made using the parsed form. 64 3. The original string is later passed to a shell. 65 66 Safer patterns: 67 68 - avoid the shell entirely 69 - use `execve()`/`posix_spawn()` with a fixed argv array 70 - derive the executed argument from the validated canonical form instead of the original input 71 72 ### User-controlled registry/config source steering kernel control flow 73 74 In Windows driver code, a **user-chosen registry path** or similar configuration source should not directly influence privileged control flow. Review patterns such as: 75 76 - `WdfRequestRetrieveInputBuffer` or IOCTL input supplying a registry path 77 - `RtlQueryRegistryValues(..., RTL_QUERY_REGISTRY_DIRECT, ...)` writing directly into stack/local variables 78 - queried values selecting callbacks, operation modes, or other security-sensitive branches 79 80 If the attacker controls the key path, they often control not only the data but also the **value type, size, and presence/absence semantics**. That can turn a "read config and choose a callback" workflow into **reliable DoS** and sometimes a **kernel code execution primitive**. 81 82 Red flags during review: 83 84 - absolute registry paths accepted from user mode 85 - no allowlist of trusted hives/keys 86 - no strict type/length validation before copying into integers/structs 87 - registry-derived values stored globally and later used as function pointers, dispatch selectors, or capability flags 88 89 ### Windows path handling footguns worth checking 90 91 For Windows usermode reviews, explicitly audit for:<sup>[[1]](#references)[[2]](#references)</sup> 92 93 - **unquoted path** issues in `CreateProcess*` call sites and service definitions 94 - ANSI/Wide-char mismatches that let Unicode characters transform during path canonicalization 95 - **WorstFit / Best-Fit** style issues where ANSI APIs reinterpret Unicode into separators or traversal primitives<sup>[[3]](#references)</sup> 96 97 These are especially relevant when a path passes through validation in wide-char form but is later consumed by an ANSI API or command line builder. 98 99 ## Multi-Language Tools 100 101 ### [Naxus - AI-Gents](https://www.naxusai.com/) 102 103 There is a **free package to review PRs**. 104 105 ### Agentic SAST pipelines 106 107 Modern **AI-assisted code review** works better as a **staged pipeline** than as a single `scan this repo` prompt. A practical pattern used by tools such as **[Visa Vulnerability Agentic Harness (VVAH)](https://github.com/visa/visa-vulnerability-agentic-harness)** is:<sup>[[4]](#references)[[5]](#references)</sup> 108 109 Large defensive initiatives such as Project Glasswing also illustrate the growing use of frontier models for vulnerability discovery, but model output still needs evidence-based human validation before remediation.<sup>[[7]](#references)</sup> 110 111 1. **Threat-model first**: inventory entrypoints, assets, trust boundaries, API boundaries, authz paths, taint candidates and reachable components before deep review. If available, enrich this with CMDB / known-CVE / control data so the model prioritizes realistic attack paths instead of isolated code smells. 112 2. **Split research by lens**: run separate passes for access control, business logic, crypto, deserialization, IaC, batch/ETL, or language-specific sinks instead of trusting one generic review. 113 3. **Require deterministic gates**: only promote a finding if it survives policy checks such as evidence completeness, majority voting, or repeated independent review. 114 4. **Add adversarial verification**: force a second pass that tries to prove the trust-boundary crossing and exploitability: attacker-controlled input, source-to-sink reachability, missing authorization, privilege boundary crossed, and realistic impact. 115 5. **Report chains, not only single bugs**: deduplicate related findings, map them to **CWE/CVSS**, and emit **SARIF** so the output can be ingested by code-scanning and vuln-management platforms. 116 117 This usually produces fewer but **higher-signal triage candidates** and is especially useful in large repos where the bottleneck is analyst triage time rather than raw finding count. 118 119 #### Quick start example with `vvaharness` 120 121 ```bash 122 python3 -m venv .venv 123 source .venv/bin/activate 124 pip install . 125 vvaharness doctor 126 vvaharness estimate --repo /path/to/target 127 vvaharness scan --repo /path/to/target --application-id 12345 128 ``` 129 130 Useful operational details: 131 132 - `vvaharness scan --resume` skips completed checkpoints after an interruption. 133 - Per-target output is written under `<target>/security-scan/` as Markdown reports, `*.sarif`, and `*_errors.jsonl`. 134 - Treat results as **triage candidates**, not confirmed vulns: this kind of pipeline is best at prioritising manual review, not replacing it. 135 136 ### [**Semgrep**](https://github.com/returntocorp/semgrep) 137 138 It's an **Open Source tool**. 139 140 #### Supported Languages 141 142 | Category | Languages | 143 | ------------ | ----------------------------------------------------------------------------------------------------- | 144 | GA | C# · Go · Java · JavaScript · JSX · JSON · PHP · Python · Ruby · Scala · Terraform · TypeScript · TSX | 145 | Beta | Kotlin · Rust | 146 | Experimental | Bash · C · C++ · Clojure · Dart · Dockerfile · Elixir · HTML · Julia · Jsonnet · Lisp · | 147 148 #### Quick Start 149 150 ```bash 151 # Install https://github.com/returntocorp/semgrep#option-1-getting-started-from-the-cli 152 brew install semgrep 153 154 # Go to your repo code and scan 155 cd repo 156 semgrep scan --config auto 157 ``` 158 159 You can also use the [**semgrep VSCode Extension**](https://marketplace.visualstudio.com/items?itemName=Semgrep.semgrep) to get the findings inside VSCode. 160 161 ### [**SonarQube**](https://www.sonarsource.com/products/sonarqube/downloads/) 162 163 There is an installable **free version**. 164 165 #### Quick Start 166 167 ```bash 168 # Run the platform in Docker 169 docker run -d --name sonarqube -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true -p 9000:9000 sonarqube:latest 170 # Install cli tool 171 brew install sonar-scanner 172 173 # Go to localhost:9000 and login with admin:admin or admin:sonar 174 # Generate a local project and then a TOKEN for it 175 176 # Using the token and from the folder with the repo, scan it 177 cd path/to/repo 178 sonar-scanner \ 179 -Dsonar.projectKey=<project-name> \ 180 -Dsonar.sources=. \ 181 -Dsonar.host.url=http://localhost:9000 \ 182 -Dsonar.token=<sonar_project_token> 183 ``` 184 185 ### CodeQL 186 187 The CodeQL CLI is available for research and open-source use; review the current GitHub CodeQL terms before using it for private or commercial analysis. 188 189 #### Install 190 191 ```bash 192 # Download your release from https://github.com/github/codeql-action/releases 193 ## Example 194 wget https://github.com/github/codeql-action/releases/download/codeql-bundle-v2.14.3/codeql-bundle-osx64.tar.gz 195 196 # Move it to the destination folder 197 mkdir ~/codeql 198 mv codeql-bundle* ~/codeql 199 200 # Decompress it 201 cd ~/codeql 202 tar -xzvf codeql-bundle-*.tar.gz 203 rm codeql-bundle-*.tar.gz 204 205 # Add to path 206 echo 'export PATH="$PATH:/Users/username/codeql/codeql"' >> ~/.zshrc 207 208 # Check it's correctly installed 209 ## Open a new terminal 210 codeql resolve qlpacks #Get paths to QL packs 211 ``` 212 213 #### Quick Start - Prepare the database 214 215 > [!TIP] 216 > The first thing you need to do is to **prepare the database** (create the code tree) so later the queries are run over it. 217 218 - You can allow codeql to automatically identify the language of the repo and create the database 219 220 ```bash 221 codeql database create <database> --language <language> 222 223 # Example 224 codeql database create /path/repo/codeql_db --source-root /path/repo 225 ## DB will be created in /path/repo/codeql_db 226 ``` 227 228 > [!CAUTION] 229 > This may report an error when more than one language is specified or automatically detected. Use one of the following options. 230 231 - You can do this **manually indicating** the **repo** and the **language** ([list of languages](https://docs.github.com/en/code-security/codeql-cli/getting-started-with-the-codeql-cli/preparing-your-code-for-codeql-analysis#running-codeql-database-create)) 232 233 ```bash 234 codeql database create <database> --language <language> --source-root </path/to/repo> 235 236 # Example 237 codeql database create /path/repo/codeql_db --language javascript --source-root /path/repo 238 ## DB will be created in /path/repo/codeql_db 239 ``` 240 241 - If your repo is using **more than 1 language**, you can also create **1 DB per language** indicating each language. 242 243 ```bash 244 export GITHUB_TOKEN=ghp_32849y23hij4... 245 codeql database create <database> --source-root /path/to/repo --db-cluster --language "javascript,python" 246 247 # Example 248 export GITHUB_TOKEN=ghp_32849y23hij4... 249 codeql database create /path/repo/codeql_db --source-root /path/to/repo --db-cluster --language "javascript,python" 250 ## DBs will be created in /path/repo/codeql_db/* 251 ``` 252 253 - You can also allow `codeql` to **identify all the languages** for you and create a DB per language. You need to give it a **GITHUB_TOKEN**. 254 255 ```bash 256 export GITHUB_TOKEN=ghp_32849y23hij4... 257 codeql database create <database> --db-cluster --source-root </path/to/repo> 258 259 # Example 260 export GITHUB_TOKEN=ghp_32849y23hij4... 261 codeql database create /tmp/codeql_db --db-cluster --source-root /path/repo 262 ## DBs will be created in /path/repo/codeql_db/* 263 ``` 264 265 #### Quick Start - Analyze the code 266 267 > [!TIP] 268 > Now it's finally time to analyze the code 269 270 If you selected several languages, CodeQL creates **one database per language** under the specified path. 271 272 ```bash 273 # Default analysis 274 codeql database analyze <database> --format=<format> --output=</out/file/path> 275 # Example 276 codeql database analyze /tmp/codeql_db/javascript --format=sarif-latest --output=/tmp/graphql_results.sarif 277 278 # Specify QL pack to use in the analysis 279 codeql database analyze <database> \ 280 <qls pack> --sarif-category=<language> \ 281 --sarif-add-baseline-file-info --format=<format> \ 282 --output=/out/file/path> 283 # Example 284 codeql database analyze /tmp/codeql_db \ 285 javascript-security-extended --sarif-category=javascript \ 286 --sarif-add-baseline-file-info --format=sarif-latest \ 287 --output=/tmp/sec-extended.sarif 288 ``` 289 290 #### Quick Start - Scripted 291 292 ```bash 293 export GITHUB_TOKEN=ghp_32849y23hij4... 294 export REPO_PATH=/path/to/repo 295 export OUTPUT_DIR_PATH="$REPO_PATH/codeql_results" 296 mkdir -p "$OUTPUT_DIR_PATH" 297 export FINAL_MSG="Results available in: " 298 299 echo "Creating DB" 300 codeql database create "$REPO_PATH/codeql_db" --db-cluster --source-root "$REPO_PATH" 301 for db_path in "$REPO_PATH"/codeql_db/*; do 302 db=$(basename "$db_path") 303 echo "Analyzing $db" 304 codeql database analyze "$db_path" --format=sarif-latest --output="${OUTPUT_DIR_PATH}/$db.sarif" 305 FINAL_MSG="$FINAL_MSG ${OUTPUT_DIR_PATH}/$db.sarif ," 306 echo "" 307 done 308 309 echo $FINAL_MSG 310 ``` 311 312 You can visualize the findings in [**https://microsoft.github.io/sarif-web-component/**](https://microsoft.github.io/sarif-web-component/) or using VSCode extension [**SARIF viewer**](https://marketplace.visualstudio.com/items?itemName=MS-SarifVSCode.sarif-viewer). 313 314 You can also use the [**VSCode extension**](https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-codeql) to get the findings inside VSCode. You will still need to create a database manually, but then you can select any files and click on `Right Click` -> `CodeQL: Run Queries in Selected Files` 315 316 ### [**Snyk**](https://snyk.io/product/snyk-code/) 317 318 There is an **installable free version**. 319 320 #### Quick Start 321 322 ```bash 323 # Install 324 sudo npm install -g snyk 325 326 # Authenticate (you can use a free account) 327 snyk auth 328 329 # Test for open source vulns & license issues 330 snyk test [--all-projects] 331 332 # Test for code vulnerabilities 333 ## This will upload your code and you need to enable this option in: Settings > Snyk Code 334 snyk test code 335 336 # Test for vulns in images 337 snyk container test [image] 338 339 # Test for IaC vulns 340 snyk iac test 341 ``` 342 343 You can also use the [**snyk VSCode Extension**](https://marketplace.visualstudio.com/items?itemName=snyk-security.snyk-vulnerability-scanner) to get findings inside VSCode. 344 345 ### [Insider](https://github.com/insidersec/insider) 346 347 It's **Open Source**, but looks **unmaintained**. 348 349 #### Supported Languages 350 351 Java (Maven and Android), Kotlin (Android), Swift (iOS), .NET Full Framework, C#, and Javascript (Node.js). 352 353 #### Quick Start 354 355 ```bash 356 # Check the correct release for your environment 357 $ wget https://github.com/insidersec/insider/releases/download/2.1.0/insider_2.1.0_linux_x86_64.tar.gz 358 $ tar -xf insider_2.1.0_linux_x86_64.tar.gz 359 $ chmod +x insider 360 $ ./insider --tech javascript --target <projectfolder> 361 ``` 362 363 ### [**DeepSource**](https://deepsource.com/pricing) 364 365 Free for **public repos**. 366 367 ## NodeJS 368 369 - **`yarn`** 370 371 ```bash 372 # Install 373 brew install yarn 374 # Run 375 cd /path/to/repo 376 yarn install 377 yarn audit # In lower versions 378 yarn npm audit # In 2+ versions 379 380 npm audit 381 ``` 382 383 - **`pnpm`** 384 385 ```bash 386 # Install 387 npm install -g pnpm 388 # Run 389 cd /path/to/repo 390 pnpm install 391 pnpm audit 392 ``` 393 394 - [**nodejsscan**](https://github.com/ajinabraham/nodejsscan)**:** Static security code scanner (SAST) for Node.js applications powered by [libsast](https://github.com/ajinabraham/libsast) and [semgrep](https://github.com/returntocorp/semgrep). 395 396 ```bash 397 # Install & run 398 docker run -it -p 9090:9090 opensecurity/nodejsscan:latest 399 # Go to localhost:9090 400 # Upload a zip file with the code 401 ``` 402 403 - [**RetireJS**](https://github.com/RetireJS/retire.js)**:** The goal of Retire.js is to help you detect the use of JS-library versions with known vulnerabilities. 404 405 ```bash 406 # Install 407 npm install -g retire 408 # Run 409 cd /path/to/repo 410 retire --colors 411 ``` 412 413 ## Electron 414 415 - [**electronegativity**](https://github.com/doyensec/electronegativity)**:** It's a tool to identify misconfigurations and security anti-patterns in Electron-based applications. 416 417 ## Python 418 419 - [**Bandit**](https://github.com/PyCQA/bandit)**:** Bandit is a tool designed to find common security issues in Python code. To do this Bandit processes each file, builds an AST from it, and runs appropriate plugins against the AST nodes. Once Bandit has finished scanning all the files it generates a report. 420 421 ```bash 422 # Install 423 pip3 install bandit 424 425 # Run 426 bandit -r <path to folder> 427 ``` 428 429 - [**safety**](https://github.com/pyupio/safety): Safety checks Python dependencies for known security vulnerabilities and suggests the proper remediations for vulnerabilities detected. Safety can be run on developer machines, in CI/CD pipelines and on production systems. 430 431 ```bash 432 # Install 433 pip install safety 434 # Run 435 safety check 436 ``` 437 438 - [~~**Pyt**~~](https://github.com/python-security/pyt): Unmaintained. 439 440 ## .NET 441 442 ```bash 443 # dnSpy 444 https://github.com/0xd4d/dnSpy 445 446 # .NET compilation 447 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe test.cs 448 ``` 449 450 ## Rust 451 452 ```bash 453 # Install 454 cargo install cargo-audit 455 456 # Run 457 cargo audit 458 459 #Update the Advisory Database 460 cargo audit fetch 461 ``` 462 463 ## Java 464 465 ```bash 466 # JD-Gui 467 https://github.com/java-decompiler/jd-gui 468 469 # Java compilation step-by-step 470 javac -source 1.8 -target 1.8 test.java 471 mkdir META-INF 472 echo "Main-Class: test" > META-INF/MANIFEST.MF 473 jar cmvf META-INF/MANIFEST.MF test.jar test.class 474 ``` 475 476 | Task | Command | 477 | --------------- | --------------------------------------------------------- | 478 | Execute Jar | java -jar \[jar] | 479 | Unzip Jar | unzip -d \[output directory] \[jar] | 480 | Create Jar | jar -cmf META-INF/MANIFEST.MF \[output jar] \* | 481 | Base64 SHA256 | sha256sum \[file] \| cut -d' ' -f1 \| xxd -r -p \| base64 | 482 | Remove Signing | rm META-INF/_.SF META-INF/_.RSA META-INF/\*.DSA | 483 | Delete from Jar | zip -d \[jar] \[file to remove] | 484 | Decompile class | procyon -o . \[path to class] | 485 | Decompile Jar | procyon -jar \[jar] -o \[output directory] | 486 | Compile class | javac \[path to .java file] | 487 488 ## Go 489 490 ```bash 491 https://github.com/securego/gosec 492 ``` 493 494 ## PHP 495 496 [Psalm](https://phpmagazine.net/2018/12/find-errors-in-your-php-applications-with-psalm.html) and [PHPStan](https://phpmagazine.net/2020/09/phpstan-pro-edition-launched.html). 497 498 ### Wordpress Plugins 499 500 [https://www.pluginvulnerabilities.com/plugin-security-checker/](https://www.pluginvulnerabilities.com/plugin-security-checker/) 501 502 ## Solidity 503 504 - [https://www.npmjs.com/package/solium](https://www.npmjs.com/package/solium) 505 506 ## JavaScript 507 508 ### Discovery 509 510 1. Burp: 511 - Spider and discover content 512 - Sitemap > filter 513 - Sitemap > right-click domain > Engagement tools > Find scripts 514 2. [WaybackURLs](https://github.com/tomnomnom/waybackurls): 515 - `waybackurls <domain> |grep -i "\.js" |sort -u` 516 517 ### Static Analysis 518 519 #### Unminimize/Beautify/Prettify 520 521 - [https://prettier.io/playground/](https://prettier.io/playground/) 522 - [https://beautifier.io/](https://beautifier.io/) 523 - [OlaJS JavaScript Prettifier](https://olajs.com/javascript-prettifier)<sup>[[14]](#references)</sup> 524 - See some of the tools mentioned in 'Deobfuscate/Unpack' below as well. 525 526 #### Deobfuscate/Unpack 527 528 **Note**: It may not be possible to fully deobfuscate.<sup>[[6]](#references)</sup> 529 530 1. Find and use .map files: 531 - If the .map files are exposed, they can be used to easily deobfuscate. 532 - Commonly, foo.js.map maps to foo.js. Manually look for them. 533 - Use [JS Miner](https://github.com/PortSwigger/js-miner) to look for them. 534 - Ensure active scan is conducted. 535 - Read '[Tips/Notes](https://github.com/minamo7sen/burp-JS-Miner/wiki#tips--notes)' 536 - If found, use [Maximize](https://www.npmjs.com/package/maximize) to deobfuscate. 537 - For webpack chunk structure, runtime injection, React/Vue/Angular internals, and DevTools workflows, consult the webpack reverse-engineering notes and related JavaScript research gists.<sup>[[11]](#references)[[12]](#references)</sup> 538 2. Without .map files, try JSnice: 539 - References: [http://jsnice.org/](http://jsnice.org/) & [https://www.npmjs.com/package/jsnice](https://www.npmjs.com/package/jsnice) 540 - Tips: 541 - If using jsnice.org, click on the options button next to the "Nicify JavaScript" button, and de-select "Infer types" to reduce cluttering the code with comments. 542 - Ensure you do not leave any empty lines before the script, as it may affect the deobfuscation process and give inaccurate results. 543 3. For some more modern alternatives to JSNice, you might like to look at the following: 544 545 - [https://github.com/pionxzh/wakaru](https://github.com/pionxzh/wakaru) 546 - > Javascript decompiler, unpacker and unminify toolkit Wakaru is the Javascript decompiler for modern frontend. It brings back the original code from a bundled and transpiled source. 547 - [https://github.com/j4k0xb/webcrack](https://github.com/j4k0xb/webcrack) 548 - > Deobfuscate obfuscator.io, unminify and unpack bundled javascript 549 - [https://github.com/jehna/humanify](https://github.com/jehna/humanify) 550 - > Un-minify JavaScript code using an LLM. The model suggests variable and function names, while Babel performs structural transformations to preserve equivalent code. 551 - [https://thejunkland.com/blog/using-llms-to-reverse-javascript-minification.html](https://thejunkland.com/blog/using-llms-to-reverse-javascript-minification.html) 552 - > Using LLMs to reverse JavaScript variable name minification 553 554 4. Use `console.log()`: 555 - Find the return value at the end and change it to `console.log(<packerReturnVariable>);` so the deobfuscated JavaScript is printed instead of executed. 556 - Then, paste the modified (and still obfuscated) js into [https://jsconsole.com/](https://jsconsole.com/) to see the deobfuscated js logged to the console. 557 - Finally, paste the deobfuscated output into [https://prettier.io/playground/](https://prettier.io/playground/) to beautify it for analysis. 558 - **Note**: If you are still seeing packed (but different) js, it may be recursively packed. Repeat the process. 559 560 #### Tools 561 562 - [https://portswigger.net/burp/documentation/desktop/tools/dom-invader](https://portswigger.net/burp/documentation/desktop/tools/dom-invader) 563 - Dynamic-analysis walkthrough: DAST JavaScript Dynamic Analysis.<sup>[[8]](#references)</sup> 564 - Angular-specific review background: the archived “Angular for Pentesters” parts 1 and 2.<sup>[[9]](#references)[[10]](#references)</sup> 565 - [CyberChef](https://cyberchef.org/) is useful for decoding, decompressing, and transforming captured bundle data.<sup>[[13]](#references)</sup> 566 - [JSHint](https://jshint.com/) and its source repository provide lightweight JavaScript quality/static checks.<sup>[[15]](#references)[[16]](#references)</sup> 567 568 ## References 569 570 - [1] [Trail of Bits blog: Master C and C++ with our new Testing Handbook chapter](https://blog.trailofbits.com/2026/04/09/master-c-and-c-with-our-new-testing-handbook-chapter/) 571 - [2] [Trail of Bits Testing Handbook: C/C++](https://appsec.guide/docs/languages/c-cpp/) 572 - [3] [DEVCORE: WorstFit - Unveiling Hidden Transformers in Windows ANSI](https://devco.re/blog/2025/01/09/worstfit-unveiling-hidden-transformers-in-windows-ansi/) 573 - [4] [Visa Vulnerability Agentic Harness](https://github.com/visa/visa-vulnerability-agentic-harness) 574 - [5] [VVAH Architecture](https://github.com/visa/visa-vulnerability-agentic-harness/blob/main/docs/architecture.md) 575 - [6] [devalias – Deobfuscating / Unminifying Obfuscated Web App Code (GitHub Gist)](https://gist.github.com/0xdevalias/d8b743efb82c0e9406fc69da0d6c6581#deobfuscating--unminifying-obfuscated-web-app-code) 576 - [7] [Anthropic Project Glasswing](https://www.anthropic.com/glasswing) 577 - [8] [YouTube: DAST - Javascript Dynamic Analysis](https://www.youtube.com/watch?v=_v8r_t4v6hQ) 578 - [9] [nVisium Blog: Angular for Pentesters – Part 1](https://web.archive.org/web/20221226054137/https://blog.nvisium.com/angular-for-pentesters-part-1) 579 - [10] [nVisium Blog: Angular for Pentesters – Part 2](https://web.archive.org/web/20230204012439/https://blog.nvisium.com/angular-for-pentesters-part-2) 580 - [11] [devalias – Reverse Engineering Webpack Apps (GitHub Gist)](https://gist.github.com/0xdevalias/8c621c5d09d780b1d321bfdb86d67cdd#reverse-engineering-webpack-apps) 581 - [12] [devalias – further JavaScript-related GitHub Gists (search)](https://gist.github.com/search?q=user:0xdevalias+javascript) 582 - [13] [CyberChef](https://cyberchef.org/) 583 - [14] [OlaJS JavaScript Prettifier](https://olajs.com/javascript-prettifier) 584 - [15] [JSHint](https://jshint.com/) 585 - [16] [jshint (GitHub repository)](https://github.com/jshint/jshint/)