Skip to content

Sync with upstream TruffleHog v3.98.0 - #19

Merged
infraguard-web merged 237 commits into
mainfrom
sync/upstream-v3.98.0
Oct 8, 2026
Merged

infraguard-web merged 237 commits into
mainfrom
sync/upstream-v3.98.0

Conversation

@infraguard-web

@infraguard-web infraguard-web commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

Brings the fork up to upstream v3.98.0 (235 commits, last sync was May).

  • Conflicts were only main.go and pkg/feature/feature.go, kept both sides. The custom --header option is unchanged.
  • Fork main (the scanner release workflow) is merged in.
  • Checked locally: builds, --header reaches a local listener on a custom detector verification call, and the appsec-workflows tests pass against this build (64, including the real scanner).

Only the branch is pushed, no upstream tags, so upstream's release.yml doesn't run.

Next: run "scanner release" on the merge commit and pin it in appsec-workflows as v2.0.2.

johnelliott and others added 30 commits April 29, 2026 13:03
…ecurity#4928)

Non-fatal scanning errors aren't really "errors" - they're consequences of the vicissitudes of scanning a ton of data. They're actionable if you're looking for them but if you're not they're extremely noisy. This commit downgrades them to only show up when you look for them.
* added cloudinary detector

* resolved linter issue

* improved regex

* added dector to defaults.go

* resolved comments

* Regen protos, Updated desc and ignore secret part in test
…ql v4, auth v3, goreleaser v7, mikepenz v6, jaxxstorm v3.0.0, docker login/qemu v4) (trufflesecurity#4933)

Made-with: Cursor
)

golangci-lint-action v8+ requires golangci-lint v2 (this repo
already pins v2.11.4). v9 runs on Node 24, eliminating the
upcoming Node 20 deprecation warning.

Made-with: Cursor
… verification request (trufflesecurity#4947)

* added content-type=application/json as default header

* improv: set content type header when it is not present in the config

* handled canonicalization
…rity#4948)

* Update linter to disallow assigning SecretParts later

This means all detectors.Result objects must be created with the
SecretParts field set.

* Update documentation

* Migrate existing detectors to always initialize SecretParts
* Add Pinecone API key detector

Adds a new detector for Pinecone vector database API keys (pcsk_* format).

Detection:
- Regex matches the pcsk_{key_id}_{secret} structure with tight bounds
  (4+ char key ID, 40+ char secret, word boundaries) to minimize false positives.
- Extracts the embedded key_id from the token unconditionally, which maps to
  the key entry in the Pinecone console and aids revocation.

Verification:
- Uses GET /indexes (non-state-changing, read-only) with Api-Key header auth.
- Validates response body structure (requires "indexes" JSON key), not just
  status codes, to be resilient against API changes.
- 200: Verified. Extracts project_id from index host, total_indexes, and
  metadata for up to 5 indexes (name, host, cloud, region).
- 401: Invalid key (handles both plain text and JSON error bodies).
- 403: Valid key with restricted permissions (DataPlane-only roles).
  Marked as verified with permission=restricted metadata.

Uses common.SaneHttpClient() with standard timeouts (5s response, 2s dial,
3s TLS) and io.LimitReader (1MB cap) on response body. No SDK dependencies.

Registered as DetectorType Pinecone = 1048.

Made-with: Cursor

* Align Pinecone detector with SecretParts

Migrate Pinecone verification metadata to SecretParts, address the redundant 200-response JSON parsing Bugbot flagged, and add focused regression coverage for malformed verification responses.

* Refactor Pinecone detector and add tests

---------

Co-authored-by: Dylan Ayrey <dylan@Dylans-MacBook-Pro.local>
Co-authored-by: Dustin Decker <dustin@trufflesec.com>
Co-authored-by: Shahzad Haider <shahzadhaider.se@gmail.com>
Co-authored-by: Shahzad Haider <76992801+shahzadhaider1@users.noreply.github.com>
…trufflesecurity#4892)

* adding customizable successRanges and rotatedRanges to customDetector

*setting definitive = true in the legacy 200 path so that an earlier ranged verifier's rangesInEffect = true can't trigger a spurious SetVerificationError after the legacy verifier already confirmed the secret as live.

* adressed review comments
….go (trufflesecurity#4915)

* add test to ensure new detectors are registered in defaults.go

* fix lint
…flesecurity#4907)

* unify common logic in atlassian data center detectors

* initialize url pat once

* engine_test fix

* remove bitbucketdatacenter from defaults test exclude list
* added gitlab oauth detector

* addressed comments; embed detectors.DefaultMultiPartCredentialProvider and use available ctx in tests

* made comments more meaningful and break loop when secret is verified against one client id

* switch from detectorspb to detector_typepb

* populate secretparts

* add secretparts to results in gitlaboauth2 detector

---------

Co-authored-by: Charlie Gunyon <camgunz@users.noreply.github.com>
…urity#4761)

* extract subject id in boxoauth detector

* update the detector design for subject id handling

* verify subject ID via CCG auth before populating AnalysisInfo

Instead of blindly pairing every found subject ID with verified
credentials, use the Box CCG token endpoint to verify which subject ID
actually works. Emit one result per credential pair with only the
verified subject ID in AnalysisInfo. Add gock-based tests for all
AnalysisInfo scenarios.

* replace analysisinfo with secretparts

* [INS-379] Populate SecretParts unconditionally in BoxOauth detector

Always set client_id and client_secret in SecretParts regardless of
verification status. subject_id is added only when a valid triplet is
confirmed via verifySubjectID. Previously SecretParts was only populated
for a fully verified triple, leaving unverified results with no
credential data stored.

* address bugbot comment; Non-deterministic map iteration for subject ID selection

---------

Co-authored-by: Charlie Gunyon <camgunz@users.noreply.github.com>
* spectralops-detector

* increased context deadline

* registered detector in engine

* Correct comment on SpectralOps API key format

* updated keyword

* fixed test

* Merged main

* Regen protos, Updated desc and ignore secret part in test

* updated protos
* Added AWS Appsync Detector

* added detector to defaults.go

* imprved regex and regen protos

* added secretparts

* ignored secret parts in test

* resolved bugbot comment
* add detector corpora test workflow and script

* only run once per PR, make comment descriptive, add handling for manual runs to get PR issue number

* comment out types to see result on all commits

* uncomment types

* remove table from comment

* comment out types

* Phase 0: add explicit pipefail and capture trufflehog stderr

* Phase 1: differential diffing PR vs main

* DEMO: loosen Stripe regex (will revert)

* DEMO: loosen JDBC regex (will revert)

* Phase 1 fix: add --allow-verification-overlap, fix no-diff detection

The bench uses --no-verification, so the engine's overlap-path dedup
(which exists to protect verifiers from duplicate calls) adds noise
without value here — it causes shifts in unrelated detectors when only
one detector's regex changes. Pair --allow-verification-overlap with
--no-verification so each detector's regex behavior is measured
independently.

Also fix the false 'no diff vs main' claim that triggered when
NEW/REMOVED were zero but total counts differed.

* revert jdbc detector change

* Phase 2: detector scoping, new-detector handling, blast radius, status emoji

* DEMO: loosen JDBC + add fictional acmevault detector

* Phase 2 fix: harden corpus byte counting against early trufflehog exit

awk's END block doesn't run when trufflehog exits before draining stdin
(SIGPIPE kills awk first), leaving the bytes file empty and breaking the
step with a `$((TOTAL_BYTES + ))` syntax error. Read the file with a
default of 0 and validate it's an integer before arithmetic. Also fold
unzstd/jq stderr into STDERR_FILE so benign Broken pipe notices stay
out of CI logs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Phase 3a (1/3): add hack/extract-keywords for detector keyword introspection

Static AST parse of a detector package to extract the strings returned by
its Keywords() method. Used by the upcoming keyword-corpus builder to fan
out per-detector GitHub Code Search queries during the corpora bench.

AST-first because each detector lives in its own package; importing them
dynamically would require codegen or `plugin`. Falls back to a regex over
the function body, then a directory-wide grep, when AST resolution can't
statically resolve the return value (helper calls, build-tagged variants).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Phase 3a (2/3): add Layer 1 keyword corpus builder + workflow integration

build_keyword_corpus.py queries GitHub Code Search for each changed
detector's pre-filter keywords and emits a zstd-compressed JSONL whose
shape matches the existing S3 corpus exactly: each line is
`{"provenance": {...}, "content": "<raw file content>"}`. The corpora
script's existing `unzstd | jq -r .content` pipe handles it unchanged —
provenance is descriptive only and never reaches trufflehog.

Rate-limit policy is header-driven: the search bucket's
X-RateLimit-Remaining and X-RateLimit-Reset headers gate every call,
with a 2.1s floor between requests as belt-and-suspenders. 403/429s
honor Retry-After or fall back to the reset window. Cap is 100 unique
results per detector, deduped on (repo, path, sha), with a per-keyword
sub-cap so one popular keyword can't starve the others.

A sidecar JSON reports per-detector fetch counts and a thin_l1 list of
detectors whose total returned results were zero (or whose keyword
extraction failed). The diff script reads it via a new
--keyword-corpus-meta arg and renders a single contiguous blockquote
callout above the per-detector details — a sidecar instead of an
in-corpus signal because stdin metadata is dropped from trufflehog's
findings output.

Workflow change: a new "Build keyword corpus (Layer 1)" step fires after
detector detection and overwrites DATASETS via $GITHUB_ENV to append the
keyword corpus path. The corpora script picks it up unchanged through
its existing local-file branch.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Phase 4 complete - Heatmap visualization

* Phase 4 rework (1/2): emit heatmap-grid.json sidecar from render_heatmap.py

Add a JSON sidecar that captures the same Δ matrix the PNG renders. The
diff script consumes this to render an emoji-bucketed Markdown table —
GitHub's PR-comment Markdown sanitizer strips data: URLs and serves
artifact zips behind auth, so neither inline base64 nor an artifact
<img src> embed actually displays. The PNG stays for artifact archival
and click-through.

Sidecar shape: {detectors, decoders, deltas, _layout}, with _layout
documenting the deltas[i][j] orientation inline so future readers don't
have to reverse-engineer it. Emitted whenever the grid is non-empty,
even if matplotlib import fails — the comment never depends on the PNG.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Phase 4 rework (2/2): replace data-URL embed with emoji-bucketed Markdown table

GitHub's PR-comment Markdown sanitizer strips data: URLs from user
content, so the inline base64 PNG embed shipped in the prior commit
rendered as a broken link in the comment DOM (no <img> tag emitted).
Artifact-zip URLs require auth to download, so a fallback ![](...) link
is also a non-starter — it would render as a broken image.

Switch to a per-(detector, decoder) Δ table built from the grid JSON
sidecar render_heatmap.py now emits. Cells use emoji buckets aligned
with the existing status-emoji thresholds so the visual weight matches
the summary table:

  🟥 Δ ≥ +6   (matches NEW > 5 → 🔴)
  🟧 +1..+5
  ⬜ 0
  🟦 ≤ −1

Renders identically on web, mobile, email notifications, and CI log
replay — every surface a PR comment lands on. The colored matplotlib
PNG stays as a workflow artifact; when --heatmap-artifact-url is
supplied, the table is followed by a click-through link for reviewers
who want the rich version.

Workflow YAML mirrors the rename (--heatmap-png → --heatmap-grid) and
drops the base64-blob log filter — the report is back to plain
human-readable text.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* Phase 5 complete - Polish

* cleanup, enable verification

* fix bug

* optimizations

* cache keywords corpus

* rewrite comment message

* cache github api corpus per keyword

* cleanup

* remove github corpus

* revert changes for testing

* move Configure AWS credentials step to run only when detector changes are detected

* revert unnecessary changes

* cleanup + bugbot fixes

* run test with bigger (30gb) dataset, loosen jdbc regex

* optimizations

* bugbot fixes

* revert jdbc changes and bugbot fix

* run only on regex and/or keywords change

* bugbot fixes

* bugbot fix

* incorporate brad's comments, loosen jdbc regex to run a test to ensure everything works as expected

* revert test changes

* fix misleading bench skipped message

* run only once when PR opens

* pipe stderr directly to CI log instead of writing to file, loosen jdbc regex to trigger workflow

* testing: run on all commits

* add archive timeout

* remove bigger dataset

* revert testing changes

---------

Co-authored-by: Shahzad Haider <shahzadhaider.se@gmail.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
…issues (trufflesecurity#4924)

* enable errcheck and staticcheck for golangci-lint v2 and resolve all issues

* skip lint on intentional reference of deprecated DetectorType values
…rufflesecurity#4849)

Populate ExtraData with parsed fields for all
database connection string detectors (MongoDB, PostgreSQL, Redis, JDBC).
This surfaces useful metadata about detected credentials.

The parsing logic already existed in each detector — this change
exposes the extracted values in the result's ExtraData map alongside
any pre-existing fields (rotation_guide, sslmode, etc.).
* remove over speculation from corpora ci workflow, change lob detector for testing (will revert)

* revert lob changes
…y#4910)

* fix line numbers for duplicate secrets within a chunk

* fix-test: use cmpopts.IgnoreUnexported instead of cmpopts.IgnoreFields

* refactor: unify FragmentLineOffset offset/ignore-tag logic

* refactor: extract effectiveSecret helper for chunk-offset callers
trufflesecurity#4961)

* Add feature flags for new detectors

* Slight rename, ensure the flags are false by default

* Missed a name change

* Turn on new detectors for OSS user

* Instead of only adding flagged detectors when their flag is enabled, remove them when their flag is disabled

* Thank you cursorbot

* Excempt the flagged detectors from a test
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Dustin Decker <humanatcomputer@gmail.com>
Convert all GitHub Actions uses: refs from mutable tags to immutable
SHA pins with version comments. This prevents tag-hijack supply chain
attacks while preserving version tracking for Renovate.

Part of the org-wide Dependency Strategy Unification (Step 2).

Co-authored-by: Cursor <cursoragent@cursor.com>
…flesecurity#4983)

* Update CODEOWNERS: replace 5 slugs with scanning + integrations

* Move gitparse and giturl to integrations

Remove explicit scanning rules -- both packages fall to the
integrations default. They are git utility libraries consumed
by multiple source integrations.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
* Added scan version feature flag to sharepoint proto

* added more fields to sharepoint proto

* renamed fields
…esecurity#4981)

* support aspx decoding in html decoder

* check isNamespaced before prefix comparison
… obfuscated APKs or APKs with resource types the 3rd party library isn't parsing (trufflesecurity#4991)

* fix(apk): adds some debugging info (APK package name) which is helpful when processing large repos of APKs, and fixes processing of obfuscated APKs that might cause lots of errors with our APK processing library

* fix(apk): put the ci.Next() iterator over classes into an IIFE

* fix(apk): some cursor issues in the PR

* fix(apk): continue if it fails to get a string value rather tahn error out completely skipping the rest of the resources

* docs(apk): add comment noting why it is a continue now

* fix(apk): had to add a thin interface wrapping apkparker logic and GetResourceEntry to mock out and test that it continues through bad string entries

* refactor(apk): renamed resourceEntryProvider to GetEntryer to be more go-ish
…gs (trufflesecurity#5011)

* enhance the verification in the enigma detector

* feat(enigma): gate detector behind feature flag
trufflesecurity#5022)

* fix: scan files with lines exceeding bufio's default 64 KB token limit

* added related test
shahzadhaider1 and others added 29 commits September 24, 2026 14:38
* detectors/azureapimanagementsubscriptionkey: report skipped candidates

* detectors/azuredirectmanagementkey: report skipped candidates

* detectors/artifactory: report candidates skipped by the host cache

* detectors/algoliaadminkey: report candidates skipped by the host cache

* detectors/azure_cosmosdb: report candidates skipped by the host cache

* detectors/azurecontainerregistry: report candidates skipped by host cache

* detectors/repositorykey: report candidates skipped by the host cache
* return error body for fetchBearerToken

* took out limitReader and return full response body
…ecurity#5281)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…flesecurity#5280)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
…rity#5367)

The Square detector treated every 403 as a live key. A 403 can also come
from a TLS-intercepting proxy or security appliance, or from Square's own
edge (rate limiting, bot protection). Those cases produced false "verified"
results. The response body was also discarded, so there was nothing to
diagnose them with.

- Move verification into verifyMatch with an injectable HTTP client
- Mark a 403 as verified only when Square's error body has code
  INSUFFICIENT_SCOPES
- Report other 403s and unexpected statuses as verification errors that
  include the response body (read up to 4 KiB, cut to 512 bytes in the
  error, whitespace collapsed)
- Add unit tests for 200, 401, 403 (scopes, HTML, other code, empty),
  429, and body truncation
trufflesecurity#5293)

Adds a CLI flag that disables the default suppression of results whose
line contains a `trufflehog:ignore` comment. Detection is unchanged;
only the post-detection drop in processResult is bypassed.
* Report progress inside a bucket while scanning an S3 unit

* Leave objects the scan never downloads out of the S3 progress ratio and publish when the count finishes

* Keep filtered objects in the S3 progress total, since the scan counts them as done

* Treat a cancelled S3 count pass as incomplete so its partial totals are not divided by

* Add a per-unit progress API so a source can report how far it has got inside a unit

* Track S3 progress per unit behind a feature toggle and leave skipped objects out of both sides
…ufflesecurity#5353)

* fix(output): escape special characters in --github-actions output

Git allows characters in file paths that GitHub's workflow-command syntax
does not — most notably newlines. When such a path is read back from a diff
and printed as part of a ::warning:: command in --github-actions output
mode, the result can be malformed and split across multiple lines that
GitHub Actions doesn't expect.

Escape file paths and messages before printing, per GitHub's documented
escaping rules for workflow commands (percent-encode '%', '\r', '\n', and
additionally ':'/',' for the file= property value).

Extract the command-building into formatWarningCommand() so this is covered
by unit tests, following the same data/IO separation SarifPrinter already
uses.

Reported by kenanyararbas <kenanyararbas@gmail.com>.

* fix(output): drop doc comments on new helpers to match file convention

Print() and the other helpers in this file (structToMap, extractFileAndLine)
carry no doc comments, so match that rather than introducing one-off
commented functions.
…ecurity#5334)

Co-authored-by: Gracy769 <169199616+Gracy769@users.noreply.github.com>
Co-authored-by: Shahzad Haider <76992801+shahzadhaider1@users.noreply.github.com>
…flesecurity#5358)

* added entropy filter and improved verification for gitlab v2/v3

* added more cases for gitlab verification
…both sides (trufflesecurity#5357)

* Corpora bench reports clean when a detector produces zero matches on both sides

* Corpora bench reports clean when a detector produces zero matches on both sides

* test okta corpus

* remove changes that were used to test github actions
…ains (trufflesecurity#5354)

domainPat required the literal substring auth0.com, so it never matched
Auth0 Private Cloud tenants' default managed domain (*.auth0app.com). Since
FromData only emits a result when a client_id, client_secret, and a domain
match are all present together, a leaked credential pair next to its real
Private Cloud domain was silently dropped -- no result, no verification
attempt.

*.auth0app.com is Auth0's own documented default for Private Cloud tenants,
not a one-off customer naming choice:
https://auth0.com/docs/migrate-private-cloud-custom-domains

Add an optional, non-capturing app group so domainPat matches both
*.auth0.com and *.auth0app.com. Fully custom domains (e.g. login.example.com)
have no learnable Auth0-related substring and remain out of scope.

A pre-existing, unrelated regex quirk was discovered while adding regression
tests: a bare domain with no leading character (e.g. "auth0.com" or
"auth0app.com" with no subdomain/prefix at all) never matches, since the
leading character class must be consumed before the literal "auth0"
substring. Left as a TODO on domainPat rather than fixed here, since it's
out of scope for this change.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* List only the keys under the S3 include prefixes rather than the whole bucket

* Count only the keys under the S3 include prefixes for unit progress

* Validate S3 access with the listing a scan starts with, so prefix scoped policies pass
…rufflesecurity#5380)

and maintain our own cache and expiry.

Using ghinstallation.Transport turned out to be a mistake because
rate limit errors weren't returned as the github client error types the
caller looks for, but also the github client can circuit-break
rate-limited requests before they're made.  That's all in the client
rather than a transport/roundtripper, so we're going back to request
through that.

INT-1151
…curity#5383)

* Fix NetSuite detector memory blowup by keeping one result per key pair

* Stop NetSuite verification after the deadline, look up missing hosts once, and drain responses

* Update NetSuite integration test to expect one result per key pair
…5375)

Every link here resolves to a 404 on GitHub today. The three file links
were verified by reading the href GitHub renders and requesting it; the
two anchors were checked against the headings they name.

README.md said the AWS credential detector lives in pkg/detectors/aws/aws.go.
That file is gone: the detector was split into access_keys and session_keys,
and the GetCallerIdentity call the sentence describes is in
access_keys/accesskey.go.

Adding_Detectors_Internal.md linked pkg/common/http.go and a heroku test
without a leading slash, so both resolved under hack/docs/ rather than the
repository root. Adding_Detectors_external.md already writes the same
SaneHttpClient link with the slash, so this just brings the two in line. The
heroku link also named heroku_test.go, which only exercises the pattern;
the step is about reading a value out of GSM, and heroku_integration_test.go
is the file that does that with common.GetSecret and MustGetField.

The last two are a copy-paste seam between the sibling documents. Internal
titles its section "Creating a new Secret Scanner" but its table of contents
asked for #creating-a-new-secret-detector; external titles the same section
"Detector" but its step 5 asked for #creating-a-new-secret-scanner. Each
document now points at its own heading.
…er clients (trufflesecurity#5288)

* Add pkg/ssrf shared egress guard and use it for WithNoLocalIP

Centralizes SSRF egress protection so detectors and downstream consumers
(the thog analyzer guard) share one classification and one enforcement
mechanism.

pkg/ssrf provides ErrEgressBlocked, IsNonPublicIP, CheckDialAddress, and
GuardDialer. The blocked set is broader than the old isLocalIP: it adds
CGNAT (incl. Alibaba metadata), class E, test-nets and other special-use
ranges, all multicast, and IPv6 embeddings of internal v4 targets (NAT64,
6to4, IPv4-compatible) that To4() does not normalize.

WithNoLocalIP now installs a dialer whose Control hook checks the
resolved address immediately before connect. The previous implementation
vetted a LookupIP result and then dialed the hostname again, which a
DNS-rebinding resolver could race; Control runs on the address actually
being dialed, and re-runs on every redirect hop. ErrNoLocalIP remains as
a deprecated alias of ssrf.ErrEgressBlocked so errors.Is call sites keep
working.

* Close IPv6 classification gaps and guard the analyzer HTTP clients

Classification fixes in pkg/ssrf, each pinned by a test:
- Block fec0::/10 (deprecated site-local, still internal scope on legacy
  gear), SIIT IPv4-translated ::ffff:0:0:0/96, and Teredo 2001::/32,
  which embed v4 targets that To4() does not normalize.
- Stop blanket-blocking the NAT64 well-known prefix 64:ff9b::/96.
  DNS64 resolvers synthesize it for every public IPv4-only endpoint, so
  blocking the whole prefix broke all guarded dials in IPv6-only
  networks. IsNonPublicIP now extracts the embedded v4 from the low 32
  bits and classifies that instead, so 64:ff9b::a00:1 (10.0.0.1) stays
  blocked while 64:ff9b::808:808 (8.8.8.8) is reachable. The RFC8215
  local-use prefix stays blanket-blocked since its embedding layout is
  operator-defined.

Analyzer client coverage: analyzers take their endpoints from scanned
content (a secret's domain, a connection string), but the clients built
in pkg/analyzer/analyzers used bare http.DefaultTransport. They now
build on a guarded transport behind an opt-in SetEgressRestriction
toggle, default off so the CLI and self-hosted behavior is unchanged.
This covers NewAnalyzeClient, NewAnalyzeClientUnrestricted, the
rate-limiter fallback transport, and HttpStatusTest.RunTest's bare
client.
Brings the fork up from v3.95.2 to v3.98.0 (234 upstream commits).
Two conflicts, both resolved by keeping both sides:
- main.go: our --header setup and upstream's new
  --drop-unverified-jwt-results flag sit next to each other.
- pkg/feature/feature.go: upstream's new feature flags plus our
  CustomHeaders field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Upstream now enforces errcheck and the go-re2 import rule. Both hits were
in our own header test files. Also gofmt the header map alignment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@infraguard-web
infraguard-web merged commit 3ab74d9 into main Oct 8, 2026
10 checks passed
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.