# AI Agent Stack Dependency Vulnerability Scanner (`kingii98/ai-agent-stack-dependency-vulnerability-scanner`) Actor

Resolve packages from a supplied dependency manifest, query the public OSV.dev advisory database, and return a ranked, import-checked fix list plus one pass/fail gate.

- **URL**: https://apify.com/kingii98/ai-agent-stack-dependency-vulnerability-scanner.md
- **Developed by:** [kingii98](https://apify.com/kingii98) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 manifest scanneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## AI Agent Stack Dependency Vulnerability Scanner

Give this Actor one or more dependency manifests as plain text. The Actor reads the packages named in each manifest, queries the public [OSV.dev](https://osv.dev/) advisory database, and reports each vulnerable package with a CVSS score, a fix version, and an import-presence flag. It also writes one run-level pass/fail gate. The Actor answers one question: **does this manifest pull in a known vulnerable package, and does the supplied source code import it?**

The Actor does not clone a repository, install a package, or run any code from a manifest. It reads the text you supply and calls the public OSV.dev API only.

### Supported ecosystems

| Ecosystem | Manifest text read | Heuristic notes |
|---|---|---|
| `PyPI` | `requirements.txt`-style lines (`name==version`) | Only exact `==` pins resolve; ranges and unpinned lines are skipped. |
| `npm` | `package.json`, or an npm `package-lock.json` (v1 or v2/v3) | A lock file's `node_modules/` nesting marks transitive packages. A plain `package.json` strips a `^`/`~`/range prefix to get a best-effort version and marks every entry `DIRECT`. |
| `Go` | `go.mod` | A `// indirect` comment marks a requirement `TRANSITIVE`. |
| `Maven` | `pom.xml` `<dependency>` blocks | Read with a bounded regex extraction, not an XML parser, so a manifest cannot trigger XML entity expansion. A version that is still a `${property}` placeholder cannot be resolved and is skipped. Every entry is marked `DIRECT`: a plain `pom.xml` does not show the resolved dependency tree. |
| `crates.io` | `Cargo.toml` `[dependencies]` tables, or a `Cargo.lock` | Every entry is marked `DIRECT`: a version 1 scanner does not walk `Cargo.lock`'s own dependency graph. |

This is a heuristic manifest reader, not a package manager's dependency solver. It does not compute a lock file from a bare manifest, and it does not run call-graph analysis. The `importPresence` field is a plain text search for the package name in the source files you supply — a name match, not proof that the vulnerable code path is reachable.

### Input

```json
{
  "manifests": [
    {"name": "requirements.txt", "ecosystem": "PyPI", "content": "django==1.11.1\nsix==1.16.0\n"}
  ],
  "sourceFiles": [
    {"path": "app/settings.py", "content": "import django\n"}
  ],
  "minCvss": 0.0,
  "includeTransitive": true,
  "failOnCvssAtOrAbove": 9.0
}
```

| Field | Description |
|---|---|
| `manifests` | 1-20 manifests. Each has `name`, `ecosystem` (`PyPI`, `npm`, `Go`, `Maven`, or `crates.io`), and `content` (the manifest text). Required. |
| `sourceFiles` | Optional, up to 2000 files. Each has `path` and `content`. Used only for the `importPresence` text search. |
| `minCvss` | Drop advisories below this CVSS score from the report and the gate. Default `0.0`. |
| `includeTransitive` | Resolve transitive packages when the manifest text carries that information. Default `true`. |
| `failOnCvssAtOrAbove` | The gate fails when any reported advisory's CVSS score is at or above this value. Default `9.0`. |

A run resolving more than 5000 packages across all manifests fails before any OSV.dev call is made.

### Output

Every run writes one `package-result` record for each resolved package that has at least one advisory at or above `minCvss`, plus one `gate-result` record, to the default dataset.

Package result:

```json
{
  "recordType": "package-result",
  "manifestName": "requirements.txt",
  "ecosystem": "PyPI",
  "packageName": "django",
  "resolvedVersion": "1.11.1",
  "dependencyKind": "DIRECT",
  "vulnerabilities": [
    {
      "osvId": "GHSA-xxxx",
      "aliases": ["CVE-2021-1234"],
      "summary": "SQL injection in QuerySet",
      "cvssScore": 9.8,
      "cvssVector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "severityBand": "CRITICAL",
      "introducedVersion": "0",
      "fixedVersion": "1.11.5",
      "publishedAt": "2021-01-01T00:00:00Z"
    }
  ],
  "importPresence": {"searched": true, "matchedFiles": ["app/settings.py"], "verdict": "IMPORTED"},
  "upgradePath": {"currentVersion": "1.11.1", "lowestSafeVersion": "1.11.5", "isMajorBump": false}
}
```

`importPresence.verdict` is `IMPORTED`, `NOT_IMPORTED`, or `UNKNOWN` (no `sourceFiles` were supplied, so nothing was searched).

Gate result:

```json
{
  "recordType": "gate-result",
  "gate": {"verdict": "FAIL", "highestCvss": 9.8, "failingPackageCount": 1, "threshold": 9.0},
  "summary": {
    "severityCounts": {"CRITICAL": 1, "HIGH": 0, "MEDIUM": 0, "LOW": 0, "NONE": 0, "UNKNOWN": 0},
    "rankedFixList": [
      {
        "manifestName": "requirements.txt",
        "packageName": "django",
        "resolvedVersion": "1.11.1",
        "highestCvss": 9.8,
        "imported": "IMPORTED",
        "lowestSafeVersion": "1.11.5"
      }
    ]
  }
}
```

`rankedFixList` is ordered by `highestCvss` descending, then by `IMPORTED` packages first. When `gate.verdict` is `FAIL`, the Actor run itself finishes with a non-zero exit code and a failed status message, so a CI job can gate a merge on the run outcome alone.

### CVSS scoring

OSV.dev advisory records carry a CVSS v3 vector string, not a precomputed score. The Actor computes the CVSS v3.1 base score from that vector using the published formula. When an advisory has no CVSS v3 vector, `cvssScore` is `null` and `severityBand` falls back to the advisory's own qualitative severity label (or `UNKNOWN` when neither is present). A `minCvss` above `0.0` drops an unscored advisory rather than guessing whether it clears the floor.

### Pricing

The Actor uses Apify pay-per-event pricing with three charge events:

| Event | Charged | Price |
|---|---|---|
| `manifest-scanned` | Once for each manifest in the input, parsed, resolved, and queried, whether or not it resolves to any package. | $0.05 |
| `package-resolved` | Once for each package resolution. The same package repeated across manifests is charged once per manifest it appears in, because parsing it cost CPU again each time. | $0.0006 |
| `vulnerability-detailed` | Once for each distinct OSV.dev advisory actually retrieved and enriched. A package/version pair repeated across manifests reuses the same OSV.dev query and detail fetch, so the advisory is charged once, not once per manifest. | $0.004 |

Apify platform usage (compute units and other resources consumed by the run) may still be shown to users according to their plan and Apify's pricing rules, as described in the Actor's listing.

Final pricing is configured in the Apify Store listing and may change subject to Apify's pricing-change notice rules.

### Security and privacy

- The Actor never fetches a URL you supply. It reads the manifest and source file text you pass in input, and it calls only the fixed, public OSV.dev API.
- The Actor does not use a browser, proxy, LLM, external database, or paid API.
- The Maven manifest reader is a bounded regex extraction, not an XML parser, so a `pom.xml` cannot trigger XML entity expansion.
- Manifest count, resolved package count, source file count, and per-field text length are all bounded before parsing begins.

Do not place secrets, private tokens, or personal data in any input field.

### Limitations

- Version resolution is heuristic: only exact pins resolve for `PyPI`; `npm`, `Maven`, and `crates.io` manifests without a lock file report the versions stated in the manifest text, not a real dependency solver's result.
- `dependencyKind` (`DIRECT`/`TRANSITIVE`) is only inferred where the manifest text itself carries that structure (an npm lock file's nesting, or a `go.mod` `// indirect` marker). Every other ecosystem reports `DIRECT` for every entry.
- `importPresence` is a plain-text name search across the supplied source files. It is a signal, not proof of reachability: it can both miss a dynamic import and match an unrelated identifier that happens to share the package's name.
- Version comparison for `upgradePath` and `minCvss` filtering uses a generic leading-numeric comparator, not each ecosystem's own version scheme (PEP 440, semver, Maven versioning, ...). Pre-release suffixes and epoch markers are ignored.
- The OSV.dev API is queried live; the Actor stores no advisory data between runs.

### Support

For reproducible issues, open an issue from the Actor page and include the Apify run ID, sanitized input, and expected result. Do not include API tokens or private data.

# Actor input Schema

## `manifests` (type: `array`):

1-20 dependency manifests supplied as text. Each item has a name, an ecosystem (PyPI, npm, Go, Maven, or crates.io), and the manifest content. No repository clone. No package install.

## `sourceFiles` (type: `array`):

Optional source file text, up to 2000 files, used only for the import-presence heuristic (does the code import a vulnerable package). Each item has a path and its text content.

## `minCvss` (type: `number`):

Drop advisories below this CVSS score from the report and the gate.

## `includeTransitive` (type: `boolean`):

Resolve and query transitive (indirect) packages when the manifest text carries that information (for example an npm lock file or a go.mod indirect marker). When off, only direct dependencies are resolved.

## `failOnCvssAtOrAbove` (type: `number`):

The run-level gate fails when any reported advisory's CVSS score is at or above this value.

## Actor input object example

```json
{
  "manifests": [
    {
      "name": "requirements.txt",
      "ecosystem": "PyPI",
      "content": "django==1.11.1\nsix==1.16.0\n"
    }
  ],
  "sourceFiles": [
    {
      "path": "app/settings.py",
      "content": "import django\n"
    }
  ],
  "minCvss": 0,
  "includeTransitive": true,
  "failOnCvssAtOrAbove": 9
}
```

# Actor output Schema

## `dataset` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("kingii98/ai-agent-stack-dependency-vulnerability-scanner").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("kingii98/ai-agent-stack-dependency-vulnerability-scanner").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 '{}' |
apify call kingii98/ai-agent-stack-dependency-vulnerability-scanner --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kingii98/ai-agent-stack-dependency-vulnerability-scanner"
        }
    }
}

```

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/QgGPNS1KDfvFoHdGz/builds/lOOrc40UH78PVlHjz/openapi.json
