Skip to content

feat: experimental traffic analysis#2848

Open
sobanieca-redocly wants to merge 23 commits into
mainfrom
feat/traffic-analysis
Open

feat: experimental traffic analysis#2848
sobanieca-redocly wants to merge 23 commits into
mainfrom
feat/traffic-analysis

Conversation

@sobanieca-redocly

@sobanieca-redocly sobanieca-redocly commented Jun 3, 2026

Copy link
Copy Markdown

What/Why/How?

Added two new (experimental) commands - drift and proxy for collecting traffic data and validating it against provided OpenAPI definition.

Reference

Testing

Screenshots (optional)

Check yourself

  • This PR follows the contributing guide
  • All new/updated code is covered by tests
  • Core code changed? - Tested with other Redocly products (internal contributions only)
  • New package installed? - Tested in different environments (browser/node)
  • Documentation update has been considered

Security

  • The security impact of the change has been considered
  • Code follows company security practices and guidelines

Note

Medium Risk
Large new surface area including security/CORS/cookie heuristics and a live forwarding proxy; behavior is experimental but misconfiguration could leak or mishandle captured credentials in HAR files.

Overview
Adds experimental drift and proxy CLI commands (minor @redocly/cli changesets) to compare real HTTP traffic against OpenAPI descriptions.

drift ingests traffic from files or folders (HAR, Kong, Nginx/Apache JSON, NDJSON, auto-detect, plus pluggable traffic parsers), bundles and indexes OpenAPI via existing @redocly/openapi-core, matches each exchange to operations (--match-mode or --server), and runs builtin/plugin rules. Findings roll up in memory and export as pretty, json, csv, or sarif; exit code 1 on error-level drift. Builtin rules cover undocumented endpoints, schema/parameter consistency (AJV with readOnly/writeOnly handling), security-baseline (documented security vs traffic), and opt-in OWASP API heuristics.

proxy runs a local reverse proxy (undici upstream), appends exchanges to a HAR on each request, and optionally reuses the same ValidationSession for live findings plus a shutdown report. Captured HARs are intended for replay with drift.

CLI wiring lazy-loads both commands; lint config output skips mixing in when format is csv or sarif. E2E tests and READMEs document flags and PoC limits (in-memory JSON arrays, full HAR rewrite on proxy).

Reviewed by Cursor Bugbot for commit fe177c4. Bugbot is set up for automated code reviews on this repo. Configure here.

@changeset-bot

changeset-bot Bot commented Jun 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 59a5bff

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@redocly/cli Minor
@redocly/openapi-core Minor
@redocly/respect-core Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@sobanieca-redocly sobanieca-redocly changed the title feat: traffic analysis poc feat: experimental traffic analysis Jun 8, 2026
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 81.39% (🎯 81%) 7406 / 9099
🔵 Statements 80.75% (🎯 80%) 7699 / 9534
🔵 Functions 84.58% (🎯 84%) 1476 / 1745
🔵 Branches 73.1% (🎯 73%) 5013 / 6857
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/cli/src/types.ts 100% 100% 100% 100%
packages/cli/src/commands/lint.ts 94.54% 86.04% 100% 94.54% 91-93, 158, 192
Generated in workflow #10428 for commit 59a5bff by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Performance Benchmark (Lower is Faster)

CLI Version Bundle Lint Check Config
cli-latest ▓ 1.00x (Fastest) ▓ 1.00x (Fastest) ▓ 1.00x ± 0.01
cli-next ▓ 1.01x ± 0.01 ▓ 1.01x ± 0.01 ▓ 1.00x (Fastest)

@sobanieca-redocly

Copy link
Copy Markdown
Author

@cursor review

Comment thread packages/cli/src/commands/proxy/server.ts Outdated
Comment thread packages/cli/src/commands/drift/utils/http.ts
Comment thread packages/cli/src/commands/proxy/server.ts
Comment thread packages/cli/src/commands/drift/engine/runner.ts
Comment thread packages/cli/src/commands/drift/rules/builtins/security.ts
@sobanieca-redocly

Copy link
Copy Markdown
Author

@cursor review

Comment thread packages/cli/src/commands/proxy/server.ts
Comment thread packages/cli/src/commands/proxy/server.ts Outdated
Comment thread packages/cli/src/commands/proxy/index.ts Outdated
Comment thread packages/cli/src/commands/drift/openapi/matcher.ts Outdated
@sobanieca-redocly

Copy link
Copy Markdown
Author

@cursor review

Comment thread packages/cli/src/commands/proxy/server.ts Outdated
Comment thread packages/cli/src/commands/drift/rules/builtins/schema.ts
Comment thread packages/cli/src/commands/drift/rules/builtins/schema.ts
Comment thread packages/cli/src/commands/drift/openapi/loader.ts
@sobanieca-redocly

Copy link
Copy Markdown
Author

@cursor review

Comment thread packages/cli/src/commands/drift/index.ts
Comment thread packages/cli/src/commands/drift/log-formats/ndjson.ts Outdated
Comment thread packages/cli/src/commands/drift/engine/schema-validator.ts
Comment thread packages/cli/src/commands/drift/openapi/generator.ts Outdated
@sobanieca-redocly

Copy link
Copy Markdown
Author

@cursor review

Comment thread packages/cli/src/commands/drift/log-formats/helpers.ts Outdated
@sobanieca-redocly

Copy link
Copy Markdown
Author

@cursor review

Comment thread packages/cli/src/commands/proxy/index.ts
Comment thread packages/cli/src/commands/drift/log-formats/har.ts
Comment thread packages/cli/src/commands/drift/rules/builtins/schema.ts
@sobanieca-redocly

Copy link
Copy Markdown
Author

@cursor review

Comment thread packages/cli/src/commands/drift/openapi/matcher.ts

- Starts a reverse proxy that forwards every request to an upstream `--target`
and records each request/response exchange into a HAR file.
- The HAR file is written incrementally (after each exchange) and flushed on

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned during demo - do we want to keep this behavior for the first release? (this means proxy will be usable only for short lived processes like e2e tests etc.). In future we can introduce chunking (and give drift command option to read whole folder of traffic files). Eventually we can switch to ndjson format and append line by line.

- `--api <path>`: OpenAPI file or folder to validate against. Omit to generate.
- `--traffic-format <auto|har|kong|nginx-json|apache-json|ndjson>` (default: `auto`)
- `--format <pretty|json|csv|sarif>` (default: `pretty`)
- `--match-mode <strict-host|basepath>` (default: `strict-host`): how requests are located

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we add server option which seems more flexible maybe we should get rid of match-mode param at all? That way we will always use strict-host so we validate against OAD, but user may also override server.

Mutually exclusive with `--match-mode`: use `--match-mode` when the traffic URLs align
with the description `servers`, use `--server` to declare the actual server when they
do not.

@sobanieca-redocly sobanieca-redocly Jun 12, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As presented during demo - shall we include ignore option for the first release? To avoid messages about unknown headers like x-caddy-authtoken etc.

Comment thread vitest.config.ts
'packages/**/__tests__/**/*',
'packages/cli/src/index.ts',
'packages/cli/src/utils/assert-node-version.ts',
'packages/cli/src/commands/drift/**',

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it fine if we ignore coverage for experimental commands? I would expect that source code there may change significantly over time after getting feedback on usage....

- missing required parameters/body,
- request/response schema mismatches,
- baseline security issues (opt-in OWASP API risk heuristics).
- When no spec is provided, infers an OpenAPI 3.1 description from the traffic.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to improve OAD generation option for the first release? Maybe we should explicitly require path to folder where OAD will be saved and implement more sophisticated schemas generation?

On the other hand - we may wait for feedback and do this in next iteration.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed in Slack - we will remove OAD generation in this PR.

maxFindings?: number;
}

const ANSI = {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have colorette as a dep in this repo, let's use it

Comment thread packages/cli/src/index.ts Outdated
Comment on lines +15 to +16
import { handleDrift, type DriftArgv } from './commands/drift/index.js';
import type { FindingSeverity, MatchMode, TrafficFormat } from './commands/drift/types/index.js';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use dynamic import

Comment thread packages/cli/src/index.ts
yargs
.env('REDOCLY_CLI_DRIFT')
.positional('traffic', {
describe: 'Path to a traffic log file or folder (HAR, Kong, Nginx/Apache JSON, NDJSON).',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it support those other formats?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it does 👍

@sobanieca-redocly

Copy link
Copy Markdown
Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 0e8c763. Configure here.

@sobanieca-redocly sobanieca-redocly marked this pull request as ready for review June 17, 2026 12:58
@sobanieca-redocly sobanieca-redocly requested review from a team as code owners June 17, 2026 12:58
Comment thread packages/cli/src/commands/drift/README.md Outdated
Comment thread packages/cli/src/commands/drift/README.md Outdated
Comment thread packages/cli/src/commands/drift/README.md Outdated
Comment thread packages/cli/src/commands/drift/README.md Outdated
Comment thread packages/cli/src/commands/drift/README.md Outdated
Comment thread packages/cli/src/commands/proxy/README.md Outdated
Comment thread packages/cli/src/commands/proxy/README.md Outdated
Comment thread packages/cli/src/commands/proxy/README.md Outdated
Comment thread packages/cli/src/commands/proxy/README.md Outdated
Co-authored-by: Jacek Łękawa <164185257+JLekawa@users.noreply.github.com>
Comment thread packages/cli/src/commands/drift/README.md Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 59a5bff. Configure here.


export function normalizeServerPrefix(server: string | undefined): string | undefined {
const trimmed = server?.replace(/\/+$/, '');
return trimmed || undefined;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Root path server override dropped

Medium Severity

Passing --server / as a path-only prefix is treated as no server override because trailing slashes are stripped and an empty remainder becomes undefined. Drift then falls back to description servers matching instead of path-only filtering, which breaks the documented path-prefix mode for the site root.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 59a5bff. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants