← All hunts high TLP:CLEAR Part 1 of 2

Obfuscated JavaScript and Local Collection

An intruder is using obfuscated JavaScript within npm install scripts or malicious browser extensions to collect credentials and cookies from the local endpoint while evading static analysis.

Based on research by Cisco Talos 2026-09-29 12 steps · 5 queries T1041 T1115 T1176 T1566

Brief

Why this hunt?

Talos Intelligence recently detailed how attackers use JavaScript obfuscation to transform simple phishing kits into persistent credential stealers in their article, JavaScript obfuscation: From party trick to phishing kit. While obfuscation is common in legitimate web development, its application within npm install scripts or browser extensions provides a stealthy path for local collection that traditional static analysis often misses.

The Hunt Flow

The hunt begins by narrowing the search to hosts with npm or Node.js installed. This scoping step reduces noise by focusing on environments where developers frequently run packages that might contain malicious install hooks, rather than scanning the entire estate for general web traffic.

Once the scope is set, the hunt runs two parallel queries. The first identifies shell processes launched directly by npm or Node, which often indicates an install-time script execution. The second query scans script content for deobfuscation primitives like "atob", "String.fromCharCode", and "eval". These primitives are the building blocks of multi-stage script execution used to hide malicious intent.

An analyst then triages these findings. They look for instances where suspicious npm process chains correlate with the presence of deobfuscated script fragments. This stage filters out standard minified libraries that use similar functions for benign reasons by looking for non-standard parent-child process relationships.

The hunt then pivots to follow-on activity. It searches for rare browser extension file changes, specifically looking for new manifest files in user profile directories. This identifies persistence mechanisms that an obfuscated script might have installed to maintain access to the user's browser environment.

Finally, the hunt checks for the execution of collection utilities like "clip.exe" or "pbpaste". The use of these tools on a host that previously showed suspicious script behavior completes the attack chain, providing high-confidence evidence of an active intrusion focused on data theft.

Blind Spots

This hunt relies on visibility into script block execution. If the telemetry does not capture the cleartext string at the final execution sink, the analyst only sees the obfuscated wrapper. Additionally, if an adversary uses an ephemeral extension—one that installs, steals data, and immediately uninstalls—the hunt may miss the persistence phase if it depends on snapshot-based inventory instead of real-time file event auditing.

In this series

Steps

  1. Scope hosts with npm installed

    Query · scoping

    Identify machines with npm packages or node.js installed to narrow the search for malicious install scripts.

    reads hb_software_inventorysql
    SELECT DISTINCT device_hostname, package_name, package_version FROM hb_software_inventory WHERE package_type = 'npm' OR LOWER(package_name) LIKE '%node%'

    What a hit looks like. A list of hosts likely to run developer workloads or handle npm packages. Silence implies no npm-managed software is in the inventory.

  2. Suspicious npm install scripts

    Query · detection candidate

    Find shells launched from npm during package installation which are commonly used for malware delivery.

    reads hb_process_activitysql
    SELECT device_hostname, process_name, process_cmd_line, parent_process_name, time FROM hb_process_activity WHERE (LOWER(parent_process_name) LIKE '%npm%' OR LOWER(parent_process_name) LIKE '%node%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. Processes like sh, bash, or cmd.exe running as children of npm or node. Presence of arbitrary commands suggests a malicious hook.

  3. Obfuscated script block detection

    Query · triage

    Identify script blocks using deobfuscation primitives or anti-analysis signals in the actual script text.

    reads hb_script_activitysql
    SELECT device_hostname, script_content, script_type, time FROM hb_script_activity WHERE (LOWER(script_content) LIKE '%string.fromcharcode%' OR LOWER(script_content) LIKE '%atob%(' OR LOWER(script_content) LIKE '%navigator.webdriver%' OR LOWER(script_content) LIKE '%eval%(') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. Script fragments resolving strings at runtime or checking for automated browser environments. Minified libraries may trigger false positives.

  4. Evaluate execution and obfuscation

    Agent triage

    Determine if the observed npm behavior and script deobfuscation primitives correlate to a single host or campaign.

  5. Rare browser extension file activity

    Query · baseline

    Identify new or modified browser extensions that may have been installed by the obfuscated script.

    reads hb_file_activitysql
    SELECT LOWER(file_path) AS ext_path, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_file_activity WHERE (LOWER(file_path) LIKE '%/extensions/%' OR LOWER(file_path) LIKE '%\extensions\%' OR LOWER(file_path) LIKE '%manifest.json%') AND activity_id = 1 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY 1 HAVING host_count <= 3 ORDER BY host_count ASC

    What a hit looks like. Extension paths found on only a few hosts. New manifest files in user profile directories across multiple platforms.

  6. Execution of collection utilities

    Query · enrichment

    Find the use of standard OS utilities for stealing clipboard data or browser credentials.

    reads hb_process_activitysql
    SELECT device_hostname, process_name, process_cmd_line, time FROM hb_process_activity WHERE (instr(',' || '{{suspicious_binaries}}' || ',', ',' || LOWER(process_name) || ',') > 0 OR instr(',' || '{{suspicious_binaries}}' || ',', ',' || LOWER(process_cmd_line) || ',') > 0) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')

    What a hit looks like. The use of clip.exe or pbpaste on hosts where suspicious JS or npm activity was previously identified.

  7. Final assessment of attack chain

    Agent triage

    Synthesize the early execution evidence with the follow-on persistence and collection activity to confirm a full intrusion.

  8. Route based on verdict

    Decision

    Decide whether to isolate the host for immediate response or proceed with manual review.

  9. Isolate compromised host

    Response action

    Prevent further exfiltration and stop the malicious extension or script from running.

  10. Manual analyst review

    Analyst task

    Conduct a deep dive into the deobfuscated script content and verify the extent of the collection.

  11. Hunt closure and documentation

    Analyst task

    Document findings, tune baseline parameters, and close the hunt.

Coverage

Scenario coverage

StageCoveredHow, or why not
Malicious Package Installation
T1566
Yes npm-install-scripts
JavaScript Obfuscation and Anti-Analysis
T1176
Yes obfuscated-script-content
Browser Extension Abuse
T1176
Yes browser-extension-changes
Credential and Browser Data Collection
T1115
Yes credential-collection-utilities
Phishing Kit and Social Engineering Delivery
T1566
Out of scope Belongs to another part of the 'JavaScript obfuscation: From party trick to phishing kit' series.
Exfiltration via Web Request
T1041
Out of scope Belongs to another part of the 'JavaScript obfuscation: From party trick to phishing kit' series.

Blind spots

  • Needs hb_script_activity with high block resolution. If the script is deobfuscated only at the final execution sink and logging does not capture the evaluated string, the hunt will only see the obfuscated wrapper. It would answer whether the deobfuscated script is visible in cleartext.
  • Needs hb_file_activity with real-time auditing. A script that installs, steals data, and then uninstalls an extension may leave no footprint in snapshot inventories, relying entirely on file events. It would answer whether the malicious extension was deleted before detection.

Parameters & data

Parameters

ParameterTypeDefaultWhat it is
lookback_daysnumber14Days of history to examine.
scope_hostslist[host]—Optional list of hostnames to focus the hunt on.
suspicious_binarieslist[string]clip.exe, pbpaste, get-clipboardBinaries or cmdlets associated with clipboard data collection.

Telemetry

SourceCategoryTelemetry
Endpoint telemetry (hb_ surfaces)endpointendpoint

Source

Download hunt.md Definition (JSON) An open hunt.md file; it runs anywhere that reads the format.
---
analysis: Standard rules may alert on 'atob' or 'eval', but they cannot differentiate
  between a legitimate minified library and a multi-stage deobfuscation routine. This
  hunt pivots from npm context to script content and rare extension persistence, distinguishing
  malice through the attack chain.
blind_spots:
- id: no-script-visibility
  question: whether the deobfuscated script is visible in cleartext
  requires: hb_script_activity with high block resolution
  risk: If the script is deobfuscated only at the final execution sink and logging
    does not capture the evaluated string, the hunt will only see the obfuscated wrapper.
  stage: defense-evasion-script-obfuscation
- id: ephemeral-extensions
  question: whether the malicious extension was deleted before detection
  requires: hb_file_activity with real-time auditing
  risk: A script that installs, steals data, and then uninstalls an extension may
    leave no footprint in snapshot inventories, relying entirely on file events.
  stage: persistence-browser-extensions
coverage:
- stage: execution-npm-install-scripts
  status: covered
  steps:
  - npm-install-scripts
- stage: defense-evasion-script-obfuscation
  status: covered
  steps:
  - obfuscated-script-content
- stage: persistence-browser-extensions
  status: covered
  steps:
  - browser-extension-changes
- stage: collection-credential-and-cookie-theft
  status: covered
  steps:
  - credential-collection-utilities
- reason: 'Belongs to another part of the ''JavaScript obfuscation: From party trick
    to phishing kit'' series.'
  stage: initial-access-phishing-delivery
  status: out_of_scope
- reason: 'Belongs to another part of the ''JavaScript obfuscation: From party trick
    to phishing kit'' series.'
  stage: exfiltration-over-c2
  status: out_of_scope
guardrails:
  claims: no_unsupported
  evidence: citation_required
  missing_data: not_benign
  telemetry: untrusted
hunt:
  applicability: campaign-specific
  handoff: promote-to-detection
  justification: JavaScript obfuscation is a primary method for hiding credential
    theft in phishing and malicious packages. A negative result over the estate confirms
    these deobfuscation primitives are not being abused for local collection.
  methodology: model-assisted
  trigger: intel-report
hypothesis: An intruder is using obfuscated JavaScript within npm install scripts
  or malicious browser extensions to collect credentials and cookies from the local
  endpoint while evading static analysis.
labels:
- hunt
- attack.t1566
- attack.t1176
- attack.t1115
- attack.t1041
- collection
- defense evasion
- execution
- exfiltration
- initial access
- persistence
name: Obfuscated JavaScript and Local Collection
parameters:
  lookback_days:
    default: '14'
    description: Days of history to examine.
    from:
      kind: manual
      observed: '2024-05-20'
      ref: standard-retention
    type: number
  scope_hosts:
    default: []
    description: Optional list of hostnames to focus the hunt on.
    from:
      kind: manual
      observed: '2024-05-20'
      ref: analyst-scoping
    type: list[host]
  suspicious_binaries:
    default:
    - clip.exe
    - pbpaste
    - get-clipboard
    description: Binaries or cmdlets associated with clipboard data collection.
    from:
      kind: article
      observed: '2024-05-20'
      ref: talos-js-obfuscation
    type: list[string]
provenance:
  authors:
  - name: Huntbase hunt generation
    org: huntbase.io
  generated:
    by: huntbase-hunt-generation
    from: https://blog.talosintelligence.com/javascript-obfuscation-from-party-trick-to-phishing-kit/
    gates:
    - dry-run
    - lint
    model: hb_google/gemini-3-flash-preview
rationale: Start with developer-heavy hosts or machines running node.js. Focus on
  user profiles where browser extensions and npm packages are locally installed.
references:
- name: "Talos \u2014 JavaScript obfuscation: From party trick to phishing kit"
  url: https://blog.talosintelligence.com/javascript-obfuscation-from-party-trick-to-phishing-kit/
related:
- hunt: initial-access-phishing-delivery
  reason: This hunt focuses on execution and collection, not the delivery vector.
  relation: out-of-scope-alternative
scenario:
  stages:
  - name: Phishing Kit and Social Engineering Delivery
    observables:
    - phishing kit
    - fake CAPTCHA
    - fake update flows
    - compromised website injections
    slug: initial-access-phishing-delivery
    tactic: initial-access
    techniques:
    - T1566
  - name: Malicious Package Installation
    observables:
    - npm package install scripts
    - npm tokens
    slug: execution-npm-install-scripts
    tactic: execution
    techniques:
    - T1566
  - name: JavaScript Obfuscation and Anti-Analysis
    observables:
    - eval()
    - atob()
    - String.fromCharCode()
    - atob('ZXZhbA==')
    - JSFuck
    - navigator.webdriver
    - control-flow flattening
    - _0x identifiers
    slug: defense-evasion-script-obfuscation
    tactic: defense-evasion
    techniques:
    - T1176
  - name: Browser Extension Abuse
    observables:
    - browser extension abuse
    - malicious software extensions
    slug: persistence-browser-extensions
    tactic: persistence
    techniques:
    - T1176
  - name: Credential and Browser Data Collection
    observables:
    - window.document.cookie
    - clipboard contents
    - clip.exe
    - pbpaste
    slug: collection-credential-and-cookie-theft
    tactic: collection
    techniques:
    - T1115
  - name: Exfiltration via Web Request
    observables:
    - https://example.com
    - fetch
    - ?password=
    slug: exfiltration-over-c2
    tactic: exfiltration
    techniques:
    - T1041
  summary: Threat actors employ sophisticated JavaScript obfuscation techniques, including
    packing, encoding, and JSFuck, to conceal malicious payloads in phishing kits,
    malware loaders, and npm packages. These scripts often include anti-analysis features
    like browser fingerprinting and control-flow flattening to evade detection while
    exfiltrating credentials and cookies from victim systems.
series:
  index: 1
  slug: javascript-obfuscation-from-party-trick-to-phishing-kit
  title: 'JavaScript obfuscation: From party trick to phishing kit'
  total: 2
severity: high
targets:
  analyst:
    name: Tier-2 analyst
    role: analyst
  endpoint:
    category: endpoint
    name: Endpoint telemetry (hb_ surfaces)
    telemetry:
    - endpoint
  hunter:
    agent: true
    name: Hunt agent
tlp: clear
type: investigation
---


# Obfuscated JavaScript and Local Collection

This hunt targets the intersection of developer-focused delivery through npm and client-side credential theft. It identifies suspicious npm install hooks and the use of deobfuscation primitives like atob, String.fromCharCode, and eval within script blocks. The hunt then pivots to look for resulting persistence via browser extensions and the execution of collection utilities like clip.exe, providing a full picture of the attack chain from execution to collection.

## scope-npm-hosts
<!-- Scope hosts with npm installed -->
Identify machines with npm packages or node.js installed to narrow the search for malicious install scripts.

```sqlite target=endpoint role=scoping
~~~yaml
expected: A list of hosts likely to run developer workloads or handle npm packages.
  Silence implies no npm-managed software is in the inventory.
reads:
- device_hostname
- package_name
- package_version
silence: not_evidence_of_absence
source: hb_software_inventory
verified: dry-run
verified_at: '2026-09-29'
~~~
SELECT DISTINCT device_hostname, package_name, package_version FROM hb_software_inventory WHERE package_type = 'npm' OR LOWER(package_name) LIKE '%node%'
```

## detect-early-execution
<!-- Detect execution and obfuscation -->
parallel:
- → npm-install-scripts
- → obfuscated-script-content
join: → triage-early-stage

## npm-install-scripts
<!-- Suspicious npm install scripts -->
Find shells launched from npm during package installation which are commonly used for malware delivery.

```sqlite target=endpoint role=detection-candidate params=(lookback_days=lookback_days, scope_hosts=scope_hosts)
~~~yaml
expected: Processes like sh, bash, or cmd.exe running as children of npm or node.
  Presence of arbitrary commands suggests a malicious hook.
reads:
- device_hostname
- process_name
- process_cmd_line
- parent_process_name
- time
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-29'
~~~
SELECT device_hostname, process_name, process_cmd_line, parent_process_name, time FROM hb_process_activity WHERE (LOWER(parent_process_name) LIKE '%npm%' OR LOWER(parent_process_name) LIKE '%node%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## obfuscated-script-content
<!-- Obfuscated script block detection -->
Identify script blocks using deobfuscation primitives or anti-analysis signals in the actual script text.

```sqlite target=endpoint role=triage params=(lookback_days=lookback_days, scope_hosts=scope_hosts)
~~~yaml
expected: Script fragments resolving strings at runtime or checking for automated
  browser environments. Minified libraries may trigger false positives.
reads:
- device_hostname
- script_content
- script_type
- time
silence: not_evidence_of_absence
source: hb_script_activity
verified: dry-run
verified_at: '2026-09-29'
~~~
SELECT device_hostname, script_content, script_type, time FROM hb_script_activity WHERE (LOWER(script_content) LIKE '%string.fromcharcode%' OR LOWER(script_content) LIKE '%atob%(' OR LOWER(script_content) LIKE '%navigator.webdriver%' OR LOWER(script_content) LIKE '%eval%(') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## triage-early-stage
<!-- Evaluate execution and obfuscation -->
```agent target=hunter
cite: required
context:
- npm-install-scripts
- obfuscated-script-content
max_iterations: 3
objective: Identify hosts where npm processes and deobfuscation primitives indicate
  a high likelihood of malicious script execution.
success_criteria: A per-host verdict of Malicious, Suspicious, or Benign citing specific
  script fragments or process chains.
tools:
- endpoint
```

## detect-follow-on-activity
<!-- Detect persistence and collection -->
parallel:
- → browser-extension-changes
- → credential-collection-utilities
join: → assess-full-chain

## browser-extension-changes
<!-- Rare browser extension file activity -->
Identify new or modified browser extensions that may have been installed by the obfuscated script.

```sqlite target=endpoint role=baseline params=(lookback_days=lookback_days, scope_hosts=scope_hosts)
~~~yaml
baseline:
  compare: first_seen
  window: '{{lookback_days}}d'
expected: Extension paths found on only a few hosts. New manifest files in user profile
  directories across multiple platforms.
prevalence:
  by: device_hostname
  key:
  - ext_path
  rare_below: 3
reads:
- file_path
- device_hostname
- time
- activity_id
silence: not_evidence_of_absence
source: hb_file_activity
verified: dry-run
verified_at: '2026-09-29'
~~~
SELECT LOWER(file_path) AS ext_path, COUNT(DISTINCT device_hostname) AS host_count, MIN(time) AS first_seen FROM hb_file_activity WHERE (LOWER(file_path) LIKE '%/extensions/%' OR LOWER(file_path) LIKE '%\extensions\%' OR LOWER(file_path) LIKE '%manifest.json%') AND activity_id = 1 AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY 1 HAVING host_count <= 3 ORDER BY host_count ASC
```

## credential-collection-utilities
<!-- Execution of collection utilities -->
Find the use of standard OS utilities for stealing clipboard data or browser credentials.

```sqlite target=endpoint role=enrichment params=(lookback_days=lookback_days, scope_hosts=scope_hosts, suspicious_binaries=suspicious_binaries)
~~~yaml
expected: The use of clip.exe or pbpaste on hosts where suspicious JS or npm activity
  was previously identified.
reads:
- device_hostname
- process_name
- process_cmd_line
- time
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-29'
~~~
SELECT device_hostname, process_name, process_cmd_line, time FROM hb_process_activity WHERE (instr(',' || '{{suspicious_binaries}}' || ',', ',' || LOWER(process_name) || ',') > 0 OR instr(',' || '{{suspicious_binaries}}' || ',', ',' || LOWER(process_cmd_line) || ',') > 0) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```

## assess-full-chain
<!-- Final assessment of attack chain -->
```agent target=hunter
cite: required
context:
- triage-early-stage
- browser-extension-changes
- credential-collection-utilities
max_iterations: 5
objective: Determine if any host shows a complete chain from suspicious execution
  to persistence and collection.
success_criteria: A detailed report identifying the compromised host, the malicious
  package or extension, and the scope of data collected.
tools:
- endpoint
```

## decision-route
<!-- Route based on verdict -->
if~: "the assess-full-chain verdict is malicious for at least one host" (confidence: high, judge=hunter)
then: → isolate-endpoint
indeterminate: → manual-review
unavailable: → manual-review (blind_spot: no-script-visibility)
else: → hunt-closure

## isolate-endpoint
<!-- Isolate compromised host -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the host immediately. Collect the suspected malicious binary or script before killing any associated processes.
```
→ manual-review

## manual-review
<!-- Manual analyst review -->
```manual target=analyst
Extract the script content from hb_script_activity. Use a controlled sandbox to recover the final payload. Identify any exfiltration endpoints found in the decoded strings.
```
→ hunt-closure

## hunt-closure
<!-- Hunt closure and documentation -->
```manual target=analyst
Record all identified IOCs including script hashes and extension IDs. Update prevalence baselines for extensions if legitimate software was flagged.
```
→ end

Run it

Take this hunt into your environment.

Open it in Huntbase to run every step against your own connections, with Scout weighing the evidence and your analysts in command. Or take the open hunt.md file anywhere that reads the format.

Machine-drafted by huntbase-hunt-generation using hb_google/gemini-3-flash-preview, gated by dry-run, lint, then reviewed by a person.