@agenttrail/guardrails 0.2.4 → 0.2.6

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.
@@ -360,7 +360,7 @@ declare function mentions(text: string): Fixture[];
360
360
  * Pinned to `package.json`'s `version` by `__tests__/stamp.test.ts` — this is a copy
361
361
  * of that value, not an independent one, and the test is what makes the copy safe.
362
362
  */
363
- declare const CATALOG_VERSION = "0.2.4";
363
+ declare const CATALOG_VERSION = "0.2.6";
364
364
  /**
365
365
  * When the guardrails in this catalog reached their current state, as an ISO-8601
366
366
  * instant. The question it answers is not "when did this reach a registry" but "how
@@ -370,7 +370,7 @@ declare const CATALOG_VERSION = "0.2.4";
370
370
  * the guard handles a missing date, and a wrong date that looks right is worse than
371
371
  * a missing one.
372
372
  */
373
- declare const CATALOG_PUBLISHED_AT = "2026-10-16T16:15:37Z";
373
+ declare const CATALOG_PUBLISHED_AT = "2026-10-22T16:18:01Z";
374
374
 
375
375
  /**
376
376
  * The corpus itself — guardrails only, and **deliberately free of zod**.
@@ -360,7 +360,7 @@ declare function mentions(text: string): Fixture[];
360
360
  * Pinned to `package.json`'s `version` by `__tests__/stamp.test.ts` — this is a copy
361
361
  * of that value, not an independent one, and the test is what makes the copy safe.
362
362
  */
363
- declare const CATALOG_VERSION = "0.2.4";
363
+ declare const CATALOG_VERSION = "0.2.6";
364
364
  /**
365
365
  * When the guardrails in this catalog reached their current state, as an ISO-8601
366
366
  * instant. The question it answers is not "when did this reach a registry" but "how
@@ -370,7 +370,7 @@ declare const CATALOG_VERSION = "0.2.4";
370
370
  * the guard handles a missing date, and a wrong date that looks right is worse than
371
371
  * a missing one.
372
372
  */
373
- declare const CATALOG_PUBLISHED_AT = "2026-10-16T16:15:37Z";
373
+ declare const CATALOG_PUBLISHED_AT = "2026-10-22T16:18:01Z";
374
374
 
375
375
  /**
376
376
  * The corpus itself — guardrails only, and **deliberately free of zod**.
@@ -23,7 +23,7 @@ import {
23
23
  mentions,
24
24
  pwsh,
25
25
  rulesForPack
26
- } from "./chunk-6YROGDEH.js";
26
+ } from "./chunk-XIRL7M4H.js";
27
27
  import {
28
28
  OWASP_AGENTIC,
29
29
  OWASP_IDS,
package/dist/index.cjs CHANGED
@@ -2674,6 +2674,8 @@ var requireAuthOnPiiEndpoints = {
2674
2674
  };
2675
2675
 
2676
2676
  // src/packs/secret-exposure/se-credential-file.ts
2677
+ var NOT_VENDORED = "*(@(!(node_modules|dist|vendor)|@(node_modules|dist|vendor)[^/]*)/)";
2678
+ var PROD_CONFIG = "@(yml|yaml|json|toml|env|ini|conf|properties|tf|tfvars)";
2677
2679
  var seCredentialFile = {
2678
2680
  id: "se.credential-file",
2679
2681
  category: "secret-exposure",
@@ -2681,7 +2683,7 @@ var seCredentialFile = {
2681
2683
  defaultAction: "require_approval",
2682
2684
  owasp: ["ASI02", "ASI03", "LLM02"],
2683
2685
  title: "Opening a file that holds credentials",
2684
- description: "Holds a file tool opening a path where credentials live \u2014 an SSH private key, an AWS credentials file, a PEM/P12/PFX/JKS keystore, `.npmrc` or `.pypirc` (which hold registry tokens), a Docker config, or a kubeconfig. Public keys are excluded (`*.pub`). It matches the PATH ONLY: it cannot tell whether the file actually holds a secret, so a `.pem` that is a public certificate is held too, and a credential in a file named something else is missed entirely. `.env` files are covered separately by block-env-file-read.",
2686
+ description: "Holds a file tool opening a path where credentials live \u2014 an SSH private key, an AWS credentials file, a PEM/P12/PFX/JKS keystore, `.npmrc` or `.pypirc` (which hold registry tokens), a Docker config, or a kubeconfig. Public keys are excluded (`*.pub`). It matches the PATH ONLY: it cannot tell whether the file actually holds a secret, so a `.pem` that is a public certificate is held too, and a credential in a file named something else is missed entirely. `.env` files are covered separately by block-env-file-read. It also holds READING \u2014 the `Read` and `Grep` tools, nothing else \u2014 of files whose edit another guardrail already holds and which commonly carry a secret: `/etc/shadow`, `/etc/gshadow`, their `-` backups, `/etc/sudoers` and `/etc/sudoers.d/`; SSH host private keys (`/etc/ssh/ssh_host_*_key` and the legacy `/etc/ssh/ssh_host_key`); `/etc/ssl/private/` and `/etc/pki/tls/private/`; Kubernetes admin configs (`/etc/kubernetes/*.conf`) and private keys (`/etc/kubernetes/pki/**/*.key`); the k3s kubeconfig (`/etc/rancher/k3s/k3s.yaml`); a repository's `.git/config`, where a remote URL or extra header can carry a token; agent configuration that often holds API keys \u2014 `.mcp.json`, `.claude/settings.local.json`, `.claude.json`, `.cursor/mcp.json` and `.codex/config.toml`; and production configuration: a `.yml`, `.yaml`, `.json`, `.toml`, `.env`, `.ini`, `.conf`, `.properties`, `.tf` or `.tfvars` file named `*.prod.*`, `prod.*`, `*.production.*` or `production.*`, or under a `prod/` or `production/` folder, unless any folder in the path, an absolute path's leading folders included, is named exactly `node_modules`, `dist` or `vendor` (so `/srv/vendor/app/config/database.prod.yml` is not held). A Grep anywhere under `/etc`, including a search of the folder itself or with a wildcard, is held too; a Read of an `/etc` file not named here is not. Editing those files is held by the guardrail that owns the path, not by this one. NOT held on read by this guardrail: a shell command such as `cat`, on any agent (Codex has no read tool, so its reads are always shell commands); a file tool other than Read and Grep, such as Claude Code's Glob or another Cursor tool, which the guardrail that owns the path still holds under its own title, except on `.claude.json`, which no other guardrail names; `.claude/settings.json`, at project or user level; other secrets under `/etc` such as Kerberos keytabs and VPN or Wi-Fi connection files, which are held on Grep only; a Grep of a production folder with no file pattern, or with a pattern whose extension is a wildcard; production files of other types, such as `.key`, `.tfstate`, `.hcl`, `.cfg`, `.xml`, `.config` or Angular's `environment.prod.ts`; and production code or prose, such as `webpack.prod.js` or a runbook in `docs/production/`.",
2685
2687
  match: {
2686
2688
  any_of: [
2687
2689
  { kind: "execute_tool", file_glob: "**/.ssh/id_*" },
@@ -2693,7 +2695,63 @@ var seCredentialFile = {
2693
2695
  { kind: "execute_tool", file_glob: "**/.npmrc" },
2694
2696
  { kind: "execute_tool", file_glob: "**/.pypirc" },
2695
2697
  { kind: "execute_tool", file_glob: "**/.docker/config.json" },
2696
- { kind: "execute_tool", file_glob: "**/.kube/config" }
2698
+ { kind: "execute_tool", file_glob: "**/.kube/config" },
2699
+ // Read only (see the header): system account and privilege files, host and TLS keys,
2700
+ // cluster admin configs and keys.
2701
+ {
2702
+ kind: "execute_tool",
2703
+ label: "{Read,Grep}",
2704
+ file_glob: "/etc/{shadow,shadow-,gshadow,gshadow-,sudoers}"
2705
+ },
2706
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "/etc/sudoers.d/**" },
2707
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "/etc/ssh/ssh_host_*_key" },
2708
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "/etc/ssh/ssh_host_key" },
2709
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "/etc/ssl/private/**" },
2710
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "/etc/pki/tls/private/**" },
2711
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "/etc/kubernetes/*.conf" },
2712
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "/etc/kubernetes/pki/**/*.key" },
2713
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "/etc/rancher/k3s/k3s.yaml" },
2714
+ // Grep only: a search anywhere under `/etc`, including the folder itself.
2715
+ { kind: "execute_tool", label: "Grep", file_glob: "/etc/**" },
2716
+ // Read only: a remote URL or `http.extraheader` can carry a token.
2717
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "**/.git/config" },
2718
+ // Read only: MCP server definitions and agent settings often carry API keys in `env`.
2719
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "**/.mcp.json" },
2720
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "**/.claude/settings.local.json" },
2721
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "**/.claude.json" },
2722
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "**/.cursor/mcp.json" },
2723
+ { kind: "execute_tool", label: "{Read,Grep}", file_glob: "**/.codex/config.toml" },
2724
+ // Read only: production configuration and secret files (see the header).
2725
+ {
2726
+ kind: "execute_tool",
2727
+ label: "{Read,Grep}",
2728
+ file_glob: `${NOT_VENDORED}*.prod.?(*.)${PROD_CONFIG}`
2729
+ },
2730
+ {
2731
+ kind: "execute_tool",
2732
+ label: "{Read,Grep}",
2733
+ file_glob: `${NOT_VENDORED}prod.?(*.)${PROD_CONFIG}`
2734
+ },
2735
+ {
2736
+ kind: "execute_tool",
2737
+ label: "{Read,Grep}",
2738
+ file_glob: `${NOT_VENDORED}*.production.?(*.)${PROD_CONFIG}`
2739
+ },
2740
+ {
2741
+ kind: "execute_tool",
2742
+ label: "{Read,Grep}",
2743
+ file_glob: `${NOT_VENDORED}production.?(*.)${PROD_CONFIG}`
2744
+ },
2745
+ {
2746
+ kind: "execute_tool",
2747
+ label: "{Read,Grep}",
2748
+ file_glob: `${NOT_VENDORED}prod/${NOT_VENDORED}*.${PROD_CONFIG}`
2749
+ },
2750
+ {
2751
+ kind: "execute_tool",
2752
+ label: "{Read,Grep}",
2753
+ file_glob: `${NOT_VENDORED}production/${NOT_VENDORED}*.${PROD_CONFIG}`
2754
+ }
2697
2755
  ],
2698
2756
  none_of: [{ kind: "execute_tool", file_glob: "**/*.pub" }]
2699
2757
  },
@@ -2702,13 +2760,154 @@ var seCredentialFile = {
2702
2760
  file("/home/dev/.ssh/id_rsa", "Read"),
2703
2761
  file("/Users/dev/.aws/credentials", "Read"),
2704
2762
  file("certs/server.pem", "Read"),
2705
- file(".npmrc", "Write")
2763
+ file(".npmrc", "Write"),
2764
+ // The other arms hold every tool, under a production or vendored path too: the
2765
+ // production arms' limits do not reach them.
2766
+ file("/home/prod/.ssh/id_rsa.txt", "Edit"),
2767
+ file("/home/prod/.ssh/id_rsa.txt", "Read"),
2768
+ file("/srv/production/.ssh/id_ed25519.md", "Write"),
2769
+ file("vendor/certs/server.pem", "Read"),
2770
+ // The original arms, each with a path only that arm matches.
2771
+ file("/home/dev/keys/id_rsa", "Read"),
2772
+ file("backup/id_ed25519", "Write"),
2773
+ file("certs/client.p12", "Read"),
2774
+ file("android/app/release.jks", "Edit"),
2775
+ file("/home/dev/.pypirc", "Read"),
2776
+ file("/home/dev/.docker/config.json", "Read"),
2777
+ file("/home/dev/.kube/config", "Grep"),
2778
+ // Each read-only arm, once through Read and once through Grep.
2779
+ file("/etc/shadow", "Read"),
2780
+ file("/etc/gshadow", "Grep"),
2781
+ file("/etc/sudoers", "Read"),
2782
+ file("/etc/shadow-", "Read"),
2783
+ file("/etc/gshadow-", "Read"),
2784
+ file("/etc/sudoers.d/90-cloud-init-users", "Read"),
2785
+ file("/etc/sudoers.d/admins", "Grep"),
2786
+ file("/etc/ssh/ssh_host_ed25519_key", "Read"),
2787
+ file("/etc/ssh/ssh_host_rsa_key", "Grep"),
2788
+ file("/etc/ssh/ssh_host_key", "Read"),
2789
+ file("/etc/ssh/ssh_host_key", "Grep"),
2790
+ file("/etc/ssl/private/server.key", "Read"),
2791
+ file("/etc/ssl/private/ca.key", "Grep"),
2792
+ file("/etc/pki/tls/private/server.key", "Read"),
2793
+ file("/etc/pki/tls/private/localhost.key", "Grep"),
2794
+ file("/etc/kubernetes/admin.conf", "Read"),
2795
+ file("/etc/kubernetes/controller-manager.conf", "Grep"),
2796
+ file("/etc/kubernetes/pki/ca.key", "Read"),
2797
+ file("/etc/kubernetes/pki/etcd/ca.key", "Grep"),
2798
+ file("/etc/rancher/k3s/k3s.yaml", "Read"),
2799
+ file("/etc/rancher/k3s/k3s.yaml", "Grep"),
2800
+ // The Grep-only arm: a folder, a wildcard joined to a folder, and the root of `/etc`.
2801
+ file("/etc", "Grep"),
2802
+ file("/etc/ssh", "Grep"),
2803
+ file("/etc/kubernetes", "Grep"),
2804
+ file("/etc/ssh/*_key", "Grep"),
2805
+ file("/etc/shadow*", "Grep"),
2806
+ file("/etc/hosts", "Grep"),
2807
+ file("/repo/.git/config", "Read"),
2808
+ file("/repo/.git/config", "Grep"),
2809
+ file(".mcp.json", "Read"),
2810
+ file(".mcp.json", "Grep"),
2811
+ file("/repo/.claude/settings.local.json", "Read"),
2812
+ file("/repo/.claude/settings.local.json", "Grep"),
2813
+ file("/Users/dev/.claude.json", "Read"),
2814
+ file("/Users/dev/.claude.json", "Grep"),
2815
+ file("/repo/.cursor/mcp.json", "Read"),
2816
+ file("/Users/dev/.cursor/mcp.json", "Grep"),
2817
+ file("/Users/dev/.codex/config.toml", "Read"),
2818
+ file("/Users/dev/.codex/config.toml", "Grep"),
2819
+ file("config/database.prod.yml", "Read"),
2820
+ file("docker-compose.prod.yml", "Grep"),
2821
+ file("config/prod.json", "Read"),
2822
+ file("config/prod.env", "Grep"),
2823
+ file("config/app.production.json", "Read"),
2824
+ file("config/app.production.toml", "Grep"),
2825
+ file("config/production.yaml", "Read"),
2826
+ file("config/production.env", "Grep"),
2827
+ file("deploy/prod/values.yaml", "Read"),
2828
+ file("infra/envs/prod/main.tfvars", "Grep"),
2829
+ file("deploy/prod/app.properties", "Read"),
2830
+ file("k8s/production/secrets.yaml", "Read"),
2831
+ file("k8s/production/configmap.yml", "Grep"),
2832
+ // Folders that only start with a skipped name are still held.
2833
+ file("distribution/prod.json", "Read"),
2834
+ file("vendors/config/production.yml", "Grep"),
2835
+ // One fixture per file type not used above.
2836
+ file("infra/prod/main.tf", "Read"),
2837
+ file("config/nginx.prod.conf", "Read"),
2838
+ file("config/app.prod.ini", "Grep")
2706
2839
  ],
2707
2840
  allow: [
2708
2841
  file("/home/dev/.ssh/id_rsa.pub", "Read"),
2709
2842
  file("certs/server.crt", "Read"),
2710
2843
  file("src/index.ts"),
2711
- file("package.json")
2844
+ file("package.json"),
2845
+ // Near-misses of the read-only arms.
2846
+ file("/etc/passwd", "Read"),
2847
+ file("/etc/passwd-", "Read"),
2848
+ file("/etc/group", "Read"),
2849
+ file("/etc/hosts", "Read"),
2850
+ file("/etc/sudo.conf", "Read"),
2851
+ file("/etc/ssh/ssh_host_ed25519_key.pub", "Read"),
2852
+ file("/etc/ssh/ssh_host_key.pub", "Read"),
2853
+ file("/etc/ssh/sshd_config", "Read"),
2854
+ file("/etc/ssl/certs/ca-certificates.crt", "Read"),
2855
+ file("/etc/pki/tls/certs/server.crt", "Read"),
2856
+ file("/etc/kubernetes/manifests/kube-apiserver.yaml", "Read"),
2857
+ file("/etc/kubernetes/pki/ca.crt", "Read"),
2858
+ file("/etc/rancher/k3s/config.yaml", "Read"),
2859
+ file("/opt/etc/app.conf", "Grep"),
2860
+ file("/repo/.git/HEAD", "Read"),
2861
+ file("/repo/.gitconfig.example", "Read"),
2862
+ file("mcp.json.example", "Read"),
2863
+ file("/repo/.claude/settings.json", "Read"),
2864
+ file("/repo/claude.json", "Read"),
2865
+ file("/repo/.cursor/rules/style.mdc", "Read"),
2866
+ file("/repo/codex/config.toml", "Read"),
2867
+ file("config/database.staging.yml", "Read"),
2868
+ // Production code, prose and vendored files are not production configuration.
2869
+ file("node_modules/react/cjs/react.production.min.js", "Read"),
2870
+ file("node_modules/react-router/dist/production/index.d.ts", "Grep"),
2871
+ // One vendored configuration file per production arm.
2872
+ file("node_modules/some-lib/config/app.prod.json", "Read"),
2873
+ file("dist/prod.json", "Read"),
2874
+ file("node_modules/some-lib/config/app.production.json", "Grep"),
2875
+ file("vendor/config/production.yml", "Read"),
2876
+ file("dist/prod/app.json", "Read"),
2877
+ file("vendor/production/config.yml", "Grep"),
2878
+ file("src/Settings.prod.test.tsx", "Read"),
2879
+ file("infra/bin/prod.ts", "Read"),
2880
+ file("webpack.prod.js", "Grep"),
2881
+ file("config/database.prod.md", "Read"),
2882
+ file("config/prod.md", "Read"),
2883
+ file("config/app.production.mdx", "Read"),
2884
+ file("config/production.txt", "Read"),
2885
+ file("deploy/prod/RUNBOOK.txt", "Grep"),
2886
+ file("docs/production/README.md", "Read"),
2887
+ // The read-only arms do not hold an edit: the guardrail that owns each path does.
2888
+ file("/etc/shadow", "Edit"),
2889
+ file("/etc/shadow-", "Write"),
2890
+ file("/etc/sudoers.d/admins", "Write"),
2891
+ file("/etc/ssh/ssh_host_ed25519_key", "Write"),
2892
+ file("/etc/ssh/ssh_host_key", "Edit"),
2893
+ file("/etc/ssl/private/server.key", "Edit"),
2894
+ file("/etc/pki/tls/private/server.key", "Write"),
2895
+ file("/etc/kubernetes/admin.conf", "Write"),
2896
+ file("/etc/kubernetes/pki/sa.key", "Write"),
2897
+ file("/etc/rancher/k3s/k3s.yaml", "Edit"),
2898
+ file("/etc/hosts", "Edit"),
2899
+ file("/repo/.git/config", "Edit"),
2900
+ file(".mcp.json", "Edit"),
2901
+ file("/repo/.claude/settings.local.json", "Write"),
2902
+ file("/Users/dev/.claude.json", "Write"),
2903
+ file("/repo/.cursor/mcp.json", "Edit"),
2904
+ file("/Users/dev/.codex/config.toml", "Edit"),
2905
+ file("config/database.prod.yml", "Edit"),
2906
+ file("config/prod.json", "Write"),
2907
+ file("config/app.production.json", "Edit"),
2908
+ file("config/production.yaml", "Write"),
2909
+ file("deploy/prod/values.yaml", "Edit"),
2910
+ file("k8s/production/secrets.yaml", "Write")
2712
2911
  ]
2713
2912
  }
2714
2913
  };
@@ -3859,8 +4058,8 @@ function owaspTitle(id) {
3859
4058
  }
3860
4059
 
3861
4060
  // src/stamp.ts
3862
- var CATALOG_VERSION = "0.2.4";
3863
- var CATALOG_PUBLISHED_AT = "2026-10-16T16:15:37Z";
4061
+ var CATALOG_VERSION = "0.2.6";
4062
+ var CATALOG_PUBLISHED_AT = "2026-10-22T16:18:01Z";
3864
4063
 
3865
4064
  // src/rules.ts
3866
4065
  var RULES_BY_PACK = {