You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Verifies GitHub HMAC signature before processing
57
57
- Handles two event types: `pull_request` and `workflow_run`
58
58
-**`pull_request` trigger (default):** on opened/synchronize/reopened, creates a Check Run in `queued` state, enqueues a BullMQ job, returns 200
59
59
-**`workflow_run` trigger:** on `pull_request` events, caches PR metadata in Redis (TTL 7 days) and creates a `skipped` Check Run; on `workflow_run completed` events matching the configured workflow name and conclusion, looks up cached PR metadata (falls back to GitHub API if cache is cold) then enqueues the scan
60
-
- Job ID is deduplicated by `{repo}#{pr}@{sha}`— duplicate webhook deliveries are no-ops (Redis lock + queue check)
60
+
- Job ID is deduplicated by `{repo}#{pr}@{sha}`- duplicate webhook deliveries are no-ops (Redis lock + queue check)
61
61
- Exported `app` and `processWebhookRequest` for use in tests
62
62
63
-
**`src/worker.js`— Job processor**
63
+
**`src/worker.js`- Job processor**
64
64
- BullMQ `Worker` consuming the `scans` queue with concurrency 5
65
65
-`processJob()` is exported for direct testing without Redis
66
66
- Per-job 10-minute timeout via `Promise.race`
67
-
- Graceful shutdown on SIGTERM/SIGINT — finishes in-flight jobs before exiting
67
+
- Graceful shutdown on SIGTERM/SIGINT - finishes in-flight jobs before exiting
68
68
- When `METRICS_ENABLED=true`: starts an HTTP metrics server on `METRICS_PORT` and polls BullMQ queue counts every 15 s
69
69
70
70
**Job lifecycle (inside `runScan`):**
71
71
1. Mark Check Run `in_progress`
72
72
2. Authenticate as installation via `src/auth.js` → short-lived token
4. Partial-clone both head and base SHAs with `--filter=blob:none`— fetches trees/commits only, no blobs yet (`src/fetcher.js` → `setupRepo`)
74
+
4. Partial-clone both head and base SHAs with `--filter=blob:none`- fetches trees/commits only, no blobs yet (`src/fetcher.js` → `setupRepo`)
75
75
5. Diff the two commits via tree objects to get changed file paths (`getChangedFiles`)
76
-
6. Sparse-checkout only the changed files — blobs fetched on demand (`checkoutFiles`)
76
+
6. Sparse-checkout only the changed files - blobs fetched on demand (`checkoutFiles`)
77
77
7. Load per-repo config via `src/config.js` → `loadScanConfig`
78
78
8. Run scanners in parallel via `src/dispatcher.js` → `dispatch()`
79
79
9. Convert findings to annotations via `src/reporter.js` → `buildAnnotations()`
@@ -83,11 +83,11 @@ Two separate Node.js processes:
83
83
13. Clean up workspace in `finally`
84
84
85
85
**Scanners (`src/adapters/`):**
86
-
-`semgrep.js`— runs `semgrep scan --config auto --json`; exit code 1 = findings found (not an error); maps ERROR→high, WARNING→medium, INFO→low
87
-
-`trufflehog.js`— runs `trufflehog filesystem --json --no-update`; exit code 183 = secrets found (not an error); batched at 200 files to stay under ARG_MAX; all findings are severity `high`
88
-
-`claude.js`— calls the Anthropic API to detect malicious intent; **disabled by default**, opt in per repo; skips binary files; caps files at 50 KB; batches at 100 KB per API call; errors are caught and logged without failing the scan. Supports two modes (configured per-repo in `config/layne.json`):
86
+
-`semgrep.js`- runs `semgrep scan --config auto --json`; exit code 1 = findings found (not an error); maps ERROR→high, WARNING→medium, INFO→low
87
+
-`trufflehog.js`- runs `trufflehog filesystem --json --no-update`; exit code 183 = secrets found (not an error); batched at 200 files to stay under ARG_MAX; all findings are severity `high`
88
+
-`claude.js`- calls the Anthropic API to detect malicious intent; **disabled by default**, opt in per repo; skips binary files; caps files at 50 KB; batches at 100 KB per API call; errors are caught and logged without failing the scan. Supports two modes (configured per-repo in `config/layne.json`):
89
89
-**Prompt mode** (default): single `messages.create` call with a system prompt; use `claude.prompt` to override
90
-
-**Skill mode**: uses the Anthropic [API Skills beta](https://platform.claude.com/docs/en/build-with-claude/skills-guide)— adds a `code_execution` tool + an uploaded skill to each batch call, enabling runtime decoding, registry lookups, and richer static analysis; set `claude.skill: { id, version }` to enable; handles `pause_turn` continuations automatically (up to 10 turns per batch)
90
+
-**Skill mode**: uses the Anthropic [API Skills beta](https://platform.claude.com/docs/en/build-with-claude/skills-guide)- adds a `code_execution` tool + an uploaded skill to each batch call, enabling runtime decoding, registry lookups, and richer static analysis; set `claude.skill: { id, version }` to enable; handles `pause_turn` continuations automatically (up to 10 turns per batch)
91
91
92
92
**Common finding shape:**
93
93
```js
@@ -118,32 +118,32 @@ Two separate Node.js processes:
118
118
See [docs/2-configuration.md](docs/2-configuration.md) for the full schema and examples.
119
119
120
120
Key points for code navigation:
121
-
- Read once per process startup —**restart both server and worker to pick up changes**
121
+
- Read once per process startup -**restart both server and worker to pick up changes**
122
122
- Loaded and merged by `src/config.js` → `loadScanConfig`
123
123
- Supports `$global` key for defaults inherited by all repos
-`trigger`: controls when scanning fires —`pull_request` (default, immediate) or `workflow_run` (deferred until a named CI workflow completes); global default → per-repo override
125
+
-`trigger`: controls when scanning fires -`pull_request` (default, immediate) or `workflow_run` (deferred until a named CI workflow completes); global default → per-repo override
126
126
-`notifications` and `labels`: per-repo notifier/key wins over global; per-repo absence = inherit global entirely
127
127
-`extraArgs` fully replaces the default (not extended)
128
128
-`config/layne.json` must be present in the Docker image (`COPY config/ ./config/`)
129
-
- Notifier contract: `async function notify({ findings, owner, repo, prNumber, toolConfig })`— must never throw
129
+
- Notifier contract: `async function notify({ findings, owner, repo, prNumber, toolConfig })`- must never throw
-`webhookUrl` values starting with `$` are resolved from `process.env` at runtime
132
132
- Label errors never affect the scan result or Check Run
133
133
134
134
## Metrics
135
135
136
136
-`src/metrics.js` exports real prom-client objects when `METRICS_ENABLED=true`, silent no-op stubs otherwise
137
-
- No `if (METRICS_ENABLED)` guards needed at call sites — stubs absorb all calls
137
+
- No `if (METRICS_ENABLED)` guards needed at call sites - stubs absorb all calls
138
138
- Worker: metrics HTTP server + BullMQ queue poller (15 s interval) started only when enabled
139
139
- Server: `GET /metrics` route registered only when enabled
140
140
-`monitoring/` directory has Prometheus scrape config and a pre-built Grafana dashboard
141
141
142
142
## Testing conventions
143
143
144
144
- Tests use Vitest with ESM (`"type": "module"` in package.json)
145
-
-`src/__tests__/setup.js` sets all required env vars before each test file; `ANTHROPIC_API_KEY` and `METRICS_ENABLED` are intentionally not set — adapters and metrics are mocked
146
-
- External dependencies (`@octokit/auth-app`, `@octokit/rest`, `bullmq`, `ioredis`, `@anthropic-ai/sdk`, `prom-client`) are always mocked — no live connections in tests
145
+
-`src/__tests__/setup.js` sets all required env vars before each test file; `ANTHROPIC_API_KEY` and `METRICS_ENABLED` are intentionally not set - adapters and metrics are mocked
146
+
- External dependencies (`@octokit/auth-app`, `@octokit/rest`, `bullmq`, `ioredis`, `@anthropic-ai/sdk`, `prom-client`) are always mocked - no live connections in tests
147
147
-`src/metrics.js` is mocked in worker and server tests with `vi.fn()` stubs; tested in isolation in `src/__tests__/metrics.test.js`
148
148
-`processJob` and `dispatch` are exported specifically for unit testing without live infrastructure
149
149
- Tests import modules with `await import(...)` after `vi.mock()` calls to handle ESM module caching
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -34,7 +34,7 @@ Thanks for your interest in contributing. This document covers the branch model,
34
34
35
35
## Changesets
36
36
37
-
Every PR that changes behaviour needs a changeset — a small file that describes what changed and what kind of version bump it warrants. The changeset check CI will fail if one is missing.
37
+
Every PR that changes behaviour needs a changeset - a small file that describes what changed and what kind of version bump it warrants. The changeset check CI will fail if one is missing.
38
38
39
39
**Add a changeset:**
40
40
```bash
@@ -53,7 +53,7 @@ This prompts you to pick a bump type and write a one-line description, then writ
53
53
54
54
**Skipping the changeset:**
55
55
56
-
For PRs that don't warrant a release entry — CI fixes, typos, documentation updates — add the `no-changeset` label to the PR. The check will be skipped.
56
+
For PRs that don't warrant a release entry - CI fixes, typos, documentation updates - add the `no-changeset` label to the PR. The check will be skipped.
57
57
58
58
---
59
59
@@ -62,7 +62,7 @@ For PRs that don't warrant a release entry — CI fixes, typos, documentation up
62
62
-**One thing per PR.** If you find yourself writing "and also..." in the description, split it.
63
63
-**Explain the why.** The diff shows what changed. The description should say why.
64
64
-**Every behaviour change needs a test.** If you're fixing a bug, the test should fail on the old code.
65
-
-**Security-sensitive areas get extra scrutiny**— webhook verification, auth, file path handling, scanner output parsing. Explain your threat model.
65
+
-**Security-sensitive areas get extra scrutiny**- webhook verification, auth, file path handling, scanner output parsing. Explain your threat model.
66
66
67
67
**Example description:**
68
68
@@ -98,8 +98,8 @@ All four must pass before a PR can be merged.
98
98
99
99
## Extending Layne
100
100
101
-
-**Adding a new scanner:** see [docs/6-extending.md — Adding a New Scanner](docs/6-extending.md#adding-a-new-scanner)
102
-
-**Adding a notification provider:** see [docs/6-extending.md — Adding a New Notifier](docs/6-extending.md#adding-a-new-notifier)
101
+
-**Adding a new scanner:** see [docs/6-extending.md - Adding a New Scanner](docs/6-extending.md#adding-a-new-scanner)
102
+
-**Adding a notification provider:** see [docs/6-extending.md - Adding a New Notifier](docs/6-extending.md#adding-a-new-notifier)
Copy file name to clipboardExpand all lines: README.md
+10-8Lines changed: 10 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -52,7 +52,7 @@ Layne ships with three built-in scanners. You can enable, disable, or configure
52
52
|[Trufflehog](https://github.com/trufflesecurity/trufflehog)| Secrets, API keys and credentials | Runs `trufflehog filesystem`; use `--only-verified` to reduce noise |
53
53
|[Claude](https://www.anthropic.com)| Bugs, vulnerabilities, backdoors, obfuscated payloads, supply-chain attacks (you can define a system prompt or a skill to use) | Disabled by default; opt in per repo; requires `ANTHROPIC_API_KEY`|
54
54
55
-
You can also add your own scanners. See [Extending Layne](docs/6-extending.md).
55
+
You can also add your own scanners. See [Extending Layne](website/docs/extending.md).
56
56
57
57
### Layne's Workflow
58
58
@@ -74,13 +74,15 @@ And you can configure Layne to send a notification via webhook to a Rocket.Chat
Then open [http://localhost:3000](http://localhost:3000).
84
+
85
+
The full documentation covers deployment, configuration, scanners, notifiers, PR comments, finding suppression, metrics, security architecture, and more.
Copy file name to clipboardExpand all lines: SECURITY.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@
4
4
5
5
If you believe you have found a security vulnerability in Layne, please do not open a public GitHub issue. Instead, report it through one of the following channels:
6
6
7
-
-**GitHub Security Advisory:**[Report a vulnerability](../../security/advisories/new)— opens a private advisory draft visible only to maintainers.
7
+
-**GitHub Security Advisory:**[Report a vulnerability](../../security/advisories/new)- opens a private advisory draft visible only to maintainers.
Please include as much detail as possible: a description of the vulnerability, steps to reproduce it, and the potential impact. If you have a proof-of-concept or suggested fix, we welcome that too.
@@ -19,7 +19,7 @@ We ask that you:
19
19
20
20
- Give us reasonable time to investigate and fix the issue before disclosing it publicly.
21
21
- Avoid accessing, modifying, or deleting data that does not belong to you.
22
-
- Act in good faith — we will do the same.
22
+
- Act in good faith - we will do the same.
23
23
24
24
Researchers who follow these guidelines will be credited in the fix unless they prefer to remain anonymous.
0 commit comments