# NPM Lifecycle Script Change Monitor — Install Script Risk Diff (`bin_ai_tools/my-actor-4`) Actor

Compare the latest npm release with the previous stable release to identify added, changed, or removed install-time lifecycle scripts—without downloading or executing package code.

- **URL**: https://apify.com/bin\_ai\_tools/my-actor-4.md
- **Developed by:** [Bin Bin](https://apify.com/bin_ai_tools) (community)
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 lifecycle script comparisons

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## NPM Lifecycle Script Change Monitor — Install Script Risk Diff

Monitor public npm package releases and see whether the newest release adds, changes, or removes install-time lifecycle scripts compared with the immediately previous stable release.

### What it checks

For each package, the Actor reads public npm Registry metadata for the current `dist-tags.latest` version and the highest previous stable semver release. It compares only:

- `preinstall`
- `install`
- `postinstall`

It does **not** download package tarballs, install target packages, or execute lifecycle scripts.

### Why this is useful

Install-time scripts can introduce new execution behavior during dependency installation. This Actor gives a factual release-to-release diff so a developer or security team can review that behavior before approving or adopting an update.

The result is a review signal, not a malware verdict.

### Input

```json
{
  "packages": ["esbuild", "sharp", "@scope/package"],
  "includeUnchanged": true
}
```

- `packages`: 1–50 public npm package names. Scoped packages are supported.
- `includeUnchanged`: when `false`, `NO_SCRIPT_CHANGE` rows are omitted from Dataset but still counted in OUTPUT.

Versions, tags, URLs, private registries, git dependencies and file dependencies are not accepted in v0.1.

### Events

- `NEW_INSTALL_SCRIPT` — a lifecycle script did not exist in the previous release and exists now.
- `SCRIPT_CHANGED` — the same lifecycle script exists in both releases but its trimmed command text changed.
- `SCRIPT_REMOVED` — a lifecycle script existed previously and is absent now.
- `NO_SCRIPT_CHANGE` — none of the three monitored lifecycle scripts changed.

Package-level severity is triage only:

- `high` — at least one `NEW_INSTALL_SCRIPT`
- `medium` — at least one `SCRIPT_CHANGED` and no new script
- `info` — only removals
- `none` — no script change

### Dataset example

```json
{
  "package": "example-package",
  "previousVersion": "1.2.0",
  "currentVersion": "1.3.0",
  "event": "NEW_INSTALL_SCRIPT",
  "severity": "high",
  "changedScripts": 1,
  "changes": [
    {
      "script": "postinstall",
      "type": "NEW_INSTALL_SCRIPT",
      "severity": "high",
      "previousValue": null,
      "currentValue": "node setup.js"
    }
  ],
  "previousScripts": {
    "preinstall": null,
    "install": null,
    "postinstall": null
  },
  "currentScripts": {
    "preinstall": null,
    "install": null,
    "postinstall": "node setup.js"
  },
  "checkedAt": "2026-09-16T00:00:00.000Z"
}
```

### OUTPUT

`OUTPUT` summarizes:

- packages requested / scanned / failed
- packages with lifecycle-script changes
- count of new, changed and removed scripts
- count of packages with no lifecycle-script change
- bounded per-package failures

One missing or unavailable package does not discard successful checks for the rest of the batch. If every package fails, the Actor writes diagnostic OUTPUT and fails the run.

### Version comparison behavior

The comparison is release-to-release, not run-to-run:

1. current release = `dist-tags.latest`
2. previous release = highest valid semver below current
3. prereleases are excluded when current latest is stable
4. if current latest is itself a prerelease, prior prereleases may be compared
5. first releases use an empty previous-script set

No persistent monitoring state is required in v0.1.

### Safety and limitations

- Public default npm Registry only.
- No npm authentication.
- No package tarball downloads.
- No `npm install` of target packages.
- No execution or shell parsing of script values.
- No malware classification, CVE scanning, maintainer monitoring, typosquat detection, license analysis, dependency-tree scanning or lockfile scanning.
- `prepare` is intentionally excluded for registry-package v0.1; non-registry dependency sources are out of scope.

Use the output as evidence for review. `NEW_INSTALL_SCRIPT` does not mean a package is malicious, and `NO_SCRIPT_CHANGE` does not mean a package is safe.

### Product expansion rule

v0.1 is the Apify validation product only. If real usage shows demand, the same platform-independent diff core can later support:

- n8n for alert automation
- MCP for agent pre-install checks
- GitHub Action for dependency-update review
- API / CLI for developer and CI workflows

No second adapter is included until real external usage or integration demand exists.

### Open-source reference

The product direction was informed by [`daniellockyer/npm-scan`](https://github.com/daniellockyer/npm-scan), an MIT-licensed project that demonstrates the value of watching npm publishes for newly introduced install scripts. This Actor independently implements a smaller Registry-metadata diff core and does not copy or vendor that project's implementation.

# Actor input Schema

## `packages` (type: `array`):

Add 1–50 public npm package names. Scoped packages such as @scope/package are supported. Do not include versions, tags, URLs, or private registries.

## `includeUnchanged` (type: `boolean`):

When enabled, Dataset includes NO\_SCRIPT\_CHANGE rows. OUTPUT counts all successfully checked packages either way.

## Actor input object example

```json
{
  "packages": [
    "esbuild",
    "sharp",
    "lodash"
  ],
  "includeUnchanged": true
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "packages": [
        "esbuild",
        "sharp",
        "lodash"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("bin_ai_tools/my-actor-4").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "packages": [
        "esbuild",
        "sharp",
        "lodash",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("bin_ai_tools/my-actor-4").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "packages": [
    "esbuild",
    "sharp",
    "lodash"
  ]
}' |
apify call bin_ai_tools/my-actor-4 --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bin_ai_tools/my-actor-4"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/WZMPaOvBxO9uTx4VP/builds/CYzhgjZsugoKr0NRt/openapi.json
