Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions vendor/nightvision-latest/_vendor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "nightvision",
"version": "latest",
"source": "https://claude.com/plugins/nightvision",
"vendored_at": "2026-03-21T12:00:13Z",
"license": "See individual files",
"skills_imported": ["api-discovery", "ci-cd-integration", "scan-configuration", "scan-triage"],
"quality_check": {
"passed": true,
"checked_at": "2026-03-21"
},
"content_hashes": {
"skills/api-discovery/SKILL.md": "sha256:d6ecbff2291b78387a34bbe9cd84aa3ec65f179f4bce013636e5c956e342a397",
"skills/ci-cd-integration/SKILL.md": "sha256:21b183cfb44b8be95d3c6a62c9e74ebbcd1fb236498fcdc48ba216143dffe823",
"skills/scan-configuration/SKILL.md": "sha256:30eb643b8986d8e454955c306ae2d5631938fb44b1a862f7e76673d48fee079d",
"skills/scan-triage/SKILL.md": "sha256:264e01deeeff918fae42ae3ee4c5f2d19029377ca8b9433776751c5c411b2334"
}
}
157 changes: 157 additions & 0 deletions vendor/nightvision-latest/skills/api-discovery/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
---
name: api-discovery
description: Guide for agents to help users extract OpenAPI specs from source code using NightVision API Discovery. Use when running swagger extract, identifying framework support, troubleshooting extraction, handling unresolved variables, comparing API specs, or understanding Code Traceback.
user-invocable: true
allowed-tools: Bash
---

# NightVision API Discovery

Use this skill when helping users generate OpenAPI specifications from their source code using `nightvision swagger extract`. API Discovery performs static analysis — no running application or compilation needed — and annotates the spec with source file paths and line numbers (Code Traceback) so that vulnerabilities found during DAST scans trace back to exact code locations.

## Agent workflow

When a user asks to extract or document their API:

1. **Check prerequisites** — verify the NightVision CLI is available (`nightvision --help`)
2. **Examine the repo** — identify the backend language and web framework to determine the `--lang` flag and whether the framework is supported (see [references/framework-support.md](references/framework-support.md))
3. **Run extraction** — execute `nightvision swagger extract` with the appropriate flags. On success, the CLI prints `"Swagger file extracted successfully."` and writes the spec to the output path (default: `openapi-spec.yml`)
4. **Review the output** — read the generated spec to check completeness. Handle unresolved variables if `nv.config` was created alongside the spec
5. **Compare coverage** — if the user has an existing spec, run `nightvision swagger diff` to show what was discovered vs. what was documented
6. **Upload to target** — attach the spec to a NightVision target for scanning

**Related skills:** Use `scan-configuration` for target/auth setup, `ci-cd-integration` for pipeline integration, `scan-triage` for interpreting scan results.

## Language flags

| Language | Flag | Frameworks |
|----------|------|------------|
| Python | `--lang python` | Django, DRF, Flask, Flask-RESTful, FastAPI |
| Java | `--lang java` | Spring Boot, JAX-RS/Jersey, Micronaut, Java EE/Jakarta EE |
| JavaScript | `--lang js` | Express, NestJS, Fastify |
| C# | `--lang dotnet` | ASP.NET Core (controllers, minimal APIs) |
| Go | `--lang go` | Gin, httprouter, net/http (experimental) |
| Ruby | `--lang ruby` | Rails, Grape |

See [references/framework-support.md](references/framework-support.md) for detailed component coverage per framework.

## Running extraction

```bash
# Basic extraction (output defaults to openapi-spec.yml)
nightvision swagger extract . --lang python

# Specify output file and format
nightvision swagger extract . --lang java -o api-spec.json --file-format json

# Extract and upload directly to a NightVision target
nightvision swagger extract . -t my-api -p my-project --lang python

# Extract without uploading
nightvision swagger extract . -o openapi-spec.yml --lang java --no-upload

# Scan multiple source directories
nightvision swagger extract ./service-a ./service-b --lang python

# Extend an existing spec (add discovered endpoints to it)
nightvision swagger extract . --lang python --extend existing-spec.yml

# Exclude directories from analysis
nightvision swagger extract . --lang python --exclude vendor,generated

# Include code snippets in the spec (useful for debugging)
nightvision swagger extract . --lang python --dump-code
```

### Extraction fallback for CI

Extraction can fail if language detection fails or the framework isn't supported. Always guard against this in pipelines:

```bash
nightvision swagger extract . -t $TARGET --lang java || true
if [ ! -e openapi-spec.yml ]; then cp backup-openapi-spec.yml openapi-spec.yml; fi
```

## Handling unresolved variables

When static analysis can't resolve a variable (e.g., an API prefix read from an environment variable), it appears as a literal placeholder in the spec. NightVision generates an `nv.config` file to fix this.

**Steps:**
1. Run extraction — if unresolved variables exist, `nv.config` is created alongside the spec (in the first source directory passed to the command)
2. Open `nv.config` — find the `replacements` object with `null` values
3. Replace `null` with the actual values (check the app's config files, environment vars, etc.)
4. Re-run extraction — the tool reads `nv.config` and substitutes the values. You can also use `-c` / `--config` to explicitly specify the config file path: `nightvision swagger extract . --lang python -c path/to/nv.config`

```json
// nv.config example
{
"replacements": {
"Microsoft.AspNetCore.Builder.WebApplication.Services...ApiPrefix": null
}
}
```

The agent should help the user find the actual value by searching their config files (`appsettings.json`, `.env`, `settings.py`, etc.) and updating `nv.config`.

## Comparing API specs

Use `swagger diff` to measure coverage or detect breaking changes:

```bash
# Summary diff (paths and schemas counts)
nightvision swagger diff original-spec.yml discovered-spec.yml

# Show only path-level changes (endpoints added/removed/modified)
nightvision swagger diff original-spec.yml discovered-spec.yml --paths

# Show only schema changes
nightvision swagger diff original-spec.yml discovered-spec.yml --schemas

# Show the full diff (paths and schemas together, with details)
nightvision swagger diff original-spec.yml discovered-spec.yml --full-diff

# Save diff output to file
nightvision swagger diff original-spec.yml discovered-spec.yml -o diff-report.txt
```

Common use cases:
- **Coverage analysis** — compare a hand-written spec against the discovered one to find undocumented shadow APIs
- **PR checks** — diff specs from the base branch vs. PR branch to detect breaking API changes
- **Audit** — verify that all endpoints are documented

## Detecting existing specs

Search the codebase for existing OpenAPI/Swagger files. The `detect` command takes no positional arguments — use `-p` to specify the root folder:

```bash
# Detect project roots in the current directory
nightvision swagger detect

# Detect in a specific directory
nightvision swagger detect -p ./path/to/code

# Save detection results as JSON
nightvision swagger detect -o detection-results.json
```

## Code Traceback

The generated spec includes `x-source` annotations on each endpoint with the file path and line number where the route is declared. When this spec is used for DAST scanning:

- Vulnerabilities found by NightVision link directly to the source code
- GitHub Security Alerts, Azure Boards work items, and Jenkins Warnings show the exact file and line
- Developers see where to fix, not just what to fix

This is why using NightVision-generated specs (vs. hand-written ones) significantly improves the triage experience.

## Troubleshooting

| Issue | Cause | Fix |
|-------|-------|-----|
| No endpoints found | Wrong `--lang` flag, or unsupported framework | Verify the framework is supported, check `--lang` value |
| Unresolved variables in paths | Config values read from env vars without defaults | Fill in `nv.config` replacements and re-run |
| Incomplete routes | Custom routing, non-standard framework usage | NightVision relies on standard framework patterns; custom routing may not be detected |
| Extraction fails entirely | Syntax errors in source, missing files | Use `--diagnostics` to get language-level error details |
| Spec missing sub-routes | Code in subdirectories not scanned | Pass multiple paths: `nightvision swagger extract ./src ./lib` |

For unsupported frameworks or components, contact support@nightvision.net.
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Framework Support Matrix

Detailed component coverage per language and framework for NightVision API Discovery.

## Python (`--lang python`)

### Django
- `django.urls`: `path`, `re_path`, `include`
- `django.views.generic.View` — class-based views
- `django.http.QueryDict`, `HttpRequest`

### Django REST Framework
- Generic views: `CreateAPIView`, `ListAPIView`, `RetrieveAPIView`, `DestroyAPIView`, `ListCreateAPIView`, `RetrieveUpdateAPIView`, `RetrieveUpdateDestroyAPIView`
- `APIView`, `GenericAPIView`
- Mixins: `CreateModelMixin`, `DestroyModelMixin`, `ListModelMixin`, `RetrieveModelMixin`, `UpdateModelMixin`
- `ModelViewSet`, `ReadOnlyModelViewSet`
- `Serializer`, `Field` classes
- `ExtendedDefaultRouter`, `ExtendedSimpleRouter`

### Flask
- `flask.Flask`, `flask.Blueprint`
- `flask.request` (args, cookies, files, form, headers)
- `flask.views.View`, `MethodView`

### Flask-RESTful
- `flask_restful.Api`, `flask_restful.Resource`

### FastAPI
- `fastapi.FastAPI`, `fastapi.APIRouter`
- `pydantic.BaseModel` for request/response models
- `fastapi.Response`, `HTTPException`
- `fastapi.Header`, `fastapi.Cookie`
- `fastapi.status`

## Java (`--lang java`)

### Spring Boot
- `@RestController`, `@Controller`
- `@GetMapping`, `@PostMapping`, `@PutMapping`, `@DeleteMapping`, `@PatchMapping`
- `@RequestMapping`, `@PathVariable`, `@ResponseBody`
- `@RepositoryRestResource` — auto-generated CRUD routes
- `@RestResource`

### JAX-RS / Jersey
- `@GET`, `@POST`, `@PUT`, `@DELETE`, `@HEAD`, `@OPTIONS`
- `@Path`, `@PathParam`, `@QueryParam`, `@FormParam`
- `@ApplicationPath`
- `MediaType`, `@Context`

### Micronaut
- `@Controller`
- `@Get`, `@Post`, `@Put`, `@Delete`, `@Patch`, `@Head`, `@Options`, `@Trace`
- `@PathVariable`, `@QueryValue`, `@Header`, `@CookieValue`, `@Body`, `@Part`
- `@Consumes`, `@Produces`
- `@Secured`, `SecurityRule`

### Java EE / Jakarta EE
- `HttpServletRequest`, `HttpServletResponse`
- `@DenyAll`, `@PermitAll`, `@RolesAllowed`

## JavaScript (`--lang js`)

### Express
- `express.Router()`, `app.use()`, `app.route()`
- HTTP verbs: `get`, `post`, `put`, `patch`, `delete`, `all`
- `req.params`, `req.body`, `req.query`
- `app.listen()`

### NestJS
- `@nestjs/common`: `Controller`, `Module`, `Injectable`
- `@nestjs/core`: `DynamicModule`, `NestFactory.create`, `RouterModule.register`
- `setGlobalPrefix`, `listen`

### Fastify
- `@fastify.autoload`
- HTTP verbs: `get`, `head`, `post`, `put`, `delete`, `options`, `patch`
- `fastify.route`, `fastify.register`
- `fastify.listen`, `fastify.ready`

## C# (`--lang dotnet`)

### ASP.NET Core
- **Controllers**: `ApiController`, `Controller`, `ControllerBase`
- **HTTP attributes**: `HttpGet`, `HttpPost`, `HttpPut`, `HttpDelete`, `HttpPatch`, `HttpHead`, `HttpOptions`
- **Parameter binding**: `FromBody`, `FromHeader`, `FromQuery`, `FromRoute`
- **Minimal APIs**: `IEndpointRouteBuilder`, `MapControllers()`, `MapGroup()`
- **Auth**: `AddJwtBearer`, `AddCookie`, `AddOAuth`, `AddOpenIdConnect`, `Authorize`, `AllowAnonymous`
- **Config**: `WebApplication`, `WebApplicationBuilder`, `UseEndpoints()`, `UsePathBase()`

## Go (`--lang go`) — Experimental

### Gin
- `gin.New()`, `gin.Default()`
- Route groups: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, `OPTIONS`, `ANY`, `Handle`, `Group`
- Binding: `BindJSON`, `ShouldBind`, `ShouldBindJSON`
- Parameters: `Query`, `Param`, `PostForm`, `Cookie`

### httprouter
- `httprouter.New()`
- `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `OPTIONS`

### net/http (standard library)
- `http.Request`: `FormValue`, `PostFormValue`, `Cookie`
- `http.ResponseWriter`
- `http.Server`, `ListenAndServe`

## Ruby (`--lang ruby`)

### Rails
- `ActionController::Base`
- Routing: `resources`, `resource`, `namespace`, `member`, `collection`
- HTTP verbs: `get`, `post`, `put`, `patch`, `delete`
- Strong parameters via `ActionController::Parameters`

### Grape
- `Grape::DSL::Routing`
- `resource`, `namespace`, `get`, `post`, `put`, `patch`, `delete`
- `mount`, `version`, `params`, `prefix`
Loading
Loading