praxis-sec 1.2.2 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -115
- package/ai-defense/cost-protection.md +6 -0
- package/ai-defense/llm-security-checklist.md +6 -0
- package/ai-defense/system-prompt-armor.md +7 -1
- package/checklists/launch-day.md +6 -7
- package/cli/agents/agent-telemetry-agent.js +2 -0
- package/cli/agents/api-fuzzer.js +2 -2
- package/cli/agents/git-history-scanner.js +14 -15
- package/cli/agents/html-reporter.js +2 -1
- package/cli/agents/memory-poisoning-agent.js +1 -5
- package/cli/commands/agent-fix.js +3 -1
- package/cli/commands/audit.js +1271 -1231
- package/cli/commands/autofix.js +32 -13
- package/cli/commands/baseline.js +2 -1
- package/cli/commands/benchmark.js +2 -1
- package/cli/commands/ci.js +7 -4
- package/cli/commands/env-audit.js +4 -2
- package/cli/commands/fix.js +2 -1
- package/cli/commands/mcp.js +52 -50
- package/cli/commands/remediate.js +2 -1
- package/cli/commands/rotate.js +2 -1
- package/cli/commands/scan-mcp.js +20 -9
- package/cli/commands/scan.js +15 -7
- package/cli/commands/score.js +2 -1
- package/cli/commands/vibe-check.js +2 -1
- package/cli/commands/watch.js +2 -1
- package/cli/core/glob.js +7 -5
- package/cli/core/paths.js +4 -4
- package/cli/core/web/jobs.js +2 -0
- package/cli/data/documented-secret-examples.json +14 -0
- package/cli/utils/entropy.js +19 -0
- package/cli/utils/hermes-tool-registry.js +11 -9
- package/configs/firebase/security-checklist.md +3 -3
- package/configs/supabase/security-checklist.md +19 -21
- package/docs/RELEASE-1.2.4.md +85 -0
- package/docs/RELEASING.md +51 -0
- package/docs/THIRD_PARTY_NOTICES.md +8 -0
- package/docs/THREAT_INTEL.md +4 -2
- package/docs/USAGE.md +97 -76
- package/package.json +82 -81
- package/snippets/README.md +6 -0
- package/snippets/auth/jwt-checklist.md +14 -13
package/docs/USAGE.md
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# Praxis — Complete Usage Guide
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
Security CLI for AI applications and codebases. Praxis runs 28 built-in scanners
|
|
4
|
+
in parallel batches, maps findings to security standards, and supports reviewed
|
|
5
|
+
LLM remediations with verification and an undo log. Requires Node.js 18 or newer.
|
|
6
|
+
|
|
7
|
+
For a local static audit, use `praxis scan . --no-ai --no-deps`. Default dependency
|
|
8
|
+
audits contact package services, and configured LLM providers may classify findings.
|
|
9
|
+
`--deep`, swarm analysis, LLM fixes, credential verification, feed updates, Git
|
|
10
|
+
clones, and live probes can also contact external services. `--no-ai` disables
|
|
11
|
+
classification; it does not disable those separately requested features.
|
|
8
12
|
|
|
9
13
|
---
|
|
10
14
|
|
|
@@ -42,7 +46,7 @@ offline; LLM features are optional.
|
|
|
42
46
|
|
|
43
47
|
```bash
|
|
44
48
|
# From source (this repo)
|
|
45
|
-
npm
|
|
49
|
+
npm ci
|
|
46
50
|
npm link # exposes `praxis` globally
|
|
47
51
|
|
|
48
52
|
# Or run directly without linking
|
|
@@ -93,6 +97,22 @@ Plus three top-level shortcuts: `praxis vibe`, `praxis score`, and `praxis` alon
|
|
|
93
97
|
|
|
94
98
|
Full audit: secrets + 28 agents + deps + score + remediation plan.
|
|
95
99
|
|
|
100
|
+
Local scan roots must be existing directories. Passing a file produces an error.
|
|
101
|
+
Use `scan changed` for a change-based scan; the editor's current-file command
|
|
102
|
+
scans its workspace and selects findings for that file.
|
|
103
|
+
|
|
104
|
+
Full-scan JSON contains:
|
|
105
|
+
|
|
106
|
+
- `scanComplete`: true only when required scan stages completed.
|
|
107
|
+
- `scanErrors`: errors from discovery, agents, dependency auditing, or requested legal analysis.
|
|
108
|
+
- `dependencyAudit`: `complete`, `skipped`, `not-applicable`, or `failed`.
|
|
109
|
+
|
|
110
|
+
Incomplete scans exit 1, do not refresh scan cache/history/playbook state, and
|
|
111
|
+
cannot verify a fix. Findings alone do not fail a normal full scan; use `scan ci`
|
|
112
|
+
for severity or score gates. Keep stderr and inspect completion before treating
|
|
113
|
+
JSON output or a high score as a successful assessment. Skipped checks provide
|
|
114
|
+
no assurance for that part of the project.
|
|
115
|
+
|
|
96
116
|
| Flag | Description |
|
|
97
117
|
| --- | --- |
|
|
98
118
|
| `--json` | Output results as JSON |
|
|
@@ -116,7 +136,7 @@ Full audit: secrets + 28 agents + deps + score + remediation plan.
|
|
|
116
136
|
| `--budget <cents>` | Max spend in cents for deep analysis (default 50) |
|
|
117
137
|
| `--verify` | Check if leaked secrets are still active |
|
|
118
138
|
| `--include-legal` | Also run the legal risk scan |
|
|
119
|
-
| `--agentic [iterations]` |
|
|
139
|
+
| `--agentic [iterations]` | Legacy annotation loop: adds review comments, then re-scans; does not apply the proposed remediation |
|
|
120
140
|
| `--agentic-target <score>` | Target security score for agentic loop |
|
|
121
141
|
| `--hermes-only` | Run only Hermes-relevant agents |
|
|
122
142
|
| `--fail-below <threshold>` | Exit 1 if score < threshold |
|
|
@@ -182,13 +202,13 @@ Credential health check: `.env` coverage, source cross-ref, git history.
|
|
|
182
202
|
|
|
183
203
|
### `scan redteam [path]` / `praxis redteam [target]`
|
|
184
204
|
|
|
185
|
-
|
|
205
|
+
`scan redteam <directory>` runs the static adversarial agent pack.
|
|
206
|
+
`praxis redteam <endpoint>` runs dynamic probes against an authorized live LLM
|
|
207
|
+
endpoint. These commands have different options; consult each command's `--help`.
|
|
208
|
+
The table below describes the static command.
|
|
186
209
|
|
|
187
210
|
| Flag | Description |
|
|
188
211
|
| --- | --- |
|
|
189
|
-
| `--endpoint <url>` | Target live LLM API endpoint for dynamic DAST probing |
|
|
190
|
-
| `--model <model>` | Target model identifier |
|
|
191
|
-
| `--probes <tags>` | Comma-separated probe categories (`jailbreak`, `injection`, `override`, `exfil`) |
|
|
192
212
|
| `--agents <list>` | Comma-separated list of static agents to run |
|
|
193
213
|
| `--json` | JSON output |
|
|
194
214
|
| `--sarif` | SARIF output |
|
|
@@ -197,13 +217,13 @@ Dynamic AI Red Teaming & DAST Prober: executes 80+ attack classes statically and
|
|
|
197
217
|
| `--no-deps` | Skip dependency audit |
|
|
198
218
|
| `--no-ai` | Skip AI classification |
|
|
199
219
|
| `--deep` | LLM-powered taint analysis with AST scope evaluation |
|
|
200
|
-
| `--swarm` |
|
|
220
|
+
| `--swarm` | Send selected source context and role instructions to a configured swarm provider; provider execution is separate from the 28 local scanners |
|
|
201
221
|
| `--think`, `--local`, `--model`, `--provider`, `--base-url`, `--budget` | LLM controls (same as `scan full`) |
|
|
202
222
|
| `-v, --verbose` | Verbose output |
|
|
203
223
|
|
|
204
224
|
### `scan standard [name] [path]`
|
|
205
225
|
|
|
206
|
-
Filter findings by AI-security standard.
|
|
226
|
+
Filter findings by AI-security standard.
|
|
207
227
|
|
|
208
228
|
| Flag | Description |
|
|
209
229
|
| --- | --- |
|
|
@@ -583,7 +603,7 @@ than silently passed off as checked.
|
|
|
583
603
|
Rule **ids are identifiers** (`AWS_ACCESS_KEY_ID`, not `AWS Access Key ID`), because
|
|
584
604
|
Semgrep suppressions (`# nosemgrep:`) and baselining key on them.
|
|
585
605
|
|
|
586
|
-
**Scope — what the export does not cover.**
|
|
606
|
+
**Scope — what the export does not cover.** The inventory identifies the rules that are static patterns. Three
|
|
587
607
|
layers have no Semgrep representation and are declared in the manifest rather than
|
|
588
608
|
approximated:
|
|
589
609
|
|
|
@@ -803,7 +823,7 @@ Praxis incorporates a pure ESM, zero-native-dependency AST & CST analysis engine
|
|
|
803
823
|
| --- | --- |
|
|
804
824
|
| `ANTHROPIC_API_KEY` | Claude (Opus / Sonnet / Haiku) |
|
|
805
825
|
| `OPENAI_API_KEY` | OpenAI (GPT-4 / GPT-4o / o1) |
|
|
806
|
-
| `
|
|
826
|
+
| `GOOGLE_API_KEY` / `GEMINI_API_KEY` | Gemini |
|
|
807
827
|
| `MOONSHOT_API_KEY` | Kimi |
|
|
808
828
|
| `OPENAI_BASE_URL` | Custom OpenAI-compatible endpoint (OpenRouter, Groq, DeepSeek, LM Studio, vLLM, ...) |
|
|
809
829
|
| `PRAXIS_LLM_MODEL` | Default model when no `--model` flag is given |
|
|
@@ -961,7 +981,7 @@ only ever emits a known class name.
|
|
|
961
981
|
prints a provenance line in its footer:
|
|
962
982
|
|
|
963
983
|
```
|
|
964
|
-
praxis
|
|
984
|
+
praxis <version> · node <runtime> · probes <version/count> · threatpack <version/count> · eaa <version> · files <count>
|
|
965
985
|
```
|
|
966
986
|
|
|
967
987
|
It records the tool version, the runtime, and the version of every vendored data asset
|
|
@@ -999,66 +1019,66 @@ between releases.
|
|
|
999
1019
|
|
|
1000
1020
|
## CI/CD integration
|
|
1001
1021
|
|
|
1002
|
-
### GitHub Action
|
|
1022
|
+
### GitHub Action
|
|
1003
1023
|
|
|
1004
|
-
The
|
|
1005
|
-
|
|
1024
|
+
The [Marketplace Action](https://github.com/marketplace/actions/praxis-security-scan)
|
|
1025
|
+
installs dependencies from its own lockfile and scans with the code selected by
|
|
1026
|
+
the Action ref. It does not depend on npm latest being synchronized with GitHub.
|
|
1006
1027
|
|
|
1007
1028
|
```yaml
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1029
|
+
name: Security
|
|
1030
|
+
on: [push, pull_request]
|
|
1031
|
+
permissions:
|
|
1032
|
+
contents: read
|
|
1033
|
+
security-events: write
|
|
1034
|
+
pull-requests: write
|
|
1035
|
+
jobs:
|
|
1036
|
+
praxis:
|
|
1037
|
+
runs-on: ubuntu-latest
|
|
1038
|
+
steps:
|
|
1039
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
1040
|
+
- uses: Ganron007/Praxis@v1.2.4
|
|
1041
|
+
with:
|
|
1042
|
+
path: '.'
|
|
1043
|
+
threshold: '80'
|
|
1044
|
+
deps: 'true'
|
|
1045
|
+
deep: 'false'
|
|
1046
|
+
sarif: 'true'
|
|
1047
|
+
comment: 'true'
|
|
1048
|
+
net-new: 'true'
|
|
1049
|
+
fail-on-new: 'high'
|
|
1050
|
+
always-fail-on: 'critical'
|
|
1023
1051
|
```
|
|
1024
1052
|
|
|
1025
|
-
|
|
1053
|
+
Use a release tag or commit for reproducibility; `v1` is a floating release-line
|
|
1054
|
+
tag. Inside this repository, `uses: ./` runs the checked-out source.
|
|
1026
1055
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
(`file:rule`) against the head scan. Only findings *introduced by the PR* can
|
|
1030
|
-
fail the build, at or above `fail-on-new`. Pre-existing debt never blocks.
|
|
1056
|
+
Outputs: `score`, `grade`, `findings`, `secrets`, `vulns`, `cves`,
|
|
1057
|
+
`sarif-file`, and `report-url`. See [action.yml](../action.yml) for all inputs.
|
|
1031
1058
|
|
|
1032
|
-
|
|
1059
|
+
On pull requests, `net-new: true` scans the base in a worktree and compares
|
|
1060
|
+
finding identities against the head scan. Introduced findings at or above
|
|
1061
|
+
`fail-on-new` fail the gate. `always-fail-on` also checks existing findings;
|
|
1062
|
+
scan and comparison failures fail the job. Other events use the normal gate.
|
|
1033
1063
|
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
- run: npm install -g praxis-sec@latest
|
|
1039
|
-
- run: praxis ci . --threshold 80 --sarif results.sarif --strict-intel
|
|
1040
|
-
- uses: github/codeql-action/upload-sarif@v4
|
|
1041
|
-
with: { sarif_file: results.sarif }
|
|
1042
|
-
```
|
|
1064
|
+
SARIF upload needs `security-events: write`; PR comments need
|
|
1065
|
+
`pull-requests: write`. Fork PR tokens and repository Code Scanning settings can
|
|
1066
|
+
restrict these integrations. Set `sarif: 'false'` or `comment: 'false'` when
|
|
1067
|
+
unavailable. The security gate operates independently of those integrations.
|
|
1043
1068
|
|
|
1044
|
-
|
|
1045
|
-
the scan itself succeeded.
|
|
1069
|
+
### Plain CLI in CI
|
|
1046
1070
|
|
|
1047
|
-
|
|
1071
|
+
After 1.2.4 is published to npm, install that exact version in your CI setup:
|
|
1048
1072
|
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
permissions:
|
|
1053
|
-
security-events: write
|
|
1054
|
-
steps:
|
|
1055
|
-
- uses: Ganron007/Praxis@v1
|
|
1056
|
-
with:
|
|
1057
|
-
net-new: 'true'
|
|
1058
|
-
fail-on-new: 'high'
|
|
1073
|
+
```bash
|
|
1074
|
+
npm install -g praxis-sec@1.2.4
|
|
1075
|
+
praxis scan ci . --fail-on high --sarif results.sarif
|
|
1059
1076
|
```
|
|
1060
1077
|
|
|
1061
|
-
|
|
1078
|
+
Keep the command's exit status. Store JSON as a regular artifact; Praxis JSON
|
|
1079
|
+
is not the GitLab SAST report schema. Upload SARIF to a compatible service with
|
|
1080
|
+
the necessary permissions. If using `--strict-intel`, refresh the feed first
|
|
1081
|
+
and ensure its configured sources completed successfully.
|
|
1062
1082
|
|
|
1063
1083
|
### Determinism gate
|
|
1064
1084
|
|
|
@@ -1070,10 +1090,10 @@ detection change cannot land unnoticed:
|
|
|
1070
1090
|
node scripts/check-determinism.mjs .
|
|
1071
1091
|
```
|
|
1072
1092
|
|
|
1073
|
-
CI runs this as its own job. A failure means
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1093
|
+
CI runs this as its own job. A failure means identical inputs produced different
|
|
1094
|
+
finding identities across runs. Investigate unstable discovery, ordering, caches,
|
|
1095
|
+
or external state. An intentional detection change between releases does not
|
|
1096
|
+
justify drift between two scans of the same checkout.
|
|
1077
1097
|
|
|
1078
1098
|
---
|
|
1079
1099
|
|
|
@@ -1168,7 +1188,7 @@ plugin-side wiring required.
|
|
|
1168
1188
|
| `rules import` says "YAML is an export format" | Import the sibling `praxis-rules.json`. Praxis has no YAML runtime dependency, so YAML is export-only. |
|
|
1169
1189
|
| `praxis web` refuses to start on a non-loopback host | Remote bind requires **both** `--allow-remote` and `--token` of at least 16 characters. This is deliberate. |
|
|
1170
1190
|
| `praxis web` won't load a project path | Projects are registered by the operator and addressed by **id**. The API intentionally does not accept client-supplied paths. |
|
|
1171
|
-
| Determinism gate fails in CI | Two scans of identical inputs disagreed on `file::rule`.
|
|
1191
|
+
| Determinism gate fails in CI | Two scans of identical inputs disagreed on `file::rule`. Investigate unstable discovery, caches, ordering, or external state; a detection change between commits does not justify drift in one checkout. |
|
|
1172
1192
|
|
|
1173
1193
|
---
|
|
1174
1194
|
|
|
@@ -1187,14 +1207,14 @@ npx praxis-sec mcp
|
|
|
1187
1207
|
|
|
1188
1208
|
### IDE integration
|
|
1189
1209
|
|
|
1190
|
-
|
|
1210
|
+
Illustrative stdio configuration (adapt the wrapper schema to your IDE; the package must be preinstalled):
|
|
1191
1211
|
|
|
1192
1212
|
```yaml
|
|
1193
1213
|
mcpServers:
|
|
1194
1214
|
- name: praxis
|
|
1195
1215
|
transport: stdio
|
|
1196
1216
|
command: npx
|
|
1197
|
-
args: ["praxis", "mcp"]
|
|
1217
|
+
args: ["--no-install", "praxis-sec", "mcp"]
|
|
1198
1218
|
```
|
|
1199
1219
|
|
|
1200
1220
|
In Docker (a container running praxis):
|
|
@@ -1204,7 +1224,7 @@ mcpServers:
|
|
|
1204
1224
|
- name: praxis
|
|
1205
1225
|
transport: stdio
|
|
1206
1226
|
command: docker
|
|
1207
|
-
args: ["exec", "-i", "
|
|
1227
|
+
args: ["exec", "-i", "your-container", "praxis", "mcp"]
|
|
1208
1228
|
```
|
|
1209
1229
|
|
|
1210
1230
|
### Available MCP tools
|
|
@@ -1212,17 +1232,18 @@ mcpServers:
|
|
|
1212
1232
|
| Tool | Input | Returns | Description |
|
|
1213
1233
|
|------|-------|---------|-------------|
|
|
1214
1234
|
| `scan_secrets` | `{ path }` | findings[] | Scan a file/directory for hardcoded secrets |
|
|
1215
|
-
| `scan_repo` | `{ path,
|
|
1216
|
-
| `analyze_file` | `{ path }` | findings
|
|
1217
|
-
| `get_findings` | `{ severity? }` | findings
|
|
1235
|
+
| `scan_repo` | `{ path, agents?, llm?, outputFile? }` | findings + score + completion | Built-in orchestrator scan; dependency audit skipped; optional LLM analysis |
|
|
1236
|
+
| `analyze_file` | `{ path }` | findings | Static secret analysis of a file |
|
|
1237
|
+
| `get_findings` | `{ reportPath, severity? }` | report + findings | Read an explicitly saved JSON report |
|
|
1218
1238
|
| `get_checklist` | — | checklist[] | Launch-day security checklist items |
|
|
1219
|
-
| `suppress_finding` | `{
|
|
1239
|
+
| `suppress_finding` | `{ file, line, reason }` | suppression status | Append a trailing comment to a reviewed source line; supported comment formats only |
|
|
1240
|
+
| `explain_and_fix` | `{ file, line, rule }` | explanation + preview | AST-aware explanation and proposed fix preview |
|
|
1220
1241
|
|
|
1221
1242
|
### Example MCP interaction
|
|
1222
1243
|
|
|
1223
1244
|
When connected, an IDE user can ask: *"Scan this file for AI vulnerabilities"*
|
|
1224
1245
|
and the LLM calls `scan_repo` — Praxis findings appear inline in the chat with
|
|
1225
|
-
file:line references. The `
|
|
1246
|
+
file:line references. The `llm` option requests provider-backed analysis. Require `scanComplete === true`, inspect errors, and disclose skipped checks. Suppression writes source and is not remediation.
|
|
1226
1247
|
|
|
1227
1248
|
---
|
|
1228
1249
|
|
package/package.json
CHANGED
|
@@ -1,81 +1,82 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "praxis-sec",
|
|
3
|
-
"version": "1.2.
|
|
4
|
-
"description": "Praxis
|
|
5
|
-
"main": "cli/index.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"praxis": "cli/bin/praxis.js"
|
|
8
|
-
},
|
|
9
|
-
"type": "module",
|
|
10
|
-
"scripts": {
|
|
11
|
-
"test": "node --test cli/__tests__/intel.test.js cli/__tests__/agents.test.js cli/__tests__/core.test.js cli/__tests__/standards.test.js cli/__tests__/model-file-scanner.test.js cli/__tests__/prompt-injection-prober.test.js cli/__tests__/ast-engine.test.js cli/__tests__/benchmark.test.js cli/__tests__/redteam.test.js cli/__tests__/html-reporter.test.js cli/__tests__/scan-fingerprint.test.js cli/__tests__/fix-ledger.test.js cli/__tests__/threatpack-probes.test.js cli/__tests__/score-history.test.js cli/__tests__/web-ui.test.js cli/__tests__/rule-portability.test.js cli/__tests__/git-remote.test.js cli/__tests__/release-reliability.test.js",
|
|
12
|
-
"test:determinism": "node scripts/check-determinism.mjs .",
|
|
13
|
-
"lint": "eslint cli/",
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"ora": "^8.0.1",
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
"
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "praxis-sec",
|
|
3
|
+
"version": "1.2.4",
|
|
4
|
+
"description": "Praxis security CLI: 28 built-in scanners for AI apps, agents, MCP and code; local static analysis, optional LLM-assisted fixes, verification, threat intelligence and CI gates.",
|
|
5
|
+
"main": "cli/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"praxis": "cli/bin/praxis.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "node --test cli/__tests__/intel.test.js cli/__tests__/agents.test.js cli/__tests__/core.test.js cli/__tests__/standards.test.js cli/__tests__/model-file-scanner.test.js cli/__tests__/prompt-injection-prober.test.js cli/__tests__/ast-engine.test.js cli/__tests__/benchmark.test.js cli/__tests__/redteam.test.js cli/__tests__/html-reporter.test.js cli/__tests__/scan-fingerprint.test.js cli/__tests__/fix-ledger.test.js cli/__tests__/threatpack-probes.test.js cli/__tests__/score-history.test.js cli/__tests__/web-ui.test.js cli/__tests__/rule-portability.test.js cli/__tests__/git-remote.test.js cli/__tests__/release-reliability.test.js",
|
|
12
|
+
"test:determinism": "node scripts/check-determinism.mjs .",
|
|
13
|
+
"lint": "eslint cli/",
|
|
14
|
+
"release:check": "node scripts/release-check.mjs",
|
|
15
|
+
"praxis": "node cli/bin/praxis.js",
|
|
16
|
+
"prepublishOnly": "node scripts/release-check.mjs --publishing"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"security",
|
|
20
|
+
"praxis",
|
|
21
|
+
"ai-security",
|
|
22
|
+
"agentic-security",
|
|
23
|
+
"llm-security",
|
|
24
|
+
"mcp-security",
|
|
25
|
+
"prompt-injection",
|
|
26
|
+
"supply-chain",
|
|
27
|
+
"secrets",
|
|
28
|
+
"scanner",
|
|
29
|
+
"sast",
|
|
30
|
+
"devsecops",
|
|
31
|
+
"red-team",
|
|
32
|
+
"vulnerability-scanner",
|
|
33
|
+
"sbom",
|
|
34
|
+
"abom",
|
|
35
|
+
"owasp-llm",
|
|
36
|
+
"agentic-remediation",
|
|
37
|
+
"threat-intel",
|
|
38
|
+
"cve",
|
|
39
|
+
"kev",
|
|
40
|
+
"epss",
|
|
41
|
+
"osv",
|
|
42
|
+
"ghsa",
|
|
43
|
+
"cli"
|
|
44
|
+
],
|
|
45
|
+
"author": "Praxis contributors",
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=18.0.0"
|
|
49
|
+
},
|
|
50
|
+
"files": [
|
|
51
|
+
"cli/",
|
|
52
|
+
"!cli/__tests__/",
|
|
53
|
+
"checklists/",
|
|
54
|
+
"configs/",
|
|
55
|
+
"snippets/",
|
|
56
|
+
"ai-defense/",
|
|
57
|
+
"docs/",
|
|
58
|
+
"!docs/internal/",
|
|
59
|
+
"assets/",
|
|
60
|
+
"scripts/check-determinism.mjs",
|
|
61
|
+
"README.md",
|
|
62
|
+
"LICENSE"
|
|
63
|
+
],
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"chalk": "^5.3.0",
|
|
66
|
+
"commander": "^12.1.0",
|
|
67
|
+
"ora": "^8.0.1",
|
|
68
|
+
"tinyglobby": "^0.2.17",
|
|
69
|
+
"write-file-atomic": "^5.0.1"
|
|
70
|
+
},
|
|
71
|
+
"devDependencies": {
|
|
72
|
+
"eslint": "^9.18.0"
|
|
73
|
+
},
|
|
74
|
+
"repository": {
|
|
75
|
+
"type": "git",
|
|
76
|
+
"url": "git+https://github.com/Ganron007/Praxis.git"
|
|
77
|
+
},
|
|
78
|
+
"homepage": "https://github.com/Ganron007/Praxis#readme",
|
|
79
|
+
"bugs": {
|
|
80
|
+
"url": "https://github.com/Ganron007/Praxis/issues"
|
|
81
|
+
}
|
|
82
|
+
}
|
package/snippets/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Security Snippets
|
|
2
2
|
|
|
3
|
+
> These examples are illustrative and require adaptation and tests. Prompt text,
|
|
4
|
+
> keyword filters, and in-memory limits do not enforce authorization or tenant
|
|
5
|
+
> isolation. Apply access controls, tool restrictions, and resource limits in code;
|
|
6
|
+
> test the deployed system against its actual threat model.
|
|
7
|
+
|
|
8
|
+
|
|
3
9
|
**Copy-paste code blocks for common security patterns.**
|
|
4
10
|
|
|
5
11
|
This folder contains drop-in code snippets for securing your application. Each snippet is heavily commented to explain *why* it works.
|
|
@@ -2,26 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
**Secure your JWT implementation before launch.**
|
|
4
4
|
|
|
5
|
-
Based on [JWT Best Practices
|
|
5
|
+
Based on [RFC 8725: JWT Best Current Practices](https://www.rfc-editor.org/rfc/rfc8725.html). Examples need application-specific key management and claim validation.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## Critical: Algorithm & Signing
|
|
10
10
|
|
|
11
|
-
### 1. [ ]
|
|
11
|
+
### 1. [ ] Use an explicitly allowed algorithm and appropriate keys
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
14
|
// BAD: HS256 with weak secret
|
|
15
15
|
jwt.sign(payload, 'my-secret', { algorithm: 'HS256' });
|
|
16
16
|
|
|
17
|
-
//
|
|
17
|
+
// Asymmetric option: RS256 with appropriate key management
|
|
18
18
|
jwt.sign(payload, privateKey, { algorithm: 'RS256' });
|
|
19
19
|
|
|
20
|
-
//
|
|
20
|
+
// Asymmetric option: ES256 with appropriate key management
|
|
21
21
|
jwt.sign(payload, privateKey, { algorithm: 'ES256' });
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
**Why:** HS256
|
|
24
|
+
**Why:** Weak HS256 keys permit offline guessing. HS256 can be appropriate with a strong random shared key; asymmetric keys separate signing authority from verification. Pin the expected algorithm and key type.
|
|
25
25
|
|
|
26
26
|
### 2. [ ] Algorithm specified in verification (not "auto")
|
|
27
27
|
|
|
@@ -35,8 +35,8 @@ jwt.verify(token, key, { algorithms: ['RS256'] });
|
|
|
35
35
|
|
|
36
36
|
### 3. [ ] Strong secret/key used
|
|
37
37
|
|
|
38
|
-
For HS256
|
|
39
|
-
- [ ] At least 256 bits (32
|
|
38
|
+
For HS256:
|
|
39
|
+
- [ ] At least 256 bits of random key material (32 bytes; character count is not entropy)
|
|
40
40
|
- [ ] Random, not dictionary words
|
|
41
41
|
- [ ] Stored in environment variable
|
|
42
42
|
|
|
@@ -59,15 +59,15 @@ jwt.sign(payload, key, { expiresIn: '15m' });
|
|
|
59
59
|
jwt.sign(payload, key, { expiresIn: '30d' }); // Too long!
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
**
|
|
62
|
+
**Illustrative lifetimes; choose these from the application risk and session requirements:**
|
|
63
63
|
- Access tokens: 15-60 minutes
|
|
64
64
|
- Refresh tokens: 7-30 days
|
|
65
65
|
- Remember me: 30-90 days (with re-auth for sensitive actions)
|
|
66
66
|
|
|
67
|
-
### 5. [ ] Expiration claim (exp)
|
|
67
|
+
### 5. [ ] Expiration claim (exp) is required and validated
|
|
68
68
|
|
|
69
69
|
```typescript
|
|
70
|
-
//
|
|
70
|
+
// Validate expiration, and separately reject tokens missing the required exp claim
|
|
71
71
|
jwt.verify(token, key, {
|
|
72
72
|
algorithms: ['RS256'],
|
|
73
73
|
clockTolerance: 30, // 30 seconds tolerance for clock skew
|
|
@@ -132,7 +132,7 @@ res.cookie('token', value, {
|
|
|
132
132
|
|
|
133
133
|
```typescript
|
|
134
134
|
res.cookie('token', value, {
|
|
135
|
-
sameSite: 'strict', //
|
|
135
|
+
sameSite: 'strict', // Helps reduce CSRF; verify the full request/CSRF design
|
|
136
136
|
// Or 'lax' if you need cross-site GET requests
|
|
137
137
|
});
|
|
138
138
|
```
|
|
@@ -184,10 +184,11 @@ JWTs can't be invalidated by default. Implement one of:
|
|
|
184
184
|
|
|
185
185
|
**Option B: Token blacklist/denylist**
|
|
186
186
|
```typescript
|
|
187
|
+
// Illustrative only; production revocation state must be shared and durable.
|
|
187
188
|
const revokedTokens = new Set();
|
|
188
189
|
|
|
189
190
|
function verifyToken(token) {
|
|
190
|
-
const payload = jwt.verify(token, key);
|
|
191
|
+
const payload = jwt.verify(token, key, { algorithms: ['RS256'] });
|
|
191
192
|
if (revokedTokens.has(payload.jti)) {
|
|
192
193
|
throw new Error('Token revoked');
|
|
193
194
|
}
|
|
@@ -261,7 +262,7 @@ const token = jwt.sign({
|
|
|
261
262
|
|
|
262
263
|
## Code Examples
|
|
263
264
|
|
|
264
|
-
###
|
|
265
|
+
### Illustrative JWT Service
|
|
265
266
|
|
|
266
267
|
```typescript
|
|
267
268
|
import jwt from 'jsonwebtoken';
|