← All finding types

secret_in_llm_prompt

CWE-200

Secret In Llm Prompt — a PullGuard finding type. Findings of this type appear in the PR comment, Step Summary, SARIF (GitHub Security tab / IDE viewers), and the HTML report, each with severity, location, and the remediation guidance below.

How to fix

Remove the secret/PII from prompt content — secrets belong in the SDK auth config only low effort

// Before (VULNERABLE): the credential becomes provider-visible prompt data
const prompt = `Connect with key ${process.env.DB_API_KEY} and summarise`; 
await openai.chat.completions.create({ messages: [{ role: "user", content: prompt }] });

// After (SAFE): the model never needs the credential — do the privileged
// work app-side and prompt with the RESULT
const rows = await db.query(summaryQuery); // app holds the credential
await openai.chat.completions.create({ messages: [{ role: "user", content: `Summarise: ${JSON.stringify(rows)}` }] });

Redact or tokenise PII before prompting; re-substitute after the response medium effort

// WHY: the provider may retain/log prompt content — send placeholders,
// keep the mapping app-side.
const redacted = redactPii(record);            // "SSN: <SSN_1>"
const answer = await llm.invoke(buildPrompt(redacted.text));
return redacted.restore(answer);               // re-substitute locally

Triage

Suppress a confirmed non-issue with a committed .pullguardignore entry (pullguard ignore locally, or comment /pullguard ignore <fingerprint> <reason> on the PR — the fingerprint is printed in the PR comment’s Triage section). Entries support expiresAt for time-boxed snoozes.

Security findings at major or critical severity — and any critical finding — always surface: .pullguardignore cannot hide them. The reviewed paths that keep them visible are acknowledged (reviewed, stays in reports) and, for a confirmed false positive, a reasoned false_positive entry — visible and audited, excluded only from the merge block.