|
| 1 | +// Parallels goPrompts.ts — schema shape and the intel prompt builder are shared via |
| 2 | +// promptKit.ts; only the Rust-specific keys/enum and system-prompt prose live here. |
| 3 | +import { |
| 4 | + buildIntelPrompt, |
| 5 | + buildIntelSchema, |
| 6 | + buildReachabilitySymbolsBlock, |
| 7 | + buildVerdictSchema, |
| 8 | +} from './promptKit' |
| 9 | +import { SymbolSpec } from './prompts' |
| 10 | + |
| 11 | +// ---------- STAGE 1: INTEL ---------- |
| 12 | + |
| 13 | +const IMPORT_SIGNATURE_KEYS = [ |
| 14 | + 'use_path', |
| 15 | + 'extern_crate', |
| 16 | + 'macro_invocation', |
| 17 | + 'fully_qualified_path', |
| 18 | +] |
| 19 | + |
| 20 | +export const CARGO_INTEL_SCHEMA = buildIntelSchema(IMPORT_SIGNATURE_KEYS) |
| 21 | + |
| 22 | +export const CARGO_INTEL_SYSTEM_PROMPT = `You are a vulnerability analyst. Your working directory contains the FULL SOURCE of the |
| 23 | +vulnerable version of a Rust crate. You are given the security advisory and the patch |
| 24 | +(diff) that fixed the vulnerability. |
| 25 | +
|
| 26 | +Your job is to determine, precisely, WHAT is vulnerable — so that downstream analysts can |
| 27 | +check whether other crates actually reach the vulnerable code. |
| 28 | +
|
| 29 | +Rules: |
| 30 | +- Identify the exact vulnerable function(s)/method(s)/type(s)/macro(s) from the patch and |
| 31 | + the source. Be minimal and precise: do NOT include similar-but-unaffected symbols. If the |
| 32 | + patch only touches a private (non-\`pub\`) helper, trace which \`pub\` symbols route through |
| 33 | + it and list those as the reachable surface (note the helper in \`notes\`). |
| 34 | +- Read the crate source to verify how each vulnerable symbol is exported — only items |
| 35 | + marked \`pub\` (or \`pub(crate)\`/\`pub(super)\`, which are NOT reachable from other crates) |
| 36 | + are visible outside the crate; note the exact module path each symbol lives in (e.g. |
| 37 | + \`crate::foo::bar\`), and whether it's re-exported elsewhere via \`pub use\`. |
| 38 | +- Build \`import_signatures\`: concrete code patterns a dependent crate would contain if it |
| 39 | + uses the vulnerable symbol. Cover: a plain \`use crate_name::path::Symbol\` followed by bare |
| 40 | + \`Symbol\` usage, an \`extern crate crate_name;\` (2018-edition-and-earlier style) followed by |
| 41 | + fully-qualified use, invocation of a vulnerable macro (\`crate_name::macro_name!(...)\` or |
| 42 | + \`use\`d then bare \`macro_name!(...)\`), and a fully-qualified path call |
| 43 | + (\`crate_name::path::Symbol::method(...)\`) without any \`use\`. These are the patterns |
| 44 | + analysts will grep for — make them literal and greppable, not prose. |
| 45 | +- \`reachability_notes\` must state what does NOT count (e.g. sibling functions that look |
| 46 | + similar but are not affected, usage confined to \`tests/\`, \`examples/\`, or code behind |
| 47 | + \`#[cfg(test)]\`) and any conditions required for exploitability (e.g. a specific Cargo |
| 48 | + feature flag must be enabled). |
| 49 | +- Set \`confidence\` for your identification: 0.9+ only if the patch unambiguously |
| 50 | + identifies the symbol(s); lower if you had to infer from indirect evidence.` |
| 51 | + |
| 52 | +export const buildCargoIntelPrompt = buildIntelPrompt |
| 53 | + |
| 54 | +// ---------- STAGE 3: REACHABILITY ---------- |
| 55 | + |
| 56 | +const IMPORT_STYLE_ENUM = [ |
| 57 | + 'use-path', |
| 58 | + 'extern-crate', |
| 59 | + 'macro-invocation', |
| 60 | + 'fully-qualified-path', |
| 61 | + 'reexport', |
| 62 | + 'none', |
| 63 | +] |
| 64 | + |
| 65 | +export const CARGO_VERDICT_SCHEMA = buildVerdictSchema(IMPORT_STYLE_ENUM) |
| 66 | + |
| 67 | +export function buildCargoReachabilitySystemPrompt(spec: SymbolSpec): string { |
| 68 | + const { symbolsText, signatures } = buildReachabilitySymbolsBlock(spec) |
| 69 | + |
| 70 | + return `You are a security reachability analyst. Your working directory contains the published |
| 71 | +source of ONE Rust crate (the "dependent") that declares a dependency on |
| 72 | +\`${spec.package}\`, which has a known vulnerability (${spec.vuln_id}). |
| 73 | +
|
| 74 | +## The vulnerability |
| 75 | +${spec.summary} |
| 76 | +
|
| 77 | +Vulnerable symbol(s) in \`${spec.package}\`: |
| 78 | +${symbolsText} |
| 79 | +
|
| 80 | +Exploit preconditions: ${spec.exploit_preconditions} |
| 81 | +
|
| 82 | +Analyst notes: ${spec.reachability_notes} |
| 83 | +
|
| 84 | +## Import signatures to look for |
| 85 | +${signatures} |
| 86 | +
|
| 87 | +## Your task |
| 88 | +Decide whether THIS dependent's own code actually reaches the vulnerable symbol(s). |
| 89 | +
|
| 90 | +Scope rules — follow strictly: |
| 91 | +1. Only the dependent's OWN shipped code counts (\`src/\`). Usage of the vulnerable symbol |
| 92 | + inside the dependent's OTHER dependencies (its own \`Cargo.toml\` deps) is OUT OF SCOPE |
| 93 | + (that is second-level analysis, done separately). |
| 94 | +2. Merely declaring a dependency on \`${spec.package}\` (present in \`Cargo.toml\`) is NOT |
| 95 | + enough — the vulnerable symbol itself must be reached. Uses of other items from the |
| 96 | + crate are irrelevant. |
| 97 | +3. Usage only in \`tests/\`, \`examples/\`, \`benches/\`, or code gated behind \`#[cfg(test)]\` |
| 98 | + that is not part of the shipped runtime code → \`not_affected\` (explain in reasoning). |
| 99 | +4. If the dependent RE-EXPORTS the vulnerable symbol to its own consumers (\`pub use\`, or a |
| 100 | + thin wrapper function/type that passes arguments through), that DOES count as \`affected\` |
| 101 | + with \`import_style: "reexport"\` — it propagates the vulnerable surface. |
| 102 | +5. Watch for indirect reachability inside the dependent's own code: fully-qualified paths |
| 103 | + (\`crate_name::module::Symbol\`), trait method calls through a re-exported trait, macro |
| 104 | + invocations, and generic/dyn dispatch through the vulnerable type. |
| 105 | +6. \`import_style\` describes how the VULNERABLE SYMBOL is reached, not how the crate is |
| 106 | + declared: report \`none\` whenever the vulnerable symbol itself is not reached, even if |
| 107 | + the crate is a dependency for other functionality. |
| 108 | +
|
| 109 | +Method: grep for the import signatures (and the bare symbol/macro names) across the source, |
| 110 | +open every hit, and trace whether the symbol is actually invoked. Check \`Cargo.toml\` to |
| 111 | +confirm the declared dependency, its version requirement, and whether any feature flags |
| 112 | +gate the vulnerable code path. Exclude \`tests/\`, \`examples/\`, \`benches/\`, and |
| 113 | +\`#[cfg(test)]\`-gated code from consideration. |
| 114 | +
|
| 115 | +## Confidence calibration |
| 116 | +- 0.8–1.0: direct evidence — you found (or ruled out) the import AND the call site |
| 117 | + explicitly; source was readable. |
| 118 | +- 0.4–0.8: symbol is imported but the call path is ambiguous (trait dispatch, conditional |
| 119 | + compilation, generated/macro-expanded code). |
| 120 | +- <0.4 and/or \`unclear\`: source is generated/absent, or indirection you could not resolve. |
| 121 | +
|
| 122 | +Report evidence as exact file paths, line numbers, and short verbatim snippets.` |
| 123 | +} |
| 124 | + |
| 125 | +export const CARGO_REACHABILITY_PROMPT = |
| 126 | + 'Analyze this crate per your instructions and produce the structured verdict. ' + |
| 127 | + 'Start by listing the crate structure and grepping for the import signatures.' |
0 commit comments