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.
Files changed (42) hide show
  1. package/README.md +84 -115
  2. package/ai-defense/cost-protection.md +6 -0
  3. package/ai-defense/llm-security-checklist.md +6 -0
  4. package/ai-defense/system-prompt-armor.md +7 -1
  5. package/checklists/launch-day.md +6 -7
  6. package/cli/agents/agent-telemetry-agent.js +2 -0
  7. package/cli/agents/api-fuzzer.js +2 -2
  8. package/cli/agents/git-history-scanner.js +14 -15
  9. package/cli/agents/html-reporter.js +2 -1
  10. package/cli/agents/memory-poisoning-agent.js +1 -5
  11. package/cli/commands/agent-fix.js +3 -1
  12. package/cli/commands/audit.js +1271 -1231
  13. package/cli/commands/autofix.js +32 -13
  14. package/cli/commands/baseline.js +2 -1
  15. package/cli/commands/benchmark.js +2 -1
  16. package/cli/commands/ci.js +7 -4
  17. package/cli/commands/env-audit.js +4 -2
  18. package/cli/commands/fix.js +2 -1
  19. package/cli/commands/mcp.js +52 -50
  20. package/cli/commands/remediate.js +2 -1
  21. package/cli/commands/rotate.js +2 -1
  22. package/cli/commands/scan-mcp.js +20 -9
  23. package/cli/commands/scan.js +15 -7
  24. package/cli/commands/score.js +2 -1
  25. package/cli/commands/vibe-check.js +2 -1
  26. package/cli/commands/watch.js +2 -1
  27. package/cli/core/glob.js +7 -5
  28. package/cli/core/paths.js +4 -4
  29. package/cli/core/web/jobs.js +2 -0
  30. package/cli/data/documented-secret-examples.json +14 -0
  31. package/cli/utils/entropy.js +19 -0
  32. package/cli/utils/hermes-tool-registry.js +11 -9
  33. package/configs/firebase/security-checklist.md +3 -3
  34. package/configs/supabase/security-checklist.md +19 -21
  35. package/docs/RELEASE-1.2.4.md +85 -0
  36. package/docs/RELEASING.md +51 -0
  37. package/docs/THIRD_PARTY_NOTICES.md +8 -0
  38. package/docs/THREAT_INTEL.md +4 -2
  39. package/docs/USAGE.md +97 -76
  40. package/package.json +82 -81
  41. package/snippets/README.md +6 -0
  42. 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
- AI-native security CLI for AI-augmented codebases. Single binary, find→fix→verify
4
- loop on autopilot. 28 parallel security agents (24 built-in + ModelFileScanner +
5
- PromptInjectionProber + AgentTelemetryAgent + EndpointAgentAbuseAgent), multi-source threat intel, modular alignment with 8 AI-security
6
- standards, LLM-powered remediation with diff review and undo log. Works fully
7
- offline; LLM features are optional.
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 install
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]` | Agentic scan→fix→verify loop |
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
- Dynamic AI Red Teaming & DAST Prober: executes 80+ attack classes statically and probes live LLM endpoints / agent runtimes with jailbreak, prompt injection, and goal-hijacking payloads.
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` | AI swarm mode — 23 parallel agents via DeepSeek/Kimi |
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. **New in this release.**
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.** 411 of the rules are static patterns. Three
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
- | `GOOGLE_AI_API_KEY` | Gemini |
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 1.2.2 · node v24.14.1 · probes v1.1(23) · threatpack v1.1(3) · eaa v0.1.0 · files 215
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 (composite)
1022
+ ### GitHub Action
1003
1023
 
1004
- The repo ships an `action.yml` (composite action) that runs `praxis ci` and
1005
- uploads SARIF.
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
- - uses: ./
1009
- with:
1010
- path: .
1011
- threshold: '80'
1012
- deep: 'false'
1013
- deps: 'true'
1014
- sarif: 'true'
1015
- comment: 'true'
1016
- # PR regression gating — scan the base ref and fail only on NEW findings
1017
- net-new: 'true'
1018
- fail-on-new: 'high'
1019
- # severity floor a baseline can't suppress
1020
- always-fail-on: 'critical'
1021
- env:
1022
- ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
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
- Outputs: `score`, `grade`, `findings`, `secrets`, `vulns`, `cves`, `sarif-file`.
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
- **Net-new PR gating** (`net-new: true`, pull-request events only): the action
1028
- checks out the PR base into a worktree, scans it, and diffs finding identities
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
- ### Plain GitHub Actions
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
- ```yaml
1035
- permissions:
1036
- security-events: write # required for SARIF upload
1037
- steps:
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
- `security-events: write` is required — without it the upload fails with a 403 even though
1045
- the scan itself succeeded.
1069
+ ### Plain CLI in CI
1046
1070
 
1047
- ### Using the action from another repository
1071
+ After 1.2.4 is published to npm, install that exact version in your CI setup:
1048
1072
 
1049
- Once the action is listed on the GitHub Marketplace and a `v1` release tag exists:
1050
-
1051
- ```yaml
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
- Inside this repository `- uses: ./` works immediately and needs no publishing step.
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 the rule set, the probe corpus or the
1074
- threatpack changed behaviour — which is sometimes intended (a version bump should change
1075
- results), so the gate exists to make the change *deliberate* and visible in the diff
1076
- rather than silent.
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`. Usually a probe-corpus or threatpack change — check `git diff` on `cli/data/`. Expected when you intentionally change detection. |
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
- Cursor / Continue config (`.continue/config.yaml` or Cursor MCP settings):
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", "darkai-ops", "praxis", "mcp"]
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, deep? }` | findings[] + score | Full orchestrator scan (all 28 agents + intel) |
1216
- | `analyze_file` | `{ path }` | findings[] | Deep LLM analysis of a single file |
1217
- | `get_findings` | `{ severity? }` | findings[] | Retrieve cached findings (optionally filtered) |
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` | `{ id, reason }` | `{ ok }` | Suppress a finding (writes to `.praxis/ignores.json`) |
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 `deep` flag triggers LLM-powered taint analysis.
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.2",
4
- "description": "Praxis — From finding to fix, on autopilot. AI-native security CLI with 28 parallel agents covering AI / MCP / skill threats, OWASP LLM Top 10, multi-source supply-chain intel (OSV / GHSA / KEV / EPSS / NVD / Gitleaks + optional paid feeds), secret scanning, and an LLM-powered agentic remediation loop.",
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
- "praxis": "node cli/bin/praxis.js",
15
- "prepublishOnly": "npm test && npm run lint && npm run test:determinism"
16
- },
17
- "keywords": [
18
- "security",
19
- "praxis",
20
- "ai-security",
21
- "agentic-security",
22
- "llm-security",
23
- "mcp-security",
24
- "prompt-injection",
25
- "supply-chain",
26
- "secrets",
27
- "scanner",
28
- "sast",
29
- "devsecops",
30
- "red-team",
31
- "vulnerability-scanner",
32
- "sbom",
33
- "abom",
34
- "owasp-llm",
35
- "agentic-remediation",
36
- "threat-intel",
37
- "cve",
38
- "kev",
39
- "epss",
40
- "osv",
41
- "ghsa",
42
- "cli"
43
- ],
44
- "author": "Praxis contributors",
45
- "license": "MIT",
46
- "engines": {
47
- "node": ">=18.0.0"
48
- },
49
- "files": [
50
- "cli/",
51
- "!cli/__tests__/",
52
- "checklists/",
53
- "configs/",
54
- "snippets/",
55
- "ai-defense/",
56
- "docs/",
57
- "!docs/internal/",
58
- "assets/",
59
- "scripts/check-determinism.mjs",
60
- "README.md",
61
- "LICENSE"
62
- ],
63
- "dependencies": {
64
- "chalk": "^5.3.0",
65
- "commander": "^12.1.0",
66
- "fast-glob": "^3.3.3",
67
- "ora": "^8.0.1",
68
- "write-file-atomic": "^5.0.1"
69
- },
70
- "devDependencies": {
71
- "eslint": "^9.18.0"
72
- },
73
- "repository": {
74
- "type": "git",
75
- "url": "git+https://github.com/Ganron007/Praxis.git"
76
- },
77
- "homepage": "https://github.com/Ganron007/Praxis#readme",
78
- "bugs": {
79
- "url": "https://github.com/Ganron007/Praxis/issues"
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
+ }
@@ -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 2025](https://jwt.app/blog/jwt-best-practices/) and OWASP guidelines.
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. [ ] Using secure algorithm (not HS256 in production)
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
- // GOOD: RS256 (asymmetric) for production
17
+ // Asymmetric option: RS256 with appropriate key management
18
18
  jwt.sign(payload, privateKey, { algorithm: 'RS256' });
19
19
 
20
- // GOOD: ES256 (elliptic curve) - smaller keys, same security
20
+ // Asymmetric option: ES256 with appropriate key management
21
21
  jwt.sign(payload, privateKey, { algorithm: 'ES256' });
22
22
  ```
23
23
 
24
- **Why:** HS256 secrets can be brute-forced. RS256/ES256 use public/private key pairs.
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 (if you must use it):
39
- - [ ] At least 256 bits (32 characters)
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
- **Recommended lifetimes:**
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) always set
67
+ ### 5. [ ] Expiration claim (exp) is required and validated
68
68
 
69
69
  ```typescript
70
- // Always verify expiration
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', // Prevents CSRF
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
- ### Complete JWT Service
265
+ ### Illustrative JWT Service
265
266
 
266
267
  ```typescript
267
268
  import jwt from 'jsonwebtoken';