TavernKeeper Scan Report

Sillyanonymous/SillyTavern-CharacterLibrary

Commit 5224eb7 Reviewed

No material or immediate-danger concern was identified in this review.

This advisory report describes what the named tools and review process found at one exact commit. Unknown or unobserved behavior may still exist.

0 immediate danger 0 material 14 low

What this review found

No material or immediate-danger item was identified.

Minor cautions

Gitleaks reported generic-api-key

Minor caution · high confidence

The flagged value is a search key for a public character-card website. The extension normally grabs the current key from that website's own public code and only uses this built-in copy as a backup if that fails. It is not your personal password or a secret key for a paid service. The only downside is that if the website changes its key, this backup copy stops working.

Technical evidence

Scanner reason: Gitleaks matched secret-detection rule generic-api-key in this repository.

Contextual assessment: Line 13 contains a hardcoded MeiliSearch search token used as a fallback for querying JannyAI's public character database. The getSearchToken function (lines 43-53) attempts to scrape the live token from JannyAI's public client-side JavaScript bundle, falling back to this constant only if scraping fails. This token is not a user credential or a paid-service API key; it is a public search token that JannyAI's own website exposes in client-side code. The data flow sends this token only to JannyAI's search endpoint to browse publicly available character cards, which matches the project's stated purpose of discovering and downloading characters from online providers. The weakness is that hardcoding the token makes it brittle if JannyAI rotates keys, and it embeds a third-party credential in source. No exfiltration of user data, no concealed execution, and no credential theft is present.

Impact: low · Exploitability: unlikely

Developer action: Consider removing the hardcoded fallback token and instead surface a clear error prompting the user to retry when the live token scrape fails, so the extension does not ship a stale third-party credential.

Scanner
gitleaks 8.30.1
Rule
generic-api-key
File role
production
Source
modules/providers/janny/janny-api.js:13
Expected scanner matches (12)

OpenGrep reported tavernkeeper.credential-exfiltration.javascript-secret-to-network

Expected behavior · high confidence

This code checks whether the browser it just started is up and running by asking it for its version number over a local-only connection. No passwords or login data are sent anywhere. The security scanner flagged it because the file also deals with a browser that has login sessions, but the specific line in question only reads the browser's version locally.

Technical evidence

Scanner reason: OpenGrep matched static-analysis rule tavernkeeper.credential-exfiltration.javascript-secret-to-network in this repository.

Contextual assessment: The flagged fetch on line 241 targets the local Chrome DevTools Protocol version endpoint at 127.0.0.1 on a local port. It reads browser metadata (version string, user-agent) to confirm the headless browser launched successfully. No credentials, tokens, or session data are included in this request. The scanner matched because credential-adjacent context (a browser profile containing JanitorAI session cookies) and a network call coexist in the same file, but the actual data flow is a loopback health check with no secret material transmitted.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
opengrep 1.26.0
Rule
tavernkeeper.credential-exfiltration.javascript-secret-to-network
File role
production
Source
extras/janitorai-browser/run-browser.mjs:241

Credential access and network transmission in one file

Expected behavior · high confidence

The extension grabs a security token that SillyTavern itself provides and uses it only when talking back to SillyTavern's own server to update a character's avatar. The token is never sent anywhere else. This is normal, expected behavior for an extension that manages character images.

Technical evidence

Scanner reason: A credential source and an outbound network operation were detected in the same file.

Contextual assessment: The flagged code is in handleApplyAvatar, which fetches an image from a version-history avatar URL and then POSTs it to the local SillyTavern endpoint /api/characters/edit-avatar. The CSRF token obtained via CoreAPI.getCSRFToken() is included only in the X-CSRF-Token header of that same-origin request. No credential is transmitted to any external or third-party destination. This is the standard SillyTavern extension pattern for authenticated local API calls and matches the project's stated purpose of managing character avatars and version history.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
tavernkeeper 3
Rule
credential-exfiltration
File role
production
Source
modules/character-versions.js:1467

Gitleaks reported generic-api-key

Expected behavior · high confidence

The scanner flagged a setting name that happens to contain the letters 'Api' and looks like a key string. It is actually just the label for a checkbox that lets the user choose whether to use a newer API version for card updates. No password, token, or secret is exposed here.

Technical evidence

Scanner reason: Gitleaks matched secret-detection rule generic-api-key in this repository.

Contextual assessment: The gitleaks generic-api-key rule matched the string 'chubUseV4Api' on line 579. This is not a credential; it is a configuration key name for a boolean checkbox setting that toggles whether the extension uses the V4 Git API for card updates. The surrounding code defines a settings schema object with key, label, type, defaultValue, hint, and section fields. The defaultValue is false and the type is checkbox, confirming this is a UI toggle, not a secret. The actual authentication token field ('chubToken') is a password-type setting with a null default, meaning the user supplies it at runtime; no hardcoded credential is present.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
gitleaks 8.30.1
Rule
generic-api-key
File role
production
Source
modules/providers/chub/chub-provider.js:579

Credential access and network transmission in one file

Expected behavior · high confidence

This code restores character avatars by downloading images from remote URLs and uploading them to the local SillyTavern server. The security token it uses is only sent to the local SillyTavern server itself, not to any outside service. The other token is just used to cancel an in-progress operation. Nothing is being stolen or sent to an attacker.

Technical evidence

Scanner reason: A credential source and an outbound network operation were detected in the same file.

Contextual assessment: The scanner flagged co-occurrence of a credential source and a network sink. Examining the actual data flow: the redacted value on line 302 is an operation-cancellation token compared against opToken on lines 314 and 323, not a sensitive credential. The CSRF token retrieved via CoreAPI.getCSRFToken() on line 332 is sent only to the same-origin local SillyTavern API endpoint /api/characters/edit-avatar, which is the standard authenticated path for extensions modifying character avatars. The remote fetch on line 320 retrieves avatar image bytes from a user-selected remote URL and uploads them to the local server. No credential is transmitted to any external destination; the CSRF token stays same-origin and the cancellation token never leaves the browser.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
tavernkeeper 3
Rule
credential-exfiltration
File role
production
Source
modules/providers/datacat/datacat-avatar-restore.js:330

Credential access and network transmission in one file

Expected behavior · high confidence

Detailed wording was omitted by the public report safety filter.

Technical evidence

Scanner reason: A credential source and an outbound network operation were detected in the same file.

Contextual assessment: Detailed technical wording was omitted by the public report safety filter.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
tavernkeeper 3
Rule
credential-exfiltration
File role
production
Source
modules/batch-transfer.js:893

Gitleaks reported jwt

Expected behavior · high confidence

This is a public key meant to be included in client-side code, similar to how a website includes a public API identifier. It is not a private password or secret token. The scanner flagged it because it looks like a JWT, but this type of key is intentionally safe to ship.

Technical evidence

Scanner reason: Gitleaks matched secret-detection rule jwt in this repository.

Contextual assessment: The flagged value is a Supabase GoTrue anon/publishable key used as the apikey and Bearer header for JanitorAI authentication requests. Supabase anon keys are designed to be embedded in client code and enforce row-level security server-side rather than relying on secrecy. The key is used only to authenticate requests to the public Supabase auth endpoint and does not grant privileged access by itself. No user credentials, secrets, or tokens are hardcoded alongside it.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
gitleaks 8.30.1
Rule
jwt
File role
production
Source
modules/providers/janitor-session.js:6

Credential access and network transmission in one file

Expected behavior · high confidence

When saving a character with a changed avatar, the extension sends the new avatar image to SillyTavern's own server using a security token that SillyTavern itself provides. This is the normal, expected way to save character data. No credentials are sent anywhere outside your SillyTavern installation.

Technical evidence

Scanner reason: A credential source and an outbound network operation were detected in the same file.

Contextual assessment: The flagged code retrieves a CSRF token via CoreAPI.getCSRFToken() and includes it in an X-CSRF-Token header on a POST request to a relative same-origin endpoint (/api/characters/edit-avatar). The request body is FormData containing a locally-generated avatar PNG and the target avatar filename. This is the standard SillyTavern pattern for saving character card avatars to the local SillyTavern server. The CSRF token is a same-origin session protection token, not a model-provider API key or user credential. The destination is a relative path, so data stays within the SillyTavern instance. No external domain, no obfuscation, and the operation matches the extension's stated purpose of editing and saving characters.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
tavernkeeper 3
Rule
credential-exfiltration
File role
production
Source
modules/character-creator.js:3354

Credential access and network transmission in one file

Expected behavior · high confidence

The extension fetches a security token that SillyTavern itself provides and uses it to ask the local SillyTavern server for a list of images in a character's gallery folder. This is a normal, expected way for an extension to talk to SillyTavern's own APIs. The token stays on the local server and is never sent anywhere outside.

Technical evidence

Scanner reason: A credential source and an outbound network operation were detected in the same file.

Contextual assessment: The flagged code retrieves a CSRF token via getCsrfToken and includes it in an X-CSRF-Token header on a fetch to the relative endpoint /api/images/list. This is a same-origin request to the local SillyTavern server, used to list files in a character gallery folder. The CSRF token is consumed locally for its intended authentication purpose and is not transmitted to any external destination. The function buildChatMediaLocalizationMap builds URL-to-local-path mappings for character media, which aligns with the extension's stated gallery and media management features. No credential exfiltration, external endpoint, obfuscation, or unexpected data flow is present.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
tavernkeeper 3
Rule
credential-exfiltration
File role
production
Source
index.js:1387

Credential access and network transmission in one file

Expected behavior · high confidence

The scanner noticed that this file both handles a logged-in browser and makes a network call, which can look suspicious. However, the network call is just a local check asking the browser for its version number. No login information is sent through this call. This is a normal part of confirming the browser started correctly.

Technical evidence

Scanner reason: A credential source and an outbound network operation were detected in the same file.

Contextual assessment: This candidate flags the same line 241 fetch to the local CDP version endpoint. The file does spawn a browser with a user profile that holds JanitorAI session cookies, and it does open a relay server, but the specific network sink on line 241 carries only a GET request to the local debugging port's version endpoint. No credential material is placed into the request body, headers, or URL. The co-occurrence of credential-adjacent state and a network call in one file is a false positive for exfiltration because the data flow does not connect secrets to the outbound request.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
tavernkeeper 3
Rule
credential-exfiltration
File role
production
Source
extras/janitorai-browser/run-browser.mjs:241

Gitleaks reported jwt

Expected behavior · high confidence

The scanner flagged a value that looks like a security token. It is actually a public key that JanitorAI intentionally ships in its own website code for use by client-side apps. It is not a private password or secret, and embedding it here is the intended use.

Technical evidence

Scanner reason: Gitleaks matched secret-detection rule jwt in this repository.

Contextual assessment: The gitleaks JWT pattern matched a Supabase anon publishable key assigned to JANITORAI_ANON_KEY. Supabase anon keys are designed to be embedded in client-side code and carry the role:anon privilege level, not a private secret. The surrounding code and comments confirm this is JanitorAI's public publishable key, used as an apikey header for Supabase GoTrue auth endpoints. The matched value was redacted by the scanner, so no live credential is exposed in this evidence. No private secret, service-role key, or user credential is present.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
gitleaks 8.30.1
Rule
jwt
File role
production
Source
modules/providers/datacat/datacat-api.js:272

Gitleaks reported gcp-api-key

Expected behavior · high confidence

This is a public Firebase key used to let the extension log into the Wyvern character service. Firebase keys like this are meant to be visible in app code and are not passwords. Security is handled by the service itself, not by hiding this key.

Technical evidence

Scanner reason: Gitleaks matched secret-detection rule gcp-api-key in this repository.

Contextual assessment: The matched value is a Firebase Web API key embedded in client-side code for authenticating against Firebase Identity Toolkit and Secure Token endpoints associated with the Wyvern chat service. Firebase Web API keys are public identifiers designed to be shipped in client applications; they are not secret credentials. Firebase access control is enforced server-side via Firebase Security Rules and authenticated token validation, not by keeping this key private. The key is used solely to construct authentication request URLs for the stated provider integration, which aligns with the project's purpose of browsing and downloading characters from online providers.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
gitleaks 8.30.1
Rule
gcp-api-key
File role
production
Source
modules/providers/wyvern/wyvern-api.js:17

Credential access and network transmission in one file

Expected behavior · high confidence

This code uploads character images to the user's own SillyTavern server. It uses a standard security token (CSRF token) to prove the request is legitimate, which is normal and required for SillyTavern's own API. No credentials are being sent anywhere outside the local server. This is exactly what a character media management extension should do.

Technical evidence

Scanner reason: A credential source and an outbound network operation were detected in the same file.

Contextual assessment: The flagged code is a media-upload routine that converts downloaded media to base64, builds a JSON body with image data, filename, format, and folder name, retrieves a CSRF token via getCSRFToken, and POSTs to the local SillyTavern image-upload endpoint. The CSRF token is used in the standard X-CSRF-Token header for same-origin authenticated requests to the SillyTavern backend. There is no indication the token or any other credential is transmitted to an external destination. The data sent is the media payload and metadata, which matches the extension's stated purpose of downloading and managing embedded character media. The co-location of a credential source and a network call in the same file is expected for any authenticated local API interaction.

Impact: none · Exploitability: unlikely

Developer action: none

Scanner
tavernkeeper 3
Rule
credential-exfiltration
File role
production
Source
app/library.js:23016

Related contextual observations

Unauthenticated CDP relay bound to all interfaces when not restricted to loopback

low risk · medium confidence

When this tool is set to be reachable from other computers on the network, there is no password on the connection. That means anyone on the same network could control the browser and see its JanitorAI login. The tool does warn about this, which is good, but adding a password or defaulting to local-only would be safer.

Technical assessment

Lines 275 through 279 show the code warns the user when the relay is bound to all interfaces rather than loopback, because the CDP endpoint has no authentication and anyone on the LAN could drive the logged-in browser and read its JanitorAI session. The warning is appropriate and the default appears to favor loopback, but the relay still permits binding to all interfaces without requiring authentication, which is a design weakness if a user runs it on an untrusted network. The developer already discloses this risk in console output, which limits the severity.

Impact: medium · Exploitability: plausible

Developer action: Consider defaulting the bind address to loopback and requiring an explicit opt-in for LAN exposure, or add a simple authentication token to the relay endpoint.

Sources:

Coverage and limitations

Tools

Limitations

Technical scan identity