Skip to content

feat(rules): add Pinecone and LangSmith API key detection rules - #2177

Open
DevamShah wants to merge 1 commit into
gitleaks:masterfrom
DevamShah:add-pinecone-langsmith-rules
Open

DevamShah wants to merge 1 commit into
gitleaks:masterfrom
DevamShah:add-pinecone-langsmith-rules

Conversation

@DevamShah

Copy link
Copy Markdown

Summary

Adds two new high-confidence Gitleaks rules — pinecone-api-key and langsmith-api-key — covering credentials for the vector-database and LLM-observability layers that now sit at the centre of most RAG/AI stacks. Both rules anchor on vendor-issued, structurally distinctive prefixes, so they detect real leaks while keeping false positives near zero.

Problem / motivation

Gitleaks ships rules for the AI model providers (Anthropic, OpenAI, Cohere, Hugging Face, Perplexity, Bedrock) but has no coverage for the retrieval and observability tier those models depend on. A leaked Pinecone or LangSmith key is not a low-value finding:

  • Pinecone keys grant read/write access to the vector indexes that store an application's embedded private data. A compromised key enables silent exfiltration of the underlying corpus and index poisoning of downstream retrieval.
  • LangSmith keys (personal access tokens and service keys) expose tracing data — full prompts, completions, tool I/O — plus the ability to act against connected LangChain/LangGraph workloads.

Both are routinely committed to .env files, notebooks, CI config, and IaC, and today pass through Gitleaks undetected (at best they trip the noisy generic-api-key rule, which yields a generic finding with no provenance).

Change

Following CONTRIBUTING.md exactly:

  • cmd/generate/config/rules/pinecone.go — PineconeApiKey()
  • cmd/generate/config/rules/langsmith.go — LangsmithApiKey()
  • Registered both in cmd/generate/config/main.go (alphabetical ordering preserved).
  • Regenerated config/gitleaks.toml via go generate ./cmd/generate/config/.

Both rules use GenerateUniqueTokenRegex, consistent with the existing prefix-anchored AI-provider rules (anthropic.go, openai.go), because the token prefixes are themselves the high-signal identifier:

Rule Pattern Source of truth
pinecone-api-key pcsk_[A-Za-z0-9]{5,6}_[A-Za-z0-9]{63} Verified against Pinecone's pcsk_<label>_<key> format
langsmith-api-key lsv2_(?:pt|sk)_[a-z0-9]{32}_[a-z0-9]{10} LangSmith PAT (lsv2_pt_) and service-key (lsv2_sk_) prefixes per LangSmith admin docs

An entropy = 3 floor is set on both to suppress low-entropy placeholders and documentation samples.

Security rationale

  • OWASP LLM Top 10 (2025) — LLM02: Sensitive Information Disclosure and LLM03: Supply Chain: the vector store and tracing backend are the two components where an AI application's private data and prompt logic concentrate; credential leakage here maps directly to these risks.
  • CWE-798: Use of Hard-coded Credentials — the exact weakness these rules surface in source control.
  • MITRE ATT&CK T1552.001 (Unsecured Credentials: Credentials In Files) — the technique these findings interdict pre-commit.
  • Prefix-anchored matching (rather than keyword-proximity heuristics) keeps the false-positive rate negligible, which is the bar for a default-config rule.

Testing / validation

  • go generate ./cmd/generate/config/ — succeeds; the generator runs Validate() (true-positive + false-positive assertions) against every rule and exits non-zero on any failure. Both new rules pass.
  • go build ./... — clean.
  • go test ./cmd/generate/... ./config/... — pass (the config test parses the regenerated gitleaks.toml).
  • End-to-end gitleaks detect against a fixture:
    • Positives detected: pcsk_<6>_<63>, lsv2_pt_<32>_<10>, lsv2_sk_<32>_<10> — each attributed to the correct rule.
    • Negatives not flagged: truncated pcsk_abc_tooshort, a generic eyJ... JWT, a legacy ls__ key (deprecated 2024-10-22), and a malformed lsv2_xx_... type segment.

Checklist

  • Does your PR pass tests?
  • Have you written new tests for your changes? (tps/fps embedded in each rule, enforced by the generator)
  • Have you lint your code locally prior to submission? (gofmt)

Pinecone (pcsk_) keys grant access to vector-database indexes backing RAG/AI
apps; LangSmith (lsv2_pt_ / lsv2_sk_) keys expose LangChain/LangSmith tracing
data, prompts, and connected LLM workloads. Both are increasingly committed to
source in the LLM/RAG ecosystem and were undetected by gitleaks.

Adds pinecone-api-key and langsmith-api-key rules with prefix-anchored regexes,
keyword prefilters, entropy 3, and TP/FP validation samples; regenerated
config/gitleaks.toml via go generate.

Signed-off-by: Devam Shah <devamshah91@gmail.com>

@sanmaxdev sanmaxdev 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.

Both rules look solid. The Pinecone regex (pcsk_[A-Za-z0-9]{5,6}_[A-Za-z0-9]{63}) and LangSmith regex (lsv2_(?:pt|sk)_[a-z0-9]{32}_[a-z0-9]{10}) match their documented key formats, and the false positive cases (wrong prefix, wrong key-type segment, too-short body) are covered.

Verified:

  • go run ./cmd/generate/config/main.go ../../../config/gitleaks.toml (config regenerates with no diff)
  • go test ./detect/... -count=1
  • go build ./...

@DevamShah

Copy link
Copy Markdown
Author

Re-verified this against current master (b58d3f1) rather than leaving it sitting.

Still applies cleanly. master has only moved by six dependabot GitHub Actions bumps since the branch point (8ad8470), so there are no conflicts and nothing in this PR's path changed. I rebased locally onto b58d3f1 and it replayed clean. I have deliberately not force-pushed: it would only churn the head SHA and risk dropping @sanmaxdev's existing approval, with no benefit — see the CI note below.

What I ran on top of b58d3f1 (go1.26.2 locally; CI pins 1.25):

$ go build ./...                          # exit 0, no output
$ go generate ./... && git diff --exit-code
                                          # exit 0 — config/gitleaks.toml regenerates byte-identical
$ go test ./... -count=1                  # exit 0
ok  github.com/zricethezav/gitleaks/v8/cmd/generate/config/base   0.701s
ok  github.com/zricethezav/gitleaks/v8/cmd/generate/config/utils  1.444s
ok  github.com/zricethezav/gitleaks/v8/config                     1.624s
ok  github.com/zricethezav/gitleaks/v8/detect                     4.362s
ok  github.com/zricethezav/gitleaks/v8/detect/codec               1.984s
ok  github.com/zricethezav/gitleaks/v8/report                     4.459s
ok  github.com/zricethezav/gitleaks/v8/sources                    2.673s

The go generate ./... && git diff --exit-code line is exactly the Validate Config step from .github/workflows/test.yml, so that step should be green.

End-to-end check with the built binary, not just the tps/fps in Validate. Scanned a file containing synthetic keys and confirmed which rule fired:

langsmith-api-key | lsv2_pt_edt2sywb3wkh5dnsipzz5fk2z9ri19r0_wyojfljoo
langsmith-api-key | lsv2_sk_5lqsaj08xui6d39zzzzg4zdmen2khvdg_aj8gxbeny
pinecone-api-key  | pcsk_u8jzP_de0IgxLd6GncfBAepfJBd0Kh8oOOL8dKLzdocJ2...
pinecone-api-key  | pcsk_NnFRIB_XuDL7DxtpYlSXpfKtHF4vUCsMehGAkWvj7FAc9...

That covers both the 5- and 6-character Pinecone id segment ({5,6}) and both LangSmith key types. pcsk_abcde_tooShort, the legacy ls__ key, and lsv2_xx_... produced no findings.

On why this is BLOCKED — I dug into it, and I don't think it's anything wrong with the branch:

  1. mergeable is MERGEABLE, but reviewDecision is still REVIEW_REQUIRED. @sanmaxdev's approval is recorded with author_association: NONE, and GitHub only counts reviews from users with write access toward branch protection. So the review is real and appreciated, but it can't satisfy the gate on its own — this needs a maintainer to click approve.
  2. There are zero check runs on the head SHA. That isn't specific to this PR: I checked the twelve most recent open PRs and every fork-authored one has 0 checks, while the dependabot PRs have 3. That's the "require approval to run workflows for outside contributors" setting, so CI here needs a maintainer to press Approve and run.

@sanmaxdev — thanks for actually running the generator and the tests back in July rather than eyeballing the regex. Is there anything else you want changed here, or is this purely waiting on maintainer bandwidth? If a maintainer would rather I split Pinecone and LangSmith into two separate PRs to make review smaller, I'll do that today.

This branch has not been deployed

No deployments
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.

2 participants